mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH] PC-9800 additional for 2.5.61-ac1 (0/21) summary
@ 2003-02-20 12:16 Osamu Tomita
  2003-02-20 12:22 ` [PATCH] PC-9800 additional for 2.5.61-ac1 (1/21) ALSA Osamu Tomita
                   ` (19 more replies)
  0 siblings, 20 replies; 21+ messages in thread
From: Osamu Tomita @ 2003-02-20 12:16 UTC (permalink / raw)
  To: Linux Kernel Mailing List; +Cc: Alan Cox

This is additional patch to support NEC PC-9800 subarchitecture
against 2.5.61-ac1.
All patches must aplly after updating files in 2.5.61-ac1 by patch
previously posted.
Sorry, scsi.patch is now working. I'll post it later.

Comments and test reports are wellcome.

Description:
 o alsa-pc98.patch (1/21)
   ALSA sound drivers for PC98.
 o apm.patch (2/21)
   APM support for PC98. Including PC98's BIOS bug fix.
 o console.patch (3/21)
   PC98 Standard console support (without japanese kanji character).
 o core-misc.patch (4/21)
   Small core patches for PC98.
 o dma.patch (5/21)
   DMA support for PC98.
 o fs.patch (6/21)
   FAT fs and partition table support for PC98.
 o ide.patch (7/21)
   PC98 standard IDE I/F support.
 o kanji.patch (8/21)
   japanese kanji character support for PC98 console.
 o kconfig.patch (9/21)
   Add selection CONFIG_X86_PC9800.
 o network_card.patch (10/21)
   C-bus(PC98's legacy bus like ISA) network cards support.
 o parport.patch (11/21)
   Parallel port support.
 o pci.patch (12/21)
   Small changes for PCI support.
 o pcmcia.patch (13/21)
   Small change for PCMCIA (16bits) support.
 o pnp.patch (14/21)
   Small change for Legacy bus PNP support.
 o rtc.patch (15/21)
   Support RTC for PC98, using mach-* scheme.
 o scsi.patch (16/21)
   SCSI host adapter support.
 o serial.patch (17/21)
   Serial port support for PC98.
 o setup.patch (18/21)
   Support difference of IO port/memory address, using mach-* scheme.
 o smp.patch (19/21)
   SMP support for PC98.
 o timer.patch (20/21)
   Support difference of timer, using mach-* scheme.
 o traps.patch (21/21)
   Support difference of NMI handling, using mach-* scheme.

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH] PC-9800 additional for 2.5.61-ac1 (1/21) ALSA
  2003-02-20 12:16 [PATCH] PC-9800 additional for 2.5.61-ac1 (0/21) summary Osamu Tomita
@ 2003-02-20 12:22 ` Osamu Tomita
  2003-02-20 12:22 ` [PATCH] PC-9800 additional for 2.5.61-ac1 (2/21) APM Osamu Tomita
                   ` (18 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Osamu Tomita @ 2003-02-20 12:22 UTC (permalink / raw)
  To: Linux Kernel Mailing List; +Cc: Alan Cox

This is additional patch to support NEC PC-9800 subarchitecture
against 2.5.61-ac1. (1/21)

ALSA sound drivers for PC98.

diff -Nru linux/sound/isa/Kconfig linux98/sound/isa/Kconfig
--- linux/sound/isa/Kconfig	2002-10-31 13:23:47.000000000 +0900
+++ linux98/sound/isa/Kconfig	2002-11-02 15:56:59.000000000 +0900
@@ -39,6 +39,12 @@
 	  Say 'Y' or 'M' to include support for CS4235,CS4236,CS4237B,CS4238B,CS4239
 	  chips from Cirrus Logic - Crystal Semiconductors.
 
+config SND_PC98_CS4232
+	tristate "NEC PC9800 CS4232 driver"
+	depends on SND
+	help
+	  Say 'Y' or 'M' to include support for NEC PC-9801/PC-9821 sound cards
+
 config SND_ES968
 	tristate "Generic ESS ES968 driver"
 	depends on SND && ISAPNP
diff -Nru linux-2.5.60/sound/isa/cs423x/Makefile linux98-2.5.60/sound/isa/cs423x/Makefile
--- linux-2.5.60/sound/isa/cs423x/Makefile	2003-02-11 03:38:51.000000000 +0900
+++ linux98-2.5.60/sound/isa/cs423x/Makefile	2003-02-11 10:26:12.000000000 +0900
@@ -8,6 +8,7 @@
 snd-cs4231-objs := cs4231.o
 snd-cs4232-objs := cs4232.o
 snd-cs4236-objs := cs4236.o
+snd-pc98-cs4232-objs := pc98.o
 
 # Toplevel Module Dependency
 obj-$(CONFIG_SND_AZT2320) += snd-cs4231-lib.o
@@ -20,5 +21,6 @@
 obj-$(CONFIG_SND_INTERWAVE_STB) += snd-cs4231-lib.o
 obj-$(CONFIG_SND_OPTI92X_CS4231) += snd-cs4231-lib.o
 obj-$(CONFIG_SND_WAVEFRONT) += snd-cs4231-lib.o
+obj-$(CONFIG_SND_PC98_CS4232) += snd-pc98-cs4232.o snd-cs4231-lib.o
 
 obj-m := $(sort $(obj-m))
diff -Nru linux/sound/isa/cs423x/pc98.c linux98/sound/isa/cs423x/pc98.c
--- linux/sound/isa/cs423x/pc98.c	1970-01-01 09:00:00.000000000 +0900
+++ linux98/sound/isa/cs423x/pc98.c	2002-11-01 11:37:22.000000000 +0900
@@ -0,0 +1,466 @@
+/*
+ *  Driver for CS4232 on NEC PC9800 series
+ *  Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ *                   Osamu Tomita <tomita@cinet.co.jp>
+ *                   Takashi Iwai <tiwai@suse.de>
+ *
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#include <sound/driver.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/cs4231.h>
+#include <sound/mpu401.h>
+#include <sound/opl3.h>
+#define SNDRV_GET_ID
+#include <sound/initval.h>
+#include "sound_pc9800.h"
+
+#define chip_t cs4231_t
+
+MODULE_AUTHOR("Osamu Tomita <tomita@cinet.co.jp>");
+MODULE_LICENSE("GPL");
+MODULE_CLASSES("{sound}");
+MODULE_DESCRIPTION("NEC PC9800 CS4232");
+MODULE_DEVICES("{{NEC,PC9800}}");
+
+#define IDENT "PC98-CS4232"
+
+static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
+static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
+static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_ISAPNP; /* Enable this card */
+static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;	/* PnP setup */
+#if 0 /* NOT USED */
+static long cport[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;	/* PnP setup */
+#endif
+static long mpu_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;/* PnP setup */
+static long fm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;	/* PnP setup */
+static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;	/* 5,7,9,11,12,15 */
+static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;	/* 9,11,12,15 */
+static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA;	/* 0,1,3,5,6,7 */
+static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA;	/* 0,1,3,5,6,7 */
+static int pc98ii[SNDRV_CARDS];				/* PC98II */
+
+MODULE_PARM(index, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
+MODULE_PARM_DESC(index, "Index value for " IDENT " soundcard.");
+MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
+MODULE_PARM(id, "1-" __MODULE_STRING(SNDRV_CARDS) "s");
+MODULE_PARM_DESC(id, "ID string for " IDENT " soundcard.");
+MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
+MODULE_PARM(enable, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
+MODULE_PARM_DESC(enable, "Enable " IDENT " soundcard.");
+MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
+MODULE_PARM(port, "1-" __MODULE_STRING(SNDRV_CARDS) "l");
+MODULE_PARM_DESC(port, "Port # for " IDENT " driver.");
+MODULE_PARM_SYNTAX(port, SNDRV_PORT12_DESC);
+#if 0 /* NOT USED */
+MODULE_PARM(cport, "1-" __MODULE_STRING(SNDRV_CARDS) "l");
+MODULE_PARM_DESC(cport, "Control port # for " IDENT " driver.");
+MODULE_PARM_SYNTAX(cport, SNDRV_PORT12_DESC);
+#endif
+MODULE_PARM(mpu_port, "1-" __MODULE_STRING(SNDRV_CARDS) "l");
+MODULE_PARM_DESC(mpu_port, "MPU-401 port # for " IDENT " driver.");
+MODULE_PARM_SYNTAX(mpu_port, SNDRV_PORT12_DESC);
+MODULE_PARM(fm_port, "1-" __MODULE_STRING(SNDRV_CARDS) "l");
+MODULE_PARM_DESC(fm_port, "FM port # for " IDENT " driver.");
+MODULE_PARM_SYNTAX(fm_port, SNDRV_PORT12_DESC);
+MODULE_PARM(irq, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
+MODULE_PARM_DESC(irq, "IRQ # for " IDENT " driver.");
+MODULE_PARM_SYNTAX(irq, SNDRV_IRQ_DESC);
+MODULE_PARM(mpu_irq, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
+MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for " IDENT " driver.");
+MODULE_PARM_SYNTAX(mpu_irq, SNDRV_IRQ_DESC);
+MODULE_PARM(dma1, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
+MODULE_PARM_DESC(dma1, "DMA1 # for " IDENT " driver.");
+MODULE_PARM_SYNTAX(dma1, SNDRV_DMA_DESC);
+MODULE_PARM(dma2, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
+MODULE_PARM_DESC(dma2, "DMA2 # for " IDENT " driver.");
+MODULE_PARM_SYNTAX(dma2, SNDRV_DMA_DESC);
+MODULE_PARM(pc98ii, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
+MODULE_PARM_DESC(pc98ii, "Roland MPU-PC98II support.");
+MODULE_PARM_SYNTAX(pc98ii, SNDRV_BOOLEAN_FALSE_DESC);
+
+
+static snd_card_t *snd_pc98_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
+
+/*
+ * initialize MPU401-UART
+ */
+
+static int __init pc98_mpu401_init(int irq)
+{
+#include "pc9801_118_magic.h"
+#define outp118(reg,data) outb((reg),0x148e);outb((data),0x148f)
+#define WAIT118 outb(0x00,0x5f)
+	int	mpu_intr, count;
+#ifdef OOKUBO_ORIGINAL
+	int	err = 0;
+#endif /* OOKUBO_ORIGINAL */
+
+	switch (irq) {
+	case 3:
+		mpu_intr = 3;
+		break;
+	case 5:
+		mpu_intr = 2;
+		break;
+	case 6:
+		mpu_intr = 1;
+		break;
+	case 10:
+		mpu_intr = 0;
+		break;
+	default:
+		snd_printk(KERN_ERR IDENT ": Bad IRQ %d\n", irq);
+		return -EINVAL;
+	}
+
+	outp118(0x21, mpu_intr);
+	WAIT118;
+	outb(0x00, 0x148e);
+	if (inb(0x148f) & 0x08) {
+		snd_printk(KERN_INFO IDENT ": No MIDI daughter board found\n");
+		return 0;
+	}
+
+	outp118(0x20, 0x00);
+	outp118(0x05, 0x04);
+	for (count = 0; count < 35000; count ++)
+		WAIT118;
+	outb(0x05, 0x148e);
+	for (count = 0; count < 65000; count ++)
+		if (inb(0x148f) == 0x04)
+			goto set_mode_118;
+	snd_printk(KERN_ERR IDENT ": MIDI daughter board initalize failed at stage1\n\n");
+	return -EINVAL;
+
+ set_mode_118:
+	outp118(0x05, 0x0c);
+	outb(0xaa, 0x485);
+	outb(0x99, 0x485);
+	outb(0x2a, 0x485);
+	for (count = 0; count < sizeof(Data0485_99); count ++) {
+		outb(Data0485_99[count], 0x485);
+		WAIT118;
+	}
+
+	outb(0x00, 0x486);
+	outb(0xaa, 0x485);
+	outb(0x9e, 0x485);
+	outb(0x2a, 0x485);
+	for (count = 0; count < sizeof(Data0485_9E); count ++)
+		if (inb(0x485) != Data0485_9E[count]) {
+#ifdef OOKUBO_ORIGINAL
+			err = 1;
+#endif /* OOKUBO_ORIGINAL */
+			break;
+		}
+	outb(0x00, 0x486);
+	for (count = 0; count < 2000; count ++)
+		WAIT118;
+#ifdef OOKUBO_ORIGINAL
+	if (!err) {
+		outb(0xaa, 0x485);
+		outb(0x36, 0x485);
+		outb(0x28, 0x485);
+		for (count = 0; count < sizeof(Data0485_36); count ++)
+			outb(Data0485_36[count], 0x485);
+		outb(0x00, 0x486);
+		for (count = 0; count < 1500; count ++)
+			WAIT118;
+		outp118(0x05, inb(0x148f) | 0x08);
+		outb(0xff, 0x148c);
+		outp118(0x05, inb(0x148f) & 0xf7);
+		for (count = 0; count < 1500; count ++)
+			WAIT118;
+	}
+#endif /* OOKUBO_ORIGINAL */
+
+	outb(0xaa, 0x485);
+	outb(0xa9, 0x485);
+	outb(0x21, 0x485);
+	for (count = 0; count < sizeof(Data0485_A9); count ++) {
+		outb(Data0485_A9[count], 0x485);
+		WAIT118;
+	}
+
+	outb(0x00, 0x486);
+	outb(0xaa, 0x485);
+	outb(0x0c, 0x485);
+	outb(0x20, 0x485);
+	for (count = 0; count < sizeof(Data0485_0C); count ++) {
+		outb(Data0485_0C[count], 0x485);
+		WAIT118;
+	}
+
+	outb(0x00, 0x486);
+	outb(0xaa, 0x485);
+	outb(0x66, 0x485);
+	outb(0x20, 0x485);
+	for (count = 0; count < sizeof(Data0485_66); count ++) {
+		outb(Data0485_66[count], 0x485);
+		WAIT118;
+	}
+
+	outb(0x00, 0x486);
+	outb(0xaa, 0x485);
+	outb(0x60, 0x485);
+	outb(0x20, 0x485);
+	for (count = 0; count < sizeof(Data0485_60); count ++) {
+		outb(Data0485_60[count], 0x485);
+		WAIT118;
+	}
+
+	outb(0x00, 0x486);
+	outp118(0x05, 0x04);
+	outp118(0x05, 0x00);
+	for (count = 0; count < 35000; count ++)
+		WAIT118;
+	outb(0x05, 0x148e);
+	for (count = 0; count < 65000; count ++)
+		if (inb(0x148f) == 0x00)
+			goto end_mode_118;
+	snd_printk(KERN_ERR IDENT ": MIDI daughter board initalize failed at stage2\n");
+	return -EINVAL;
+
+ end_mode_118:
+	outb(0x3f, 0x148d);
+	snd_printk(KERN_INFO IDENT ": MIDI daughter board initalized\n");
+	return 0;
+}
+
+static int __init pc98_cs4231_chip_init(int dev)
+{
+	int intr_bits, intr_bits2, dma_bits;
+
+	switch (irq[dev]) {
+	case 3:
+		intr_bits = 0x08;
+		intr_bits2 = 0x03;
+		break;
+	case 5:
+		intr_bits = 0x10;
+		intr_bits2 = 0x08;
+		break;
+	case 10:
+		intr_bits = 0x18;
+		intr_bits2 = 0x02;
+		break;
+	case 12:
+		intr_bits = 0x20;
+		intr_bits2 = 0x00;
+		break;
+	default:
+		snd_printk(KERN_ERR IDENT ": Bad IRQ %d\n", irq[dev]);
+		return -EINVAL;
+	}
+
+	switch (dma1[dev]) {
+	case 0:
+		dma_bits = 0x01;
+		break;
+	case 1:
+		dma_bits = 0x02;
+		break;
+	case 3:
+		dma_bits = 0x03;
+		break;
+	default:
+		snd_printk(KERN_ERR IDENT ": Bad DMA %d\n", dma1[dev]);
+		return -EINVAL;
+	}
+
+	if (dma2[dev] >= 2) {
+		snd_printk(KERN_ERR IDENT ": Bad DMA %d\n", dma2[dev]);
+		return -EINVAL;
+	}
+	if (dma1[dev] != dma2[dev] && dma2[dev] >= 0)
+		intr_bits |= 0x04;
+
+	if (PC9800_SOUND_ID() == PC9800_SOUND_ID_118) {
+		/* Set up CanBe control registers. */
+		snd_printd(KERN_INFO "Setting up CanBe Sound System\n");
+		outb(inb(PC9800_SOUND_IO_ID) | 0x03, PC9800_SOUND_IO_ID);
+		outb(0x01, 0x0f4a);
+		outb(intr_bits2, 0x0f4b);
+	}
+
+	outb(intr_bits | dma_bits, 0xf40);
+	return 0;
+}
+
+
+static int __init snd_card_pc98_probe(int dev)
+{
+	snd_card_t *card;
+	snd_pcm_t *pcm = NULL;
+	cs4231_t *chip;
+	opl3_t *opl3;
+	int err;
+
+	if (port[dev] == SNDRV_AUTO_PORT) {
+		snd_printk(KERN_ERR IDENT ": specify port\n");
+		return -EINVAL;
+	}
+	card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
+	if (card == NULL)
+		return -ENOMEM;
+	if (mpu_port[dev] < 0 || mpu_irq[dev] < 0)
+		mpu_port[dev] = SNDRV_AUTO_PORT;
+	if (fm_port[dev] < 0)
+		fm_port[dev] = SNDRV_AUTO_PORT;
+
+	if ((err = pc98_cs4231_chip_init(dev)) < 0) {
+		snd_card_free(card);
+		return err;
+	}
+
+	if ((err = snd_cs4231_create(card,
+				     port[dev],
+				     -1,
+				     irq[dev],
+				     dma1[dev],
+				     dma2[dev],
+				     CS4231_HW_DETECT,
+				     0,
+				     &chip)) < 0) {
+		snd_card_free(card);
+		return err;
+	}
+	if ((err = snd_cs4231_pcm(chip, 0, &pcm)) < 0) {
+		snd_card_free(card);
+		return err;
+	}
+	if ((err = snd_cs4231_mixer(chip)) < 0) {
+		snd_card_free(card);
+		return err;
+	}
+
+	if ((err = snd_cs4231_timer(chip, 0, NULL)) < 0) {
+		snd_card_free(card);
+		return err;
+	}
+
+	if (fm_port[dev] != SNDRV_AUTO_PORT) {
+		/* ??? */
+		outb(0x00, fm_port[dev] + 6);
+		inb(fm_port[dev] + 7);
+		/* Enable OPL-3 Function */
+		outb(inb(PC9800_SOUND_IO_ID) | 0x03, PC9800_SOUND_IO_ID);
+		if (snd_opl3_create(card,
+				    fm_port[dev], fm_port[dev] + 2,
+				    OPL3_HW_OPL3_PC98, 0, &opl3) < 0) {
+			printk(KERN_ERR IDENT ": OPL3 not detected\n");
+		} else {
+			if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) {
+				snd_card_free(card);
+				return err;
+			}
+		}
+	}
+
+	if (mpu_port[dev] != SNDRV_AUTO_PORT) {
+		err = pc98_mpu401_init(mpu_irq[dev]);
+		if (! err) {
+			err = snd_mpu401_uart_new(card, 0,
+						  pc98ii[dev] ? MPU401_HW_PC98II : MPU401_HW_MPU401,
+						  mpu_port[dev], 0,
+						  mpu_irq[dev], SA_INTERRUPT, NULL);
+			if (err < 0)
+				snd_printk(KERN_INFO IDENT ": MPU401 not detected\n");
+		}
+	}
+
+	strcpy(card->driver, pcm->name);
+	strcpy(card->shortname, pcm->name);
+	sprintf(card->longname, "%s at 0x%lx, irq %i, dma %i",
+		pcm->name,
+		chip->port,
+		irq[dev],
+		dma1[dev]);
+	if (dma1[dev] >= 0)
+		sprintf(card->longname + strlen(card->longname), "&%d", dma2[dev]);
+	if ((err = snd_card_register(card)) < 0) {
+		snd_card_free(card);
+		return err;
+	}
+	snd_pc98_cards[dev] = card;
+	return 0;
+}
+
+static int __init alsa_card_pc98_init(void)
+{
+	int dev, cards = 0;
+
+	for (dev = 0; dev < SNDRV_CARDS; dev++) {
+		if (!enable[dev])
+			continue;
+		if (snd_card_pc98_probe(dev) >= 0)
+			cards++;
+	}
+	if (!cards) {
+#ifdef MODULE
+		printk(KERN_ERR IDENT " soundcard not found or device busy\n");
+#endif
+		return -ENODEV;
+	}
+	return 0;
+}
+
+static void __exit alsa_card_pc98_exit(void)
+{
+	int idx;
+
+	for (idx = 0; idx < SNDRV_CARDS; idx++)
+		snd_card_free(snd_pc98_cards[idx]);
+}
+
+module_init(alsa_card_pc98_init)
+module_exit(alsa_card_pc98_exit)
+
+#ifndef MODULE
+
+/* format is: snd-pc98-cs4232=enable,index,id,port,
+			 mpu_port,fm_port,
+			 irq,mpu_irq,dma1,dma2,pc98ii */
+
+static int __init alsa_card_pc98_setup(char *str)
+{
+	static unsigned __initdata nr_dev = 0;
+
+	if (nr_dev >= SNDRV_CARDS)
+		return 0;
+	(void)(get_option(&str,&enable[nr_dev]) == 2 &&
+	       get_option(&str,&index[nr_dev]) == 2 &&
+	       get_id(&str,&id[nr_dev]) == 2 &&
+	       get_option(&str,(int *)&port[nr_dev]) == 2 &&
+	       get_option(&str,(int *)&mpu_port[nr_dev]) == 2 &&
+	       get_option(&str,(int *)&fm_port[nr_dev]) == 2 &&
+	       get_option(&str,&irq[nr_dev]) == 2 &&
+	       get_option(&str,&mpu_irq[nr_dev]) == 2 &&
+	       get_option(&str,&dma1[nr_dev]) == 2 &&
+	       get_option(&str,&dma2[nr_dev]) == 2 &&
+	       get_option(&str,&pc98ii[nr_dev]) == 2);
+	nr_dev++;
+	return 1;
+}
+
+__setup("snd-pc98-cs4232=", alsa_card_pc98_setup);
+
+#endif /* ifndef MODULE */
diff -Nru linux/sound/isa/cs423x/pc9801_118_magic.h linux/sound/isa/cs423x/pc9801_118_magic.h
--- linux/sound/isa/cs423x/pc9801_118_magic.h	1970-01-01 09:00:00.000000000 +0100
+++ linux/sound/isa/cs423x/pc9801_118_magic.h	2002-10-28 15:44:12.000000000 +0100
@@ -0,0 +1,411 @@
+		static unsigned char	Data0485_A9[] = {
+		0x12, 0x03, 0x90, 0xc2, 0x2a, 0x75, 0x1e, 0x20,
+		0xe4, 0x12, 0x2b, 0x9b, 0x22, 0xa9, 0x16, 0x77,
+		0x33, 0xe9, 0x04, 0x54, 0x03, 0x44, 0xa8, 0xf5,
+		0x16, 0xc2, 0x2f, 0x22, 0xa9, 0x16, 0x77, 0x42,
+		0xe9, 0x04, 0x54, 0x03, 0x44, 0xa8, 0xf9, 0x77,
+		0xf8, 0x04, 0x54, 0x03, 0x44, 0xa8, 0xf5, 0x16,
+		0xc2, 0x2f, 0x22, 0x90, 0x25, 0x9f, 0x30, 0x04,
+		0x05, 0xc2, 0x04, 0x12, 0x1f, 0x62, 0x30, 0x00,
+		0x05, 0xc2, 0x00, 0x12, 0x15, 0xe6, 0x30, 0x01,
+		0x05, 0xc2, 0x01, 0x12, 0x29, 0xaf, 0x30, 0x02,
+		0x05, 0xc2, 0x02, 0x12, 0x29, 0xaf, 0x30, 0x05,
+		0x05, 0xc2, 0x05, 0x12, 0x16, 0x65, 0x30, 0x06,
+		0x08, 0xc2, 0x06, 0x12, 0x16, 0xb1, 0x12, 0x29,
+		0xaf, 0x30, 0x07, 0x08, 0xc2, 0x07, 0x12, 0x16,
+		0xe9, 0x12, 0x29, 0xaf, 0x22, 0x20, 0x97, 0x09,
+		0x53, 0xa8, 0xfb, 0x12, 0x04, 0x2c, 0x43, 0xa8,
+		0x04, 0x22, 0x71, 0xb8, 0x71, 0xb8, 0x71, 0xb8,
+		0x22, 0x20, 0x4b, 0x04, 0x75, 0x4e, 0x02, 0x22,
+		0xe5, 0x35, 0x24, 0xff, 0xf5, 0x35, 0xe5, 0x36,
+		0x34, 0xff, 0xf5, 0x36, 0x75, 0x4e, 0x02, 0x22,
+		0x10, 0x19, 0x02, 0x80, 0x08, 0x78, 0x00, 0xe2,
+		0x78, 0x07, 0xf2, 0x61, 0x9b, 0x78, 0x11, 0xe2,
+		0xc0, 0x01, 0xc0, 0xf0, 0xc0, 0xd0, 0xc0, 0x02,
+		0x71, 0x14, 0xe5, 0x30, 0xb4, 0x01, 0x02, 0x61,
+		0x93, 0x43, 0x08, 0x40, 0x12, 0x2a, 0x53, 0x61,
+		0x93, 0x79, 0x03, 0xe3, 0xa2, 0xe2, 0x92, 0x26,
+		0xa2, 0xe3, 0x92, 0x27, 0x22, 0xad, 0x2b, 0xbd,
+		0x04, 0x07, 0xf5, 0x72, 0x78, 0x27, 0x02, 0x11,
+		0x76, 0x02, 0x11, 0x30, 0x00, 0x00, 0x00, 0x12,
+		0x28, 0xba, 0x79, 0x01, 0xe3, 0x75, 0x21, 0x3f,
+		0x75, 0x49, 0x11, 0x75, 0x4c, 0x11, 0x31, 0xdc,
+		0x75, 0x1a, 0x80, 0x51, 0x72, 0x75, 0x81, 0xe3,
+		0x12, 0x25, 0xc9, 0x43, 0xa8, 0x01, 0x00, 0x53,
+		0xa8, 0xfe, 0x10, 0x50, 0x02, 0x80, 0x03, 0x12,
+		0x1a, 0x8d, 0xd1, 0x28, 0x12, 0x03, 0xd9, 0xd1,
+		0xf2, 0x12, 0x2d, 0xf0, 0xb0, 0x11, 0x92, 0xe0,
+		0xa2, 0x2a, 0xa0, 0xb5, 0x82, 0xe0, 0x50, 0x03,
+		0x79, 0x0f, 0xe3, 0x71, 0xca, 0x51, 0x1e, 0x91,
+		0xe4, 0x53, 0xa8, 0xfb, 0x10, 0x10, 0x02, 0x80,
+		0x26, 0xc2, 0x8e, 0xd2, 0xab, 0xa2, 0x1c, 0x40,
+		0x13, 0xa2, 0x1d, 0x50, 0x0a, 0x43, 0x08, 0x40,
+		0x12, 0x1a, 0x01, 0xd1, 0xd7, 0x80, 0x0b, 0x12,
+		0x26, 0x04, 0x61, 0x08, 0x43, 0x08, 0x40, 0x12,
+		0x1a, 0x01, 0xd2, 0x1f, 0x12, 0x17, 0x7f, 0x43,
+		0xa8, 0x04, 0x51, 0x1e, 0x91, 0xe4, 0x12, 0x13,
+		0x34, 0x80, 0x98, 0xa2, 0x17, 0x72, 0x16, 0x72,
+		0x15, 0x72, 0x2d, 0x50, 0x06, 0xfa, 0x12, 0x13,
+		0x66, 0x80, 0x25, 0xc2, 0x13, 0x30, 0x28, 0x05,
+		0x12, 0x02, 0xbe, 0x80, 0x1b, 0xb4, 0x10, 0x12,
+		0x78, 0x00, 0xf2, 0xe5, 0x30, 0xb4, 0x01, 0x06,
+		0x12, 0x03, 0x90, 0xd2, 0x19, 0x22, 0x12, 0x00,
+		0xdd, 0x22, 0x75, 0x30, 0x00, 0x12, 0x00, 0xa1,
+		0x22, 0x00, 0x00, 0x75, 0x1e, 0x00, 0x74, 0x0c,
+		0x12, 0x2b, 0x9b, 0x74, 0x40, 0x79, 0x05, 0xf3,
+		0x74, 0x49, 0x12, 0x2b, 0x9b, 0x74, 0x04, 0x79,
+		0x05, 0xf3, 0x75, 0x15, 0x04, 0x74, 0x10, 0x12,
+		0x2b, 0x9b, 0x74, 0x00, 0x79, 0x05, 0xf3, 0x74,
+		0x17, 0x12, 0x2b, 0x9b, 0x74, 0x00, 0x79, 0x05,
+		0xf3, 0x74, 0x1a, 0x12, 0x2b, 0x9b, 0x74, 0x00,
+		0x79, 0x05, 0xf3, 0x74, 0x0a, 0x12, 0x2b, 0x9b,
+		0x74, 0x20, 0x79, 0x05, 0xf3, 0x79, 0xe0, 0x77,
+		0x20, 0x22, 0xd0, 0x02, 0xd0, 0xd0, 0xd0, 0xf0,
+		0xd0, 0x01, 0xe5, 0x5f, 0xd0, 0xa8, 0x22, 0x00,
+		0x00, 0x90, 0x25, 0x9f, 0x75, 0x26, 0xff, 0x75,
+		0x27, 0xff, 0x75, 0x28, 0x03, 0x75, 0x13, 0xff,
+		0x75, 0x1f, 0x00, 0x75, 0x14, 0xff, 0x22, 0x79,
+		0x06, 0xe5, 0x29, 0x60, 0x0b, 0xe3, 0x30, 0xe1,
+		0xf8, 0xe5, 0x4f, 0x64, 0x80, 0x79, 0x07, 0xf3,
+		0x22, 0x10, 0x4c, 0x01, 0x22, 0x30, 0x4b, 0x0a,
+		0xc2, 0x4b, 0xe5, 0x4d, 0x64, 0x80, 0xf5, 0x4f,
+		0x80, 0x1d, 0xe5, 0x15, 0xa2, 0xe0, 0x82, 0xe6,
+		0x40, 0x02, 0x80, 0x35, 0x30, 0x4a, 0x04, 0xb1,
+		0xe6, 0x80, 0x0c, 0x30, 0x49, 0x04, 0x51, 0x2b,
+		0x80, 0x05, 0x30, 0x48, 0x24, 0x91, 0x7e, 0x79,
+		0x06, 0xe3, 0x30, 0xe0, 0x1a, 0x79, 0x06, 0xf3,
+		0xe5, 0x4e, 0x24, 0xff, 0x50, 0x04, 0xf5, 0x4e,
+		0x80, 0x0d, 0x79, 0x0f, 0xf3, 0x20, 0x2a, 0x07,
+		0x12, 0x2b, 0x32, 0x75, 0x29, 0x00, 0x22, 0x91,
+		0x1b, 0x22, 0x79, 0x0f, 0xe3, 0xc0, 0xa8, 0x75,
+		0xa8, 0x00, 0x30, 0x2b, 0x03, 0xd0, 0xa8, 0x22,
+		0x79, 0x0e, 0xf3, 0xd0, 0xa8, 0x22, 0x8a, 0xf0,
+		0xe5, 0x50, 0x10, 0xf3, 0x10, 0x23, 0x23, 0x23,
+		0x25, 0xf0, 0x12, 0x2c, 0xb8, 0xa2, 0xe7, 0x92,
+		0xe4, 0xc2, 0xe7, 0x80, 0x08, 0x23, 0x23, 0x23,
+		0x25, 0xf0, 0x12, 0x2c, 0x19, 0x25, 0x4f, 0x20,
+		0xd2, 0x04, 0xf5, 0x4f, 0x80, 0x0a, 0x40, 0x05,
+		0x75, 0x4f, 0x7f, 0x80, 0x03, 0x75, 0x4f, 0xff,
+		0xea, 0x12, 0x2c, 0x3c, 0x25, 0x50, 0x20, 0xe7,
+		0x05, 0xb4, 0x03, 0x07, 0x80, 0x0c, 0x75, 0x50,
+		0x00, 0x80, 0x09, 0x40, 0x05, 0x75, 0x50, 0x03,
+		0x80, 0x02, 0xf5, 0x50, 0x22, 0xe5, 0x4d, 0xc4,
+		0x54, 0x0c, 0x03, 0x03, 0xfa, 0x91, 0xa9, 0x71,
+		0xb8, 0xe5, 0x4d, 0xc4, 0x54, 0x03, 0xfa, 0x91,
+		0xa9, 0x71, 0xb8, 0xe5, 0x4d, 0x54, 0x0c, 0x03,
+		0x03, 0xfa, 0x91, 0xa9, 0x71, 0xb8, 0xe5, 0x4d,
+		0x54, 0x03, 0xfa, 0x91, 0xa9, 0x71, 0xb8, 0x22,
+		0x8a, 0xf0, 0xe5, 0x50, 0x23, 0x23, 0x25, 0xf0,
+		0x12, 0x2b, 0xf6, 0x25, 0x4f, 0x20, 0xd2, 0x04,
+		0xf5, 0x4f, 0x80, 0x0a, 0x40, 0x05, 0x75, 0x4f,
+		0x7f, 0x80, 0x03, 0x75, 0x4f, 0xff, 0xea, 0x12,
+		0x2c, 0x40, 0x25, 0x50, 0x20, 0xe7, 0x05, 0xb4,
+		0x05, 0x07, 0x80, 0x0c, 0x75, 0x50, 0x00, 0x80,
+		0x09, 0x40, 0x05, 0x75, 0x50, 0x05, 0x80, 0x02,
+		0xf5, 0x50, 0x22, 0x30, 0x26, 0x03, 0x12, 0x1e,
+		0xf5, 0x30, 0x27, 0x03, 0x12, 0x1f, 0x37, 0x30,
+		0x25, 0x09, 0x12, 0x1f, 0x4e, 0x30, 0x23, 0x03,
+		0x12, 0x1f, 0x1e, 0x10, 0x22, 0x02, 0x80, 0x0a,
+		0xe5, 0x3b, 0xb4, 0xff, 0x02, 0xc2, 0x20, 0x12,
+		0x1e, 0x79, 0x22, 0x78, 0x11, 0xe2, 0x20, 0xe0,
+		0x07, 0xc0, 0x01, 0x12, 0x28, 0xba, 0xd0, 0x01,
+		0x78, 0x00, 0xf2, 0x61, 0x9b, 0x12, 0x2b, 0x32,
+		0x12, 0x17, 0x7f, 0x78, 0x00, 0xf2, 0xaa, 0x35,
+		0xab, 0x36, 0xea, 0x24, 0xff, 0xfa, 0xeb, 0x34,
+		0xff, 0xfb, 0x50, 0x03, 0xd2, 0x10, 0x22, 0x75,
+		0x37, 0x01, 0x75, 0x38, 0x00, 0x75, 0x39, 0x00,
+		0x12, 0x04, 0x04, 0xd2, 0x8e, 0x22, 0xa8, 0x2b,
+		0xb8, 0x00, 0x02, 0x80, 0x03, 0x02, 0x11, 0xbd,
+		0xf5, 0x74, 0x78, 0x2a, 0x12, 0x11, 0xec, 0xe5,
+		0x74, 0x78, 0x29, 0x12, 0x11, 0xec, 0x22, 0xfa,
+		0xe5, 0x2b, 0x60, 0x01, 0x22, 0xea, 0x78, 0x2b,
+		0xf5, 0x75, 0x12, 0x11, 0xec, 0x22, 0x74, 0x10,
+		0x12, 0x2b, 0x9b, 0x74, 0x20, 0x78, 0x05, 0xf2,
+		0x74, 0x09, 0x12, 0x17, 0x75, 0xe5, 0x15, 0x44,
+		0x80, 0x79, 0x05, 0xf3, 0xf5, 0x15, 0x12, 0x17,
+		0x7f, 0x22, 0x12, 0x03, 0x84, 0x79, 0x0f, 0xe3,
+		0x78, 0x00, 0xf2, 0x12, 0x2b, 0x28, 0xe5, 0x81,
+		0x24, 0xfc, 0xf5, 0x81, 0x61, 0x93, 0xd2, 0x07,
+		0x78, 0x11, 0xe2, 0x44, 0x11, 0xf5, 0x4c, 0xc2,
+		0x0f, 0x12, 0x29, 0xa3, 0x61, 0x93, 0x02, 0x1b,
+		0x77, 0x00, 0xe1, 0x81, 0xe1, 0x9a, 0xd2, 0x2c,
+		0xa1, 0x0c, 0x20, 0x20, 0x02, 0xd2, 0x26, 0x02,
+		0x1e, 0x35, 0x02, 0x1e, 0x61, 0x02, 0x1d, 0x8f,
+		0xc2, 0x8e, 0x75, 0xa8, 0x9e, 0x22, 0x41, 0x49,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x02, 0x29, 0x91, 0x00, 0x00, 0x00, 0xa1, 0xbb,
+		0xa1, 0xc3, 0x02, 0x1e, 0x6b, 0xe5, 0x4d, 0xc4,
+		0x54, 0x0f, 0xfa, 0x91, 0x2f, 0x71, 0xb8, 0xe5,
+		0x4d, 0x54, 0x0f, 0xfa, 0x91, 0x2f, 0x71, 0xb8,
+		0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa1, 0xc6,
+		0x02, 0x1d, 0x8f, 0xc2, 0x8e, 0xd2, 0xab, 0xc2,
+		0x10, 0x79, 0x0f, 0xf3, 0x22, 0x00, 0x02, 0x2a,
+		0x84, 0x00, 0xe1, 0xbc, 0xe1, 0xc8, 0x02, 0x1e,
+		0x27, 0x00, 0x78, 0x00, 0xf2, 0x78, 0x0b, 0xe2,
+		0xf4, 0xf5, 0x4d, 0xd2, 0x4c, 0x61, 0x9b, 0x30,
+		0xb5, 0x02, 0xc2, 0x11, 0x22, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x79, 0xbd, 0xf1, 0x3d, 0x83,
+		0x22, 0xdd, 0xbd, 0xbd, 0xbd, 0x61, 0xbd, 0x8d,
+		0x7a, 0xbd, 0xbd, 0xbd, 0xbd, 0x30, 0xbd, 0xbd,
+		0xbd, 0x55, 0xbd, 0xbd, 0xbd, 0x52, 0xbd, 0xb6,
+		0xb6, 0xbd, 0xbd, 0xbd, 0xbd, 0x00, 0xbd, 0xbd,
+		0xbd, 0xe8, 0xda, 0xbd, 0xbd, 0xcf, 0xb9, 0xbd,
+		0xc4, 0xf1, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd,
+		0xbd, 0x7b, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd,
+		0xbd, 0x70, 0x6a, 0x57, 0x47, 0x34, 0xbd, 0xbd,
+		0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0x29, 0xbd,
+		0xbd, 0xbd, 0xb6, 0xb6, 0xbd, 0xbd, 0xbd, 0xbd,
+		0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0x2e, 0x25,
+		0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xfe, 0xf5,
+		0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0x19, 0xbd,
+		0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0x21, 0x8f,
+		0x09, 0xbd, 0xf9, 0x86, 0xbd, 0xbd, 0xbd, 0xd7,
+		0xbd, 0xa9, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0x9b,
+		0xd1, 0x9d, 0xbd, 0xae, 0xbd, 0xbd, 0xbd, 0xcb,
+		0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd,
+		0xb6, 0xa5, 0xbd, 0xc5, 0xbd, 0xbd, 0xbd, 0xc3,
+		0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0x74, 0x10,
+		0x12, 0x2b, 0x9b, 0xe4, 0x78, 0x05, 0xf2, 0x74,
+		0x09, 0x12, 0x17, 0x75, 0xe5, 0x15, 0x54, 0x7f,
+		0x79, 0x05, 0xf3, 0xf5, 0x15, 0x12, 0x17, 0x7f,
+		0x22, 0x30, 0x51, 0x01, 0x22, 0x53, 0xa8, 0xfb,
+		0x12, 0x2d, 0xf0, 0x50, 0x22, 0x79, 0x03, 0xe3,
+		0x20, 0xe4, 0x1c, 0xaa, 0x35, 0xab, 0x36, 0xea,
+		0x24, 0xf0, 0xfa, 0xeb, 0x34, 0xff, 0xfb, 0x50,
+		0x0e, 0x10, 0x1f, 0x02, 0x80, 0x09, 0x20, 0x2a,
+		0x03, 0x12, 0x2b, 0x32, 0x12, 0x2d, 0xd6, 0x43,
+		0xa8, 0x04, 0x22, 0xa2, 0x1c, 0x72, 0x1d, 0x40,
+		0x07, 0x53, 0x08, 0xbf, 0x78, 0x00, 0xf2, 0x22,
+		0xb1, 0x1e, 0x22, 0x00, 0x79, 0x02, 0x12, 0x27,
+		0x3d, 0x02, 0x2d, 0x37, 0x14, 0x54, 0xf0, 0x60,
+		0x21, 0xe5, 0xf0, 0x24, 0xb6, 0xe5, 0xf0, 0x50,
+		0x16, 0x24, 0x8b, 0x50, 0x15, 0xe5, 0xf0, 0x24,
+		0x56, 0xe5, 0xf0, 0x50, 0x08, 0x24, 0x2f, 0x50,
+		0x09, 0xe5, 0xf0, 0x24, 0xd9, 0x24, 0xd5, 0x24,
+		0xf0, 0x22, 0x15, 0x81, 0x15, 0x81, 0xe9, 0x22,
+		0x78, 0x13, 0x74, 0x00, 0xf2, 0x75, 0x2e, 0x01,
+		0xd2, 0x6a, 0xc2, 0x69, 0xc2, 0x68, 0xc2, 0x6c,
+		0x90, 0x25, 0x9f, 0x75, 0xb8, 0x07, 0x41, 0xa4,
+		0xc0, 0x01, 0xc0, 0xf0, 0xc0, 0xd0, 0xc0, 0x02,
+		0xe5, 0x3d, 0x54, 0x7d, 0x03, 0x10, 0xe5, 0x05,
+		0x90, 0x28, 0x4b, 0x80, 0x03, 0x90, 0x2b, 0x7c,
+		0x73, 0xe5, 0x3d, 0x30, 0xe5, 0x07, 0x74, 0xfd,
+		0x78, 0x00, 0xf2, 0x61, 0x9b, 0x90, 0x1a, 0x97,
+		0x74, 0xb6, 0xc0, 0xe0, 0x74, 0x27, 0xc0, 0xe0,
+		0xc0, 0xa8, 0x02, 0x1b, 0xab, 0x90, 0x25, 0x9f,
+		0xd0, 0xa8, 0x22, 0x90, 0x27, 0xb6, 0xc0, 0x82,
+		0xc0, 0x83, 0xc0, 0xa8, 0x02, 0x1d, 0xa6, 0x90,
+		0x27, 0xb6, 0xc0, 0x82, 0xc0, 0x83, 0xc0, 0xa8,
+		0x02, 0x1e, 0x0a, 0xea, 0x24, 0xf0, 0xfa, 0xeb,
+		0x34, 0xff, 0xfb, 0x50, 0x2e, 0x20, 0x0b, 0x05,
+		0x85, 0x44, 0xe0, 0x80, 0x03, 0x75, 0xe0, 0x00,
+		0x30, 0xe1, 0x20, 0xe5, 0x35, 0x24, 0xff, 0xf5,
+		0x35, 0xe5, 0x36, 0x34, 0xff, 0xf5, 0x36, 0xc3,
+		0xe5, 0x36, 0x13, 0xf5, 0x36, 0xe5, 0x35, 0x13,
+		0xf5, 0x35, 0x75, 0x3a, 0x10, 0x12, 0x1a, 0x77,
+		0x02, 0x18, 0x77, 0x75, 0x3a, 0x00, 0x12, 0x1a,
+		0x77, 0x02, 0x18, 0x1b, 0x20, 0x4b, 0x04, 0x75,
+		0x4e, 0x03, 0x22, 0xe5, 0x35, 0x24, 0xff, 0xf5,
+		0x35, 0xe5, 0x36, 0x34, 0xff, 0xf5, 0x36, 0x75,
+		0x4e, 0x03, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x02, 0x2c,
+		0x70, 0xd2, 0x00, 0x78, 0x11, 0xe2, 0x44, 0x11,
+		0xf5, 0x3f, 0xc2, 0x08, 0x12, 0x29, 0xa3, 0x02,
+		0x23, 0x93, 0x21, 0x62, 0x61, 0x40, 0x01, 0x3a,
+		0x01, 0x73, 0x21, 0x76, 0x61, 0xa8, 0x21, 0x39,
+		0x21, 0x4a, 0x02, 0x2a, 0x7b, 0x79, 0x06, 0xf3,
+		0xc0, 0xd0, 0x12, 0x03, 0xd9, 0x78, 0x00, 0xf2,
+		0xd0, 0xd0, 0x22, 0x00, 0x00, 0x00, 0x00, 0x02,
+		0x2c, 0xb4, 0x78, 0x11, 0xe2, 0x44, 0x11, 0x54,
+		0x0f, 0xf8, 0xc4, 0x48, 0xd2, 0x05, 0xf5, 0x48,
+		0xc2, 0x0d, 0x31, 0xa3, 0x02, 0x23, 0x93, 0x20,
+		0x4b, 0x04, 0x75, 0x4e, 0x01, 0x22, 0xe5, 0x35,
+		0x24, 0xff, 0xf5, 0x35, 0xe5, 0x36, 0x34, 0xff,
+		0xf5, 0x36, 0x75, 0x4e, 0x01, 0x22, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x79, 0xd0, 0x77, 0x1b, 0x79, 0xd1, 0x77, 0x18,
+		0x79, 0xd2, 0x77, 0x77, 0x79, 0xd3, 0x77, 0x18,
+		0x22, 0x75, 0x29, 0x00, 0x75, 0x25, 0x00, 0x75,
+		0x34, 0x03, 0x75, 0x22, 0x00, 0x75, 0x23, 0x05,
+		0x75, 0x4f, 0x00, 0x75, 0x50, 0x00, 0x75, 0x30,
+		0x00, 0x79, 0xdc, 0x77, 0x03, 0xc2, 0x8e, 0x75,
+		0x17, 0xa8, 0x75, 0x16, 0xa8, 0x74, 0xaa, 0x79,
+		0x01, 0xf3, 0x79, 0xd7, 0x77, 0x74, 0x79, 0xd8,
+		0x77, 0xff, 0x79, 0xd9, 0x77, 0x07, 0x79, 0xda,
+		0x77, 0x00, 0x12, 0x25, 0x6f, 0x43, 0x08, 0x40,
+		0x71, 0x32, 0x79, 0x0e, 0xe3, 0x10, 0x51, 0x1c,
+		0x74, 0x06, 0x71, 0x9b, 0xe5, 0x11, 0x44, 0x80,
+		0x79, 0x05, 0xf3, 0xf5, 0x11, 0x74, 0x07, 0x71,
+		0x9b, 0xe5, 0x12, 0x44, 0x80, 0x79, 0x05, 0xf3,
+		0xf5, 0x12, 0x80, 0x18, 0x53, 0x27, 0xa0, 0x53,
+		0x28, 0x01, 0x75, 0x20, 0xf7, 0x12, 0x23, 0x4c,
+		0x75, 0x11, 0x80, 0x75, 0x12, 0x80, 0x12, 0x1f,
+		0xc0, 0x12, 0x21, 0xdc, 0x79, 0x06, 0xf3, 0x22,
+		0xd2, 0x02, 0x78, 0x11, 0xe2, 0x44, 0x11, 0xf5,
+		0x43, 0xc2, 0x0a, 0x12, 0x29, 0xa3, 0x02, 0x23,
+		0x93, 0x78, 0x11, 0xe2, 0x44, 0x11, 0xf5, 0x44,
+		0xc2, 0x0b, 0x12, 0x29, 0xa3, 0x02, 0x23, 0x93,
+		0x78, 0x00, 0xe2, 0x90, 0x25, 0x9f, 0x02, 0x23,
+		0x93, 0x78, 0x11, 0xe2, 0x75, 0x20, 0xf7, 0x75,
+		0x21, 0x3f, 0x75, 0x49, 0x11, 0x75, 0x4c, 0x11,
+		0x31, 0xa3, 0x02, 0x23, 0x93, 0x78, 0x11, 0xe2,
+		0x44, 0x11, 0x54, 0x0f, 0xf8, 0xc4, 0x48, 0xf8,
+		0xe5, 0x49, 0x45, 0x3f, 0x58, 0xf5, 0x49, 0xd2,
+		0x06, 0xc2, 0x0e, 0x31, 0xa3, 0x02, 0x23, 0x93,
+		0xc0, 0x01, 0x20, 0x2a, 0x04, 0x71, 0x32, 0xc2,
+		0x11, 0x11, 0x5e, 0xc2, 0x1f, 0xd0, 0x01, 0x02,
+		0x23, 0x9b, 0x12, 0x21, 0xdc, 0x78, 0x00, 0xf2,
+		0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0xda,
+		0xe7, 0x70, 0x2b, 0x20, 0x0a, 0x05, 0x85, 0x43,
+		0xe0, 0x80, 0x03, 0x75, 0xe0, 0x00, 0x30, 0xe1,
+		0x1d, 0x20, 0xe2, 0x1f, 0x74, 0xe0, 0xca, 0x74,
+		0x00, 0x71, 0x9b, 0xca, 0x79, 0x05, 0xf3, 0xf5,
+		0x09, 0xca, 0x74, 0x01, 0x71, 0x9b, 0xca, 0x79,
+		0x05, 0xf3, 0xf5, 0x0a, 0x80, 0x43, 0x12, 0x15,
+		0x3e, 0x80, 0x3e, 0xe5, 0x0b, 0xb4, 0x17, 0x02,
+		0x80, 0x0b, 0x50, 0x09, 0x74, 0x17, 0xc3, 0x95,
+		0x0b, 0x44, 0x60, 0x80, 0x02, 0x74, 0x60, 0xca,
+		0x74, 0x00, 0x71, 0x9b, 0xca, 0x79, 0x05, 0xf3,
+		0xf5, 0x09, 0xe5, 0x0c, 0xb4, 0x17, 0x02, 0x80,
+		0x0b, 0x50, 0x09, 0x74, 0x17, 0xc3, 0x95, 0x0c,
+		0x44, 0x60, 0x80, 0x02, 0x74, 0x60, 0xca, 0x74,
+		0x01, 0x71, 0x9b, 0xca, 0x79, 0x05, 0xf3, 0xf5,
+		0x0a, 0x22, 0xd2, 0x04, 0x78, 0x11, 0xe2, 0x44,
+		0x11, 0xf5, 0x46, 0xc2, 0x0c, 0x31, 0xa3, 0x02,
+		0x23, 0x93, 0xd2, 0x05, 0x78, 0x11, 0xe2, 0x44,
+		0x11, 0xf5, 0x48, 0xc2, 0x0d, 0x31, 0xa3, 0x02,
+		0x23, 0x93, 0xd2, 0x06, 0x78, 0x11, 0xe2, 0x44,
+		0x11, 0xf5, 0x49, 0xc2, 0x0e, 0x31, 0xa3, 0x02,
+		0x23, 0x93, 0x30, 0x1c, 0x21, 0x20, 0x4d, 0x1e,
+		0xe5, 0x29, 0x60, 0x1a, 0xc2, 0x1c, 0x12, 0x19,
+		0xec, 0x12, 0x13, 0xcf, 0xd2, 0x4d, 0x12, 0x17,
+		0x7f, 0x78, 0x00, 0xf2, 0x79, 0x06, 0xf3, 0x43,
+		0xa8, 0x04, 0x12, 0x24, 0x1b, 0x22, 0x12, 0x27,
+		0x24, 0x22, 0x78, 0x00, 0xe2, 0x90, 0x25, 0x9f,
+		0x02, 0x23, 0x93, 0x78, 0x00, 0xe2, 0xa2, 0xe7,
+		0x72, 0xe3, 0x92, 0xe7, 0x02, 0x1d, 0x85, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x79, 0x04, 0xe3, 0x54, 0x80, 0x70, 0xf9, 0x22,
+		0xe5, 0x29, 0x79, 0xde, 0xf7, 0x75, 0x29, 0x00,
+		0x70, 0x12, 0xe5, 0x15, 0x79, 0xdd, 0xf7, 0x12,
+		0x2d, 0xf0, 0x40, 0x08, 0x20, 0x1c, 0x07, 0x20,
+		0x1d, 0x04, 0x80, 0x02, 0x71, 0x32, 0x30, 0xb5,
+		0x0c, 0x79, 0x06, 0xf3, 0x20, 0x2a, 0x06, 0x79,
+		0xdd, 0xe7, 0x54, 0xfc, 0xf7, 0xd2, 0x2b, 0x12,
+		0x25, 0x6f, 0x22, 0x00, 0x00, 0x00, 0x00, 0xe5,
+		0x15, 0xa2, 0xe0, 0xb0, 0xe6, 0x40, 0x31, 0xa2,
+		0xe1, 0xb0, 0xe7, 0x40, 0x38, 0x10, 0x2b, 0x02,
+		0x80, 0x26, 0x79, 0xde, 0xe7, 0x70, 0x0b, 0x79,
+		0xdd, 0xe7, 0x20, 0xe0, 0x12, 0x20, 0xe1, 0x28,
+		0x80, 0x16, 0xf5, 0x29, 0x30, 0x4d, 0x11, 0x20,
+		0x4c, 0x0e, 0x12, 0x24, 0x1b, 0x80, 0x09, 0x43,
+		0x08, 0x40, 0x12, 0x13, 0xcf, 0x12, 0x17, 0x7f,
+		0xe5, 0x13, 0x20, 0xe4, 0x05, 0x12, 0x18, 0x1b,
+		0x80, 0x03, 0x12, 0x18, 0x77, 0xc2, 0x2b, 0x22,
+		0x12, 0x26, 0xd7, 0x12, 0x13, 0xb7, 0x22, 0x78,
+		0x04, 0x79, 0x00, 0xd9, 0xfe, 0xd8, 0xfa, 0x22,
+		0x00, 0x74, 0x09, 0x71, 0x9b, 0xe5, 0x15, 0x54,
+		0xfc, 0x79, 0x05, 0xf3, 0xf5, 0x15, 0x22, 0x78,
+		0x11, 0xe2, 0x44, 0x11, 0x54, 0x0f, 0xf8, 0xc4,
+		0x48, 0xf5, 0x46, 0xc2, 0x0c, 0xd2, 0x04, 0x31,
+		0xa3, 0x02, 0x23, 0x93, 0x12, 0x26, 0xd7, 0x12,
+		0x00, 0xb7, 0x22, 0x00, 0x79, 0x06, 0xf3, 0x74,
+		0x0a, 0x71, 0x9b, 0x79, 0xe0, 0xe7, 0x44, 0x02,
+		0xf7, 0x79, 0x05, 0xf3, 0x22, 0x74, 0x0a, 0x71,
+		0x9b, 0x79, 0xe0, 0xe7, 0x54, 0xfd, 0xf7, 0x79,
+		0x05, 0xf3, 0x22, 0x21, 0x59, 0x41, 0x23, 0x21,
+		0x59, 0x41, 0x33, 0x41, 0x43, 0x21, 0x59, 0x21,
+		0x59, 0x02, 0x25, 0x9f, 0x00, 0x74, 0x0d, 0x71,
+		0x9b, 0x74, 0x4d, 0x79, 0x05, 0xf3, 0xd2, 0x52,
+		0x22, 0x00, 0x53, 0x08, 0x40, 0x45, 0x08, 0x45,
+		0x1e, 0x79, 0x04, 0xf3, 0xf5, 0x08, 0x22, 0xd2,
+		0x01, 0x78, 0x11, 0xe2, 0x44, 0x11, 0xf5, 0x42,
+		0xc2, 0x09, 0x31, 0xa3, 0x02, 0x23, 0x93, 0x00,
+		0x00, 0x00, 0x00, 0x71, 0x6e, 0x74, 0x09, 0x12,
+		0x17, 0x75, 0xe5, 0x15, 0x44, 0x40, 0x79, 0x05,
+		0xf3, 0xf5, 0x15, 0x75, 0x3a, 0x00, 0x12, 0x1a,
+		0x77, 0x02, 0x18, 0x1b, 0xf5, 0x38, 0xe5, 0x37,
+		0x24, 0x01, 0xf5, 0x37, 0xe5, 0x38, 0x34, 0x00,
+		0xf5, 0x38, 0x40, 0x05, 0x75, 0x39, 0x00, 0x80,
+		0x03, 0x75, 0x39, 0x01, 0x12, 0x04, 0x04, 0xd2,
+		0x8e, 0x02, 0x03, 0x8d, 0x00, 0xb4, 0x0d, 0x03,
+		0x74, 0x14, 0x22, 0x04, 0x83, 0x22, 0x00, 0x02,
+		0xff, 0x01, 0x00, 0x05, 0xfe, 0xff, 0x00, 0x0a,
+		0xfc, 0xfe, 0x00, 0xc0, 0xf8, 0xfc, 0x00, 0x28,
+		0xf0, 0xf8, 0x00, 0x30, 0xe0, 0xd0, 0x01, 0x88,
+		0x04, 0x83, 0x22, 0x00, 0xff, 0xfe, 0xfd, 0xfc,
+		0xfc, 0xfb, 0xfa, 0xfe, 0xfd, 0xfb, 0xf9, 0xf7,
+		0xf7, 0xf5, 0xf3, 0xfc, 0xfa, 0xf6, 0xf2, 0xee,
+		0xee, 0xea, 0xe6, 0xf8, 0xf4, 0xec, 0xe4, 0xdc,
+		0xd4, 0xcc, 0xc4, 0x24, 0x21, 0x83, 0x22, 0x04,
+		0x83, 0x22, 0xff, 0x01, 0xff, 0x01, 0x00, 0x00,
+		0x00, 0x02, 0x22, 0x32, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+		0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0xff,
+		0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x83,
+		0x22, 0x8a, 0x01, 0x20, 0x01, 0x0b, 0xea, 0xf3,
+		0xf9, 0x8b, 0x7e, 0x6b, 0xd5, 0x01, 0x00, 0x01,
+		0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x01, 0x3a, 0x01, 0x38, 0x01, 0x4b, 0x01,
+		0x49, 0x01, 0x5c, 0x01, 0x5a, 0x01, 0x08, 0x08,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x01, 0x15, 0x24, 0x48, 0x83, 0x22, 0x04,
+		0x83, 0x22, 0x00, 0x01, 0x02, 0x03, 0x04, 0x06,
+		0x07, 0x08, 0x00, 0x03, 0x05, 0x07, 0x09, 0x0d,
+		0x0f, 0x81, 0x00, 0x06, 0x0a, 0x0e, 0x82, 0x8a,
+		0x8e, 0x22, 0x00, 0x0c, 0x84, 0x8c, 0x24, 0x2c,
+		0xa4, 0xac, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0xaa, 0x35, 0xab, 0x36,
+		0x02, 0x27, 0xd4, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
+		0x03, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x25,
+		0x03, 0x03, 0x2b, 0x03, 0x00, 0x03, 0x00, 0x03,
+		0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
+		0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
+		0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x83, 0x22,
+		0x00, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, 0x02,
+		0x02, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, 0x02,
+		0x2b, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, 0x02,
+		0x02, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, 0x02,
+		0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x01,
+		0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+		0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+		0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+		0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+		0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+		0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02,
+		0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02,
+		0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+		0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x02,
+		0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x02,
+		0x21, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x00,
+		0x02, 0x02, 0x01, 0x02, 0x02, 0x02, 0x00, 0x02,
+		0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x21,
+		0x01, 0x02, 0x21, 0x02, 0x02, 0x02, 0x00, 0x02,
+		0x02, 0x02, 0x02, 0x02, 0x02, 0x20, 0xb5, 0x05,
+		0x79, 0x0f, 0xf3, 0xc2, 0x11, 0x22, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe5,
+		0x15, 0xa2, 0xe0, 0xb0, 0xe6, 0x50, 0x01, 0x22,
+		0xa2, 0xe1, 0xb0, 0xe7, 0x22, 0x02, 0x00};
+		static unsigned char	Data0485_0C[] = {
+		0x02, 0x27, 0x69};
+		static unsigned char	Data0485_66[] = {
+		0x02, 0x25, 0x47, 0x02, 0x25, 0x60};
+		static unsigned char	Data0485_60[] = {
+		0x02, 0x22, 0x7e};
+		static unsigned char	Data0485_99[] = {
+		0xc2, 0x53, 0x02, 0x12, 0x86};
+		static unsigned char	Data0485_9E[] = {
+		0x70, 0xf9, 0x22};
+#ifdef OOKUBO_ORIGINAL
+		static unsigned char	Data0485_36[] = {
+		0x78, 0x00, 0xf2, 0xc2, 0x53, 0x74, 0x86, 0xc0,
+		0xe0, 0x74, 0x12, 0xc0,	0xe0, 0x32};
+#endif /* OOKUBO_ORIGINAL */
diff -Nru linux/sound/isa/cs423x/sound_pc9800.h linux/sound/isa/cs423x/sound_pc9800.h
--- linux/sound/isa/cs423x/sound_pc9800.h	1970-01-01 09:00:00.000000000 +0100
+++ linux/sound/isa/cs423x/sound_pc9800.h	2002-10-28 15:45:00.000000000 +0100
@@ -0,0 +1,23 @@
+#ifndef _SOUND_PC9800_H_
+#define _SOUND_PC9800_H_
+
+#include <asm/io.h>
+
+#define PC9800_SOUND_IO_ID	0xa460
+
+/* Sound Functions ID. */
+#define PC9800_SOUND_ID()	((inb(PC9800_SOUND_IO_ID) >> 4) & 0x0f)
+
+#define PC9800_SOUND_ID_DO	0x0	/* PC-98DO+ Internal */
+#define PC9800_SOUND_ID_GS	0x1	/* PC-98GS Internal */
+#define PC9800_SOUND_ID_73	0x2	/* PC-9801-73 (base 0x18x) */
+#define PC9800_SOUND_ID_73A	0x3	/* PC-9801-73/76 (base 0x28x) */
+#define PC9800_SOUND_ID_86	0x4	/* PC-9801-86 and compatible (base 0x18x) */
+#define PC9800_SOUND_ID_86A	0x5	/* PC-9801-86 (base 0x28x) */
+#define PC9800_SOUND_ID_NF	0x6	/* PC-9821Nf/Np Internal */
+#define PC9800_SOUND_ID_XMATE	0x7	/* X-Mate Internal and compatible */
+#define PC9800_SOUND_ID_118	0x8	/* PC-9801-118 and compatible(CanBe Internal, etc.) */
+
+#define PC9800_SOUND_ID_UNKNOWN	0xf	/* Unknown (No Sound System or PC-9801-26) */
+
+#endif
diff -Nru linux-2.5.60/sound/core/Makefile linux98-2.5.60/sound/core/Makefile
--- linux-2.5.60/sound/core/Makefile	2003-02-11 03:38:46.000000000 +0900
+++ linux98-2.5.60/sound/core/Makefile	2003-02-11 10:26:12.000000000 +0900
@@ -93,6 +93,7 @@
 obj-$(CONFIG_SND_YMFPCI) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o snd-hwdep.o
 obj-$(CONFIG_SND_POWERMAC) += snd-pcm.o snd-timer.o snd.o
 obj-$(CONFIG_SND_SA11XX_UDA1341) += snd-pcm.o snd-timer.o snd.o
+obj-$(CONFIG_SND_PC98_CS4232) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o snd-hwdep.o
 ifeq ($(CONFIG_SND_SB16_CSP),y)
   obj-$(CONFIG_SND_SB16) += snd-hwdep.o
   obj-$(CONFIG_SND_SBAWE) += snd-hwdep.o
diff -Nru linux-2.5.60/sound/drivers/mpu401/Makefile linux98-2.5.60/sound/drivers/mpu401/Makefile
--- linux-2.5.60/sound/drivers/mpu401/Makefile	2003-02-11 03:39:14.000000000 +0900
+++ linux98-2.5.60/sound/drivers/mpu401/Makefile	2003-02-11 10:26:12.000000000 +0900
@@ -37,5 +37,6 @@
 obj-$(CONFIG_SND_ALI5451) += snd-mpu401-uart.o
 obj-$(CONFIG_SND_TRIDENT) += snd-mpu401-uart.o
 obj-$(CONFIG_SND_YMFPCI) += snd-mpu401-uart.o
+obj-$(CONFIG_SND_PC98_CS4232) += snd-mpu401-uart.o
 
 obj-m := $(sort $(obj-m))
diff -Nru linux-2.5.60/sound/drivers/opl3/Makefile linux98-2.5.60/sound/drivers/opl3/Makefile
--- linux-2.5.60/sound/drivers/opl3/Makefile	2003-02-11 03:37:56.000000000 +0900
+++ linux98-2.5.60/sound/drivers/opl3/Makefile	2003-02-11 10:26:12.000000000 +0900
@@ -24,6 +24,7 @@
 obj-$(CONFIG_SND_OPL3SA2) += $(OPL3_OBJS)
 obj-$(CONFIG_SND_AD1816A) += $(OPL3_OBJS)
 obj-$(CONFIG_SND_CS4232) += $(OPL3_OBJS)
+obj-$(CONFIG_SND_PC98_CS4232) += $(OPL3_OBJS)
 obj-$(CONFIG_SND_CS4236) += $(OPL3_OBJS)
 obj-$(CONFIG_SND_ES1688) += $(OPL3_OBJS)
 obj-$(CONFIG_SND_GUSEXTREME) += $(OPL3_OBJS)

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH] PC-9800 additional for 2.5.61-ac1 (2/21) APM
  2003-02-20 12:16 [PATCH] PC-9800 additional for 2.5.61-ac1 (0/21) summary Osamu Tomita
  2003-02-20 12:22 ` [PATCH] PC-9800 additional for 2.5.61-ac1 (1/21) ALSA Osamu Tomita
@ 2003-02-20 12:22 ` Osamu Tomita
  2003-02-20 12:23 ` [PATCH] PC-9800 additional for 2.5.61-ac1 (3/21) console Osamu Tomita
                   ` (17 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Osamu Tomita @ 2003-02-20 12:22 UTC (permalink / raw)
  To: Linux Kernel Mailing List; +Cc: Alan Cox

This is additional patch to support NEC PC-9800 subarchitecture
against 2.5.61-ac1. (2/21)

APM support for PC98. Including PC98's BIOS bug fix.

diff -Nru linux-2.5.61/arch/i386/kernel/apm.c linux98-2.5.61/arch/i386/kernel/apm.c
--- linux-2.5.61/arch/i386/kernel/apm.c	2003-02-15 08:51:10.000000000 +0900
+++ linux98-2.5.61/arch/i386/kernel/apm.c	2003-02-15 13:40:49.000000000 +0900
@@ -226,6 +226,8 @@
 #include <asm/uaccess.h>
 #include <asm/desc.h>
 
+#include "io_ports.h"
+
 extern spinlock_t i8253_lock;
 extern unsigned long get_cmos_time(void);
 extern void machine_real_restart(unsigned char *, int);
@@ -621,6 +623,9 @@
 	__asm__ __volatile__(APM_DO_ZERO_SEGS
 		"pushl %%edi\n\t"
 		"pushl %%ebp\n\t"
+#ifdef CONFIG_X86_PC9800
+		"pushfl\n\t"
+#endif
 		"lcall *%%cs:apm_bios_entry\n\t"
 		"setc %%al\n\t"
 		"popl %%ebp\n\t"
@@ -682,6 +687,9 @@
 		__asm__ __volatile__(APM_DO_ZERO_SEGS
 			"pushl %%edi\n\t"
 			"pushl %%ebp\n\t"
+#ifdef CONFIG_X86_PC9800
+			"pushfl\n\t"
+#endif
 			"lcall *%%cs:apm_bios_entry\n\t"
 			"setc %%bl\n\t"
 			"popl %%ebp\n\t"
@@ -722,7 +730,7 @@
 
 	if (apm_bios_call_simple(APM_FUNC_VERSION, 0, *val, &eax))
 		return (eax >> 8) & 0xff;
-	*val = eax;
+	*val = pc98 ? ((eax & 0xff00) | ((eax & 0x00f0) >> 4)) : eax;
 	return APM_SUCCESS;
 }
 
@@ -1211,11 +1219,11 @@
 {
 #ifdef INIT_TIMER_AFTER_SUSPEND
 	/* set the clock to 100 Hz */
-	outb_p(0x34,0x43);		/* binary, mode 2, LSB/MSB, ch 0 */
+	outb_p(0x34, PIT_MODE);		/* binary, mode 2, LSB/MSB, ch 0 */
 	udelay(10);
-	outb_p(LATCH & 0xff , 0x40);	/* LSB */
+	outb_p(LATCH & 0xff, PIT_CH0);	/* LSB */
 	udelay(10);
-	outb(LATCH >> 8 , 0x40);	/* MSB */
+	outb(LATCH >> 8, PIT_CH0);	/* MSB */
 	udelay(10);
 #endif
 }
diff -Nru linux-2.5.61/include/linux/apm_bios.h linux98-2.5.61/include/linux/apm_bios.h
--- linux-2.5.61/include/linux/apm_bios.h	2003-02-15 08:51:47.000000000 +0900
+++ linux98-2.5.61/include/linux/apm_bios.h	2003-02-20 08:51:34.000000000 +0900
@@ -20,6 +20,7 @@
 typedef unsigned short	apm_eventinfo_t;
 
 #ifdef __KERNEL__
+#include <linux/config.h>
 
 #define APM_CS		(GDT_ENTRY_APMBIOS_BASE * 8)
 #define APM_CS_16	(APM_CS + 8)
@@ -60,6 +61,28 @@
 /*
  * The APM function codes
  */
+#ifdef CONFIG_X86_PC9800
+#define	APM_FUNC_INST_CHECK	0x9a00
+#define	APM_FUNC_REAL_CONN	0x9a01
+#define	APM_FUNC_16BIT_CONN	0x9a02
+#define	APM_FUNC_32BIT_CONN	0x9a03
+#define	APM_FUNC_DISCONN	0x9a04
+#define	APM_FUNC_IDLE		0x9a05
+#define	APM_FUNC_BUSY		0x9a06
+#define	APM_FUNC_SET_STATE	0x9a07
+#define	APM_FUNC_ENABLE_PM	0x9a08
+#define	APM_FUNC_RESTORE_BIOS	0x9a09
+#define	APM_FUNC_GET_STATUS	0x9a3a
+#define	APM_FUNC_GET_EVENT	0x9a0b
+#define	APM_FUNC_GET_STATE	0x9a0c
+#define	APM_FUNC_ENABLE_DEV_PM	0x9a0d
+#define	APM_FUNC_VERSION	0x9a3e
+#define	APM_FUNC_ENGAGE_PM	0x9a3f
+#define	APM_FUNC_GET_CAP	0x9a10
+#define	APM_FUNC_RESUME_TIMER	0x9a11
+#define	APM_FUNC_RESUME_ON_RING	0x9a12
+#define	APM_FUNC_TIMER		0x9a13
+#else
 #define	APM_FUNC_INST_CHECK	0x5300
 #define	APM_FUNC_REAL_CONN	0x5301
 #define	APM_FUNC_16BIT_CONN	0x5302
@@ -80,6 +103,7 @@
 #define	APM_FUNC_RESUME_TIMER	0x5311
 #define	APM_FUNC_RESUME_ON_RING	0x5312
 #define	APM_FUNC_TIMER		0x5313
+#endif
 
 /*
  * Function code for APM_FUNC_RESUME_TIMER

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH] PC-9800 additional for 2.5.61-ac1 (3/21) console
  2003-02-20 12:16 [PATCH] PC-9800 additional for 2.5.61-ac1 (0/21) summary Osamu Tomita
  2003-02-20 12:22 ` [PATCH] PC-9800 additional for 2.5.61-ac1 (1/21) ALSA Osamu Tomita
  2003-02-20 12:22 ` [PATCH] PC-9800 additional for 2.5.61-ac1 (2/21) APM Osamu Tomita
@ 2003-02-20 12:23 ` Osamu Tomita
  2003-02-20 12:24 ` [PATCH] PC-9800 additional for 2.5.61-ac1 (4/21) misc core Osamu Tomita
                   ` (16 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Osamu Tomita @ 2003-02-20 12:23 UTC (permalink / raw)
  To: Linux Kernel Mailing List; +Cc: Alan Cox

This is additional patch to support NEC PC-9800 subarchitecture
against 2.5.61-ac1. (3/21)

PC98 Standard console support (without japanese kanji character).

diff -Nru linux-2.5.60/drivers/char/Makefile linux98-2.5.60/drivers/char/Makefile
--- linux-2.5.60/drivers/char/Makefile	2003-02-18 11:10:03.000000000 +0900
+++ linux98-2.5.60/drivers/char/Makefile	2003-02-20 09:16:30.000000000 +0900
@@ -5,7 +5,11 @@
 #
 # This file contains the font map for the default (hardware) font
 #
+ifeq ($(CONFIG_X86_PC9800),y)
+FONTMAPFILE = pc9800.uni
+else
 FONTMAPFILE = cp437.uni
+endif
 
 obj-y	 += mem.o tty_io.o n_tty.o tty_ioctl.o pty.o misc.o random.o
 
diff -Nru linux/drivers/char/console_macros.h linux98/drivers/char/console_macros.h
--- linux/drivers/char/console_macros.h	Sat Oct 19 13:01:17 2002
+++ linux98/drivers/char/console_macros.h	Mon Oct 28 16:53:39 2002
@@ -55,6 +55,10 @@
 #define	s_reverse	(vc_cons[currcons].d->vc_s_reverse)
 #define	ulcolor		(vc_cons[currcons].d->vc_ulcolor)
 #define	halfcolor	(vc_cons[currcons].d->vc_halfcolor)
+#define def_attr	(vc_cons[currcons].d->vc_def_attr)
+#define ul_attr		(vc_cons[currcons].d->vc_ul_attr)
+#define half_attr	(vc_cons[currcons].d->vc_half_attr)
+#define bold_attr	(vc_cons[currcons].d->vc_bold_attr)
 #define tab_stop	(vc_cons[currcons].d->vc_tab_stop)
 #define palette		(vc_cons[currcons].d->vc_palette)
 #define bell_pitch	(vc_cons[currcons].d->vc_bell_pitch)
diff -Nru linux/drivers/char/console_pc9800.h linux98/drivers/char/console_pc9800.h
--- linux/drivers/char/console_pc9800.h	Thu Jan  1 09:00:00 1970
+++ linux98/drivers/char/console_pc9800.h	Mon Oct 28 11:48:10 2002
@@ -0,0 +1,14 @@
+#ifndef __CONSOLE_PC9800_H
+#define __CONSOLE_PC9800_H
+
+#define BLANK_ATTR	0x00E1
+
+#define JIS_CODE       0x01
+#define EUC_CODE       0x00
+#define SJIS_CODE      0x02
+#define JIS_CODE_ASCII  0x00
+#define JIS_CODE_78     0x01
+#define JIS_CODE_83     0x02
+#define JIS_CODE_90     0x03
+
+#endif /* __CONSOLE_PC9800_H */
diff -Nru linux/drivers/char/consolemap.c linux98/drivers/char/consolemap.c
--- linux/drivers/char/consolemap.c	2002-12-10 11:46:14.000000000 +0900
+++ linux98/drivers/char/consolemap.c	2002-12-16 11:27:23.000000000 +0900
@@ -23,7 +23,7 @@
 #include <linux/consolemap.h>
 #include <linux/vt_kern.h>
 
-static unsigned short translations[][256] = {
+unsigned short translations[][256] = {
   /* 8-bit Latin-1 mapped to Unicode -- trivial mapping */
   {
     0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
@@ -163,7 +163,59 @@
     0xf0e8, 0xf0e9, 0xf0ea, 0xf0eb, 0xf0ec, 0xf0ed, 0xf0ee, 0xf0ef,
     0xf0f0, 0xf0f1, 0xf0f2, 0xf0f3, 0xf0f4, 0xf0f5, 0xf0f6, 0xf0f7,
     0xf0f8, 0xf0f9, 0xf0fa, 0xf0fb, 0xf0fc, 0xf0fd, 0xf0fe, 0xf0ff
-  }
+  },
+  /* JIS X0201 mapped to Unicode */
+  /* code marked with ** is not defined in JIS X0201.
+	 So 0x00 - 0x1f are mapped to same to Laten1,
+	 and others are mapped to PC-9800 internal font# directry */
+  {
+    0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+/*    **      **      **      **      **      **      **      **    */
+    0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
+/*    **      **      **      **      **      **      **      **    */
+    0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+/*    **      **      **      **      **      **      **      **    */
+    0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
+/*    **      **      **      **      **      **      **      **    */
+    0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+    0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
+    0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+    0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
+    0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+    0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
+    0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+    0x0058, 0x0059, 0x005a, 0x005b, 0x00a5, 0x005d, 0x005e, 0x005f,
+    0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+    0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
+    0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+    0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x203e, 0xf07f,
+/*                                                            **   */
+    0xf080, 0xf081, 0xf082, 0xf083, 0xf084, 0xf085, 0xf086, 0xf087,
+/*    **      **      **      **      **      **      **      **    */
+    0xf088, 0xf089, 0xf08a, 0xf08b, 0xf08c, 0xf08d, 0xf08e, 0xf08f,
+/*    **      **      **      **      **      **      **      **    */
+    0xf090, 0xf091, 0xf092, 0xf093, 0xf094, 0xf095, 0xf096, 0xf097,
+/*    **      **      **      **      **      **      **      **    */
+    0xf098, 0xf099, 0xf09a, 0xf09b, 0xf09c, 0xf09d, 0xf09e, 0xf09f,
+/*    **      **      **      **      **      **      **      **    */
+    0xf0a0, 0xff61, 0xff62, 0xff63, 0xff64, 0xff65, 0xff66, 0xff67,
+/*    **                                                            */
+    0xff68, 0xff69, 0xff6a, 0xff6b, 0xff6c, 0xff6d, 0xff6e, 0xff6f,
+    0xff70, 0xff71, 0xff72, 0xff73, 0xff74, 0xff75, 0xff76, 0xff77,
+    0xff78, 0xff79, 0xff7a, 0xff7b, 0xff7c, 0xff7d, 0xff7e, 0xff7f,
+    0xff80, 0xff81, 0xff82, 0xff83, 0xff84, 0xff85, 0xff86, 0xff87,
+    0xff88, 0xff89, 0xff8a, 0xff8b, 0xff8c, 0xff8d, 0xff8e, 0xff8f,
+    0xff90, 0xff91, 0xff92, 0xff93, 0xff94, 0xff95, 0xff96, 0xff97,
+    0xff98, 0xff99, 0xff9a, 0xff9b, 0xff9c, 0xff9d, 0xff9e, 0xff9f,
+    0xf0e0, 0xf0e1, 0xf0e2, 0xf0e3, 0xf0e4, 0xf0e5, 0xf0e6, 0xf0e7,
+/*    **      **      **      **      **      **      **      **    */
+    0xf0e8, 0xf0e9, 0xf0ea, 0xf0eb, 0xf0ec, 0xf0ed, 0xf0ee, 0xf0ef,
+/*    **      **      **      **      **      **      **      **    */
+    0xf0f0, 0xf0f1, 0xf0f2, 0xf0f3, 0xf0f4, 0xf0f5, 0xf0f6, 0xf0f7,
+/*    **      **      **      **      **      **      **      **    */
+    0xf0f8, 0xf0f9, 0xf0fa, 0xf0fb, 0xf0fc, 0xf0fd, 0xf0fe, 0xf0ff
+/*    **      **      **      **      **      **      **      **    */
+  },
 };
 
 /* The standard kernel character-to-font mappings are not invertible
@@ -177,7 +229,7 @@
 	u16 		**uni_pgdir[32];
 	unsigned long	refcount;
 	unsigned long	sum;
-	unsigned char	*inverse_translations[4];
+	unsigned char	*inverse_translations[5];
 	int		readonly;
 };
 
diff -Nru linux/drivers/char/pc9800.uni linux98/drivers/char/pc9800.uni
--- linux/drivers/char/pc9800.uni	Thu Jan  1 09:00:00 1970
+++ linux98/drivers/char/pc9800.uni	Fri Aug 17 21:50:17 2001
@@ -0,0 +1,260 @@
+#
+# Unicode table for PC-9800 console.
+# Copyright (C) 1998,2001  Linux/98 project (project Seraphim)
+#			   Kyoto University Microcomputer Club (KMC).
+#
+
+# Kore ha unicode wo 98 no ROM no font ni taio saseru tame no
+# map desu.
+
+# Characters for control codes.
+# PC-9800 uses 2-char sequences while Unicode uses 3-char for some codes.
+0x00	
+0x01	U+2401	# SH / SOH
+0x02	U+2402	# SX / SOX
+0x03	U+2403	# EX / ETX
+0x04	U+2404	# ET / EOT
+0x05	U+2405	# EQ / ENQ
+0x06	U+2406	# AK / ACK
+0x07	U+2407	# BL / BEL
+0x08	U+2408	# BS
+0x09	U+2409	# HT
+0x0a	U+240a	# LF
+0x0b		# HM / (VT)
+0x0c		# CL / (FF)
+0x0d	U+240d	# CR
+0x0e		# SO / (SS)
+0x0f	U+240f	# SI
+0x10	U+2410	# DE / DLE
+0x11	U+2411	# D1 / DC1
+0x12	U+2412	# D2 / DC2
+0x13	U+2413	# D3 / DC3
+0x14	U+2414	# D4 / DC4
+0x15	U+2415	# NK / NAK
+0x16	U+2416	# SN / SYN
+0x17	U+2417	# EB / ETB
+0x18	U+2418	# CN / CAN
+0x19	U+2419	# EM
+0x1a	U+241a	# SB / SUB
+0x1b	U+241b	# EC / ESC
+
+# arrow
+0x1c	U+2192 U+ffeb	# right
+0x1d	U+2190 U+ffe9	# left
+0x1e	U+2191 U+ffea	# up
+0x1f	U+2193 U+ffec	# down
+
+#
+# The ASCII range is identity-mapped, but some of the characters also
+# have to act as substitutes, especially the upper-case characters.
+#
+0x20	U+0020
+0x21	U+0021
+# U+00a8 is Latin-1 Supplement DIAELESIS.
+0x22	U+0022 U+00a8
+0x23	U+0023
+0x24	U+0024
+0x25	U+0025
+0x26	U+0026
+0x26	U+2019	# General Punctuation "RIGHT SINGLE QUOTATION MARK"
+0x27	U+0027 U+2032
+0x28	U+0028
+0x29	U+0029
+0x2a	U+002a
+0x2b	U+002b
+# U+00b8 is Latin-1 Supplement CEDILLA.
+0x2c	U+002c U+00b8
+# U+00b8 is Latin-1 Supplement SOFT HYPHEN.
+0x2d	U+002d U+00ad
+0x2d	U+2212	# Mathematical Operators "MINUS SIGN"
+0x2e	U+002e
+0x2f	U+002f
+0x2f	U+2044	# General Punctuation "FRACTION SLASH"
+0x2f	U+2215	# Mathematical Operators "DIVISION SLASH"
+0x30	U+0030
+0x31	U+0031
+0x32	U+0032
+0x33	U+0033
+0x34	U+0034
+0x35	U+0035
+0x36	U+0036
+0x37	U+0037
+0x38	U+0038
+0x39	U+0039
+0x3a	U+003a
+0x3a	U+003a	# Mathematical Operators "RATIO"
+0x3b	U+003b
+0x3c	U+003c
+0x3d	U+003d
+0x3e	U+003e
+0x3f	U+003f
+0x40	U+0040
+0x41	U+0041 U+00c0 U+00c1 U+00c2 U+00c3
+0x42	U+0042
+# U+00a9 is Latin-1 Supplement COPYRIGHT SIGN.
+0x43	U+0043 U+00a9
+0x44	U+0044
+0x45	U+0045 U+00c8 U+00ca U+00cb
+0x46	U+0046
+0x47	U+0047
+0x48	U+0048
+0x49	U+0049 U+00cc U+00cd U+00ce U+00cf
+0x4a	U+004a
+# U+212a: Letterlike Symbols "KELVIN SIGN"
+0x4b	U+004b U+212a
+0x4c	U+004c
+0x4d	U+004d
+0x4e	U+004e
+0x4f	U+004f U+00d2 U+00d3 U+00d4 U+00d5
+0x50	U+0050
+0x51	U+0051
+# U+00ae: Latin-1 Supplement "REGISTERED SIGN"
+0x52	U+0052 U+00ae
+0x53	U+0053
+0x54	U+0054
+0x55	U+0055 U+00d9 U+00da U+00db
+0x56	U+0056
+0x57	U+0057
+0x58	U+0058
+0x59	U+0059 U+00dd
+0x5a	U+005a
+0x5b	U+005b
+0x5c	U+00a5	# Latin-1 Supplement "YEN SIGN"
+0x5d	U+005d
+0x5e	U+005e
+0x5f	U+005f U+f804
+0x60	U+0060 U+2035
+0x61	U+0061 U+00e3
+0x62	U+0062
+0x63	U+0063
+0x64	U+0064
+0x65	U+0065
+0x66	U+0066
+0x67	U+0067
+0x68	U+0068
+0x69	U+0069
+0x6a	U+006a
+0x6b	U+006b
+0x6c	U+006c
+0x6d	U+006d
+0x6e	U+006e
+0x6f	U+006f U+00f5
+0x70	U+0070
+0x71	U+0071
+0x72	U+0072
+0x73	U+0073
+0x74	U+0074
+0x75	U+0075
+0x76	U+0076
+0x77	U+0077
+0x78	U+0078 U+00d7
+0x79	U+0079 U+00fd
+0x7a	U+007a
+0x7b	U+007b
+# U+00a6: Latin-1 Supplement "BROKEN (VERTICAL) BAR"
+0x7c	U+007c U+00a6
+0x7d	U+007d
+0x7e	U+007e
+
+# kuhaku
+0x7f	# U+2302
+
+# Block Elements.
+0x80	U+2581	# LOWER ONE EIGHTH BLOCK
+0x81	U+2582	# LOWER ONE QUARTER BLOCK
+0x82	U+2583	# LOWER THREE EIGHTHS BLOCK
+0x83	U+2584	# LOWER HALF BLOCK
+0x84	U+2585	# LOWER FIVE EIGHTHS BLOCK
+0x85	U+2586	# LOWER THREE QUARTERS BLOCK
+0x86	U+2587	# LOWER SEVEN EIGHTHS BLOCK
+0x87	U+2588	# FULL BLOCK
+0x88	U+258f	# LEFT ONE EIGHTH BLOCK
+0x89	U+258e	# LEFT ONE QUARTER BLOCK
+0x8a	U+258d	# LEFT THREE EIGHTHS BLOCK
+0x8b	U+258c	# LEFT HALF BLOCK
+0x8c	U+258b	# LEFT FIVE EIGHTHS BLOCK
+0x8d	U+258a	# LEFT THREE QUARTERS BLOCK
+0x8e	U+2589	# LEFT SEVEN EIGHTHS BLOCK
+
+# Box Drawing.
+0x8f	U+253c
+0x90	U+2534
+0x91	U+252c
+0x92	U+2524
+0x93	U+251c
+0x94	U+203e	# General Punctuation "OVERLINE" (= "SPACING OVERSCORE")
+0x95	U+2500	# Box Drawing "BOX DRAWING LIGHT HORIZONTAL"
+0x96	U+2502	# Box Drawing "BOX DRAWING LIGHT VERTICAL"
+0x96	U+ffe8	# Halfwidth symbol variants "HALFWIDTH FORMS LIGHT VERTICAL"
+0x97	U+2595	# Block Elements "RIGHT ONE EIGHTH BLOCK"
+0x98	U+250c
+0x99	U+2510
+0x9a	U+2514
+0x9b	U+2518
+
+0x9c	U+256d	# "BOX DRAWING LIGHT ARC DOWN AND RIGHT"
+0x9d	U+256e	# "BOX DRAWING LIGHT ARC DOWN AND LEFT"
+0x9e	U+2570	# "BOX DRAWING LIGHT ARC UP AND RIGHT"
+0x9f	U+256f	# "BOX DRAWING LIGHT ARC UP AND LEFT"
+
+0xa0	# another whitespace
+
+# Halfwidth CJK punctuation
+0xa1 - 0xa4	U+ff61 - U+ff64
+
+# Halfwidth Katakana variants
+0xa5 - 0xdf	U+ff65 - U+ff9f
+0xa5	U+00b7	# Latin-1 Supplement "MIDDLE DOT"
+0xdf	U+00b0	# Latin-1 Supplement "DEGREE SIGN"
+
+# Box Drawing
+0xe0	U+2550	# "BOX DRAWING DOUBLE HORIZONTAL"
+0xe1	U+255e	# "BOX DRAWING VERTICAL SINGLE AND RIGHT DOUBLE"
+0xe2	U+256a	# "BOX DRAWING VERTICAL SINGLE AND HORIZONTAL DOUBLE"
+0xe3	U+2561	# "BOX DRAWING VERTICAL SINGLE AND LEFT DOUBLE"
+
+# Geometric Shapes
+0xe4	U+25e2	# "BLACK LOWER RIGHT TRIANGLE"
+0xe5	U+25e3	# "BLACK LOWER LEFT TRIANGLE"
+0xe6	U+25e5	# "BLACK UPPER RIGHT TRIANGLE"
+0xe7	U+25e4	# "BLACK UPPER LEFT TRIANGLE"
+
+# Playing card symbols
+0xe8	U+2660	# "BLACK SPADE SUIT"
+0xe9	U+2665	# "BLACK HEART SUIT"
+0xea	U+2666	# "BLACK DIAMOND SUIT"
+0xeb	U+2663	# "BLACK CLUB SUIT"
+
+# Geometric Shapes
+0xec	U+25cf	# "BLACK CIRCLE"
+0xed	U+25cb U+25ef	# "WHITE CIRCLE", "LARGE CIRCLE"
+
+# Box Drawing
+0xee	U+2571	# "BOX DRAWING LIGHT DIAGONAL UPPER RIGHT TO LOWER LEFT"
+0xef	U+2572	# "BOX DRAWING LIGHT DIAGONAL UPPER LEFT TO LOWER RIGHT"
+0xf0	U+2573	# "BOX DRAWING LIGHT DIAGONAL CROSS"
+
+# CJK Unified Ideographs (XXX - should these be here?)
+0xf1	U+5186
+0xf2	U+5e74
+0xf3	U+6708
+0xf4	U+65e5
+0xf5	U+6642
+0xf6	U+5206
+0xf7	U+79d2
+
+# unassigned
+0xf8
+0xf9
+0xfa
+0xfb
+
+0xfc	U+005c	# "REVERSE SOLIDUS" / "BACKSLASH"
+0xfc	U+2216	# Mathematical Operators "SET MINUS"
+
+# unassigned
+0xfd
+0xfe
+0xff
+
+# End of pc9800.uni
diff -Nru linux-2.5.61-ac1/drivers/char/vt.c linux98-2.5.61/drivers/char/vt.c
--- linux-2.5.61-ac1/drivers/char/vt.c	2003-02-18 08:58:23.000000000 +0900
+++ linux98-2.5.61/drivers/char/vt.c	2003-02-18 11:11:11.000000000 +0900
@@ -107,6 +107,10 @@
 
 #include "console_macros.h"
 
+#ifdef CONFIG_X86_PC9800
+#include "console_pc9800.h"
+extern unsigned short translations[][256];
+#endif
 
 const struct consw *conswitchp;
 
@@ -301,7 +305,7 @@
 		xx = nxx; yy = nyy;
 	}
 	for(;;) {
-		u16 attrib = scr_readw(p) & 0xff00;
+		vram_char_t attrib = scr_readw(p) & 0xff00;
 		int startx = xx;
 		u16 *q = p;
 		while (xx < video_num_columns && count) {
@@ -387,6 +391,8 @@
 {
 	attr = build_attr(currcons, color, intensity, blink, underline, reverse ^ decscnm);
 	video_erase_char = (build_attr(currcons, color, 1, blink, 0, decscnm) << 8) | ' ';
+	if (pc98 && decscnm)
+		video_erase_char |= 0x0400; /* reverse */
 }
 
 /* Note: inverting the screen twice should revert to the original state */
@@ -403,7 +409,7 @@
 	else {
 		u16 *q = p;
 		int cnt = count;
-		u16 a;
+		vram_char_t a;
 
 		if (!can_do_color) {
 			while (cnt--) {
@@ -437,7 +443,7 @@
 void complement_pos(int currcons, int offset)
 {
 	static unsigned short *p;
-	static unsigned short old;
+	static vram_char_t old;
 	static unsigned short oldx, oldy;
 
 	if (p) {
@@ -448,10 +454,15 @@
 	if (offset == -1)
 		p = NULL;
 	else {
-		unsigned short new;
+		vram_char_t new;
 		p = screenpos(currcons, offset, 1);
 		old = scr_readw(p);
+#ifdef CONFIG_FB_EGC
+		new = (old & 0xff0000ff) | ((old & 0xf000) >> 4)
+			| ((old & 0xf00) << 4);
+#else
 		new = old ^ complement_mask;
+#endif
 		scr_writew(new, p);
 		if (DO_UPDATE) {
 			oldx = (offset >> 1) % video_num_columns;
@@ -510,7 +521,7 @@
 
 static void add_softcursor(int currcons)
 {
-	int i = scr_readw((u16 *) pos);
+	vram_char_t i = scr_readw((u16 *) pos);
 	u32 type = cursor_type;
 
 	if (! (type & 0x10)) return;
@@ -646,8 +657,12 @@
     complement_mask = 0;
     can_do_color = 0;
     sw->con_init(vc_cons[currcons].d, init);
-    if (!complement_mask)
-        complement_mask = can_do_color ? 0x7700 : 0x0800;
+    if (!complement_mask) {
+	if (pc98)
+        	complement_mask = 0x0400;
+	else
+        	complement_mask = can_do_color ? 0x7700 : 0x0800;
+    }
     s_complement_mask = complement_mask;
     video_size_row = video_num_columns<<1;
     screenbuf_size = video_num_lines*video_size_row;
@@ -679,7 +694,7 @@
 	    visual_init(currcons, 1);
 	    if (!*vc_cons[currcons].d->vc_uni_pagedir_loc)
 		con_set_default_unimap(currcons);
-	    q = (long)kmalloc(screenbuf_size, GFP_KERNEL);
+	    q = (long)kmalloc(screenbuf_size + (pc98 ? screenbuf_size : 0), GFP_KERNEL);
 	    if (!q) {
 		kfree((char *) p);
 		vc_cons[currcons].d = NULL;
@@ -732,7 +747,7 @@
 	if (new_cols == video_num_columns && new_rows == video_num_lines)
 		return 0;
 
-	newscreen = (unsigned short *) kmalloc(new_screen_size, GFP_USER);
+	newscreen = (unsigned short *) kmalloc(new_screen_size + (pc98 ? new_screen_size : 0), GFP_USER);
 	if (!newscreen)
 		return -ENOMEM;
 
@@ -1261,6 +1276,10 @@
 /* console_sem is held */
 static void setterm_command(int currcons)
 {
+	if (sw->con_setterm_command
+	    && sw->con_setterm_command(vc_cons[currcons].d))
+		return;
+
 	switch(par[0]) {
 		case 1:	/* set color for underline mode */
 			if (can_do_color && par[1] < 16) {
@@ -2427,9 +2446,17 @@
 		vc_cons[currcons].d->vc_palette[k++] = default_grn[j] ;
 		vc_cons[currcons].d->vc_palette[k++] = default_blu[j] ;
 	}
-	def_color       = 0x07;   /* white */
-	ulcolor		= 0x0f;   /* bold white */
-	halfcolor       = 0x08;   /* grey */
+	if (pc98) {
+		def_color	= 0x07;		/* white */
+		def_attr	= 0xE1;
+		ul_attr		= 0x08;		/* underline */
+		half_attr	= 0x00;		/* ignore half color */
+		bold_attr	= 0xC1;		/* yellow */
+	} else {
+		def_color       = 0x07;   /* white */
+		ulcolor		= 0x0f;   /* bold white */
+		halfcolor       = 0x08;   /* grey */
+	}
 	init_waitqueue_head(&vt_cons[currcons]->paste_wait);
 	reset_terminal(currcons, do_clear);
 }
@@ -2470,7 +2497,12 @@
 		vt_cons[currcons] = (struct vt_struct *)
 				alloc_bootmem(sizeof(struct vt_struct));
 		visual_init(currcons, 1);
+#if defined(CONFIG_X86_PC9800) || defined(CONFIG_FB)
+		screenbuf
+			= (unsigned short *) alloc_bootmem(screenbuf_size * 2);
+#else
 		screenbuf = (unsigned short *) alloc_bootmem(screenbuf_size);
+#endif
 		kmalloced = 0;
 		vc_init(currcons, video_num_lines, video_num_columns, 
 			currcons || !sw->con_save_screen);
@@ -2973,9 +3005,12 @@
 /* used by selection */
 u16 screen_glyph(int currcons, int offset)
 {
-	u16 w = scr_readw(screenpos(currcons, offset, 1));
+	vram_char_t w = scr_readw(screenpos(currcons, offset, 1));
 	u16 c = w & 0xff;
 
+	if (pc98)
+		return ((u16)(w >> 16) & 0xff00) | c;
+
 	if (w & hi_font_mask)
 		c |= 0x100;
 	return c;
@@ -3037,8 +3072,10 @@
 EXPORT_SYMBOL(default_red);
 EXPORT_SYMBOL(default_grn);
 EXPORT_SYMBOL(default_blu);
+#ifndef CONFIG_X86_PC9800
 EXPORT_SYMBOL(video_font_height);
 EXPORT_SYMBOL(video_scan_lines);
+#endif
 EXPORT_SYMBOL(vc_cons_allocated);
 EXPORT_SYMBOL(update_region);
 EXPORT_SYMBOL(redraw_screen);
diff -Nru linux/drivers/char/vt_ioctl.c linux98/drivers/char/vt_ioctl.c
--- linux/drivers/char/vt_ioctl.c	2002-12-10 11:46:13.000000000 +0900
+++ linux98/drivers/char/vt_ioctl.c	2002-12-16 13:15:34.000000000 +0900
@@ -63,9 +63,11 @@
 asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int on);
 #endif
 
+#ifndef CONFIG_X86_PC9800
 unsigned int video_font_height;
 unsigned int default_font_height;
 unsigned int video_scan_lines;
+#endif
 
 /*
  * these are the valid i/o ports we're allowed to change. they map all the
@@ -637,6 +639,17 @@
 		return 0;
 	}
 
+#ifdef CONFIG_X86_PC9800
+	case VT_GDC_RESIZE:
+	{
+		if (!perm)
+			return -EPERM; 
+/*		con_adjust_height(0);*/
+		update_screen(console);
+		return 0;
+	}
+#endif 
+
 	case VT_SETMODE:
 	{
 		struct vt_mode tmp;
@@ -830,7 +843,9 @@
 		__get_user(clin, &vtconsize->v_clin);
 		__get_user(vcol, &vtconsize->v_vcol);
 		__get_user(ccol, &vtconsize->v_ccol);
+#ifndef CONFIG_X86_PC9800
 		vlin = vlin ? vlin : video_scan_lines;
+#endif
 		if (clin) {
 			if (ll) {
 				if (ll != vlin/clin)
@@ -849,10 +864,12 @@
 		if (clin > 32)
 			return -EINVAL;
 		    
+#ifndef CONFIG_X86_PC9800		    
 		if (vlin)
 			video_scan_lines = vlin;
 		if (clin)
 			video_font_height = clin;
+#endif
 	
 		for (i = 0; i < MAX_NR_CONSOLES; i++)
 			vc_resize(i, cc, ll);
@@ -1022,8 +1039,10 @@
 	vt_cons[new_console]->vt_mode.frsig = 0;
 	vt_cons[new_console]->vt_pid = -1;
 	vt_cons[new_console]->vt_newvt = -1;
+#ifndef CONFIG_X86_PC9800
 	if (!in_interrupt())    /* Via keyboard.c:SAK() - akpm */
 		reset_palette(new_console) ;
+#endif
 }
 
 /*
diff -Nru linux-2.5.59/drivers/video/console/Kconfig linux98-2.5.59/drivers/video/console/Kconfig
--- linux-2.5.59/drivers/video/console/Kconfig	2003-01-17 13:22:14.000000000 +0900
+++ linux98-2.5.59/drivers/video/console/Kconfig	2003-01-17 13:43:44.000000000 +0900
@@ -6,7 +6,7 @@
 
 config VGA_CONSOLE
 	bool "VGA text console"
-	depends on !ARCH_ACORN && !ARCH_EBSA110 || !4xx && !8xx
+	depends on !X86_PC9800 && !ARCH_ACORN && !ARCH_EBSA110 || !4xx && !8xx
 	help
 	  Saying Y here will allow you to use Linux in text mode through a
 	  display that complies with the generic VGA standard. Virtually
@@ -97,6 +97,18 @@
 	  Say Y to build a console driver for Sun machines that uses the
 	  terminal emulation built into their console PROMS.
 
+config GDC_CONSOLE
+	bool "PC-9800 GDC text console"
+	depends on X86_PC9800
+	default y
+	help
+	  This enables support for PC-9800 standard text mode console.
+	  If use NEC PC-9801/PC-9821, Say Y.
+
+config GDC_32BITACCESS
+	bool "Enable 32-bit access to text video RAM"
+	depends on GDC_CONSOLE
+
 config DUMMY_CONSOLE
 	bool
 	depends on PROM_CONSOLE!=y || VGA_CONSOLE!=y || SGI_NEWPORT_CONSOLE!=y
diff -Nru linux/include/linux/console.h linux98/include/linux/console.h
--- linux/include/linux/console.h	2003-02-15 08:51:33.000000000 +0900
+++ linux98/include/linux/console.h	2003-02-20 09:47:41.000000000 +0900
@@ -17,6 +17,13 @@
 #include <linux/types.h>
 #include <linux/kdev_t.h>
 #include <linux/spinlock.h>
+#include <linux/config.h>
+
+#ifdef CONFIG_X86_PC9800
+typedef __u32 vram_char_t;
+#else
+typedef __u16 vram_char_t;
+#endif
 
 struct vc_data;
 struct console_font_op;
@@ -32,7 +39,7 @@
 	void	(*con_init)(struct vc_data *, int);
 	void	(*con_deinit)(struct vc_data *);
 	void	(*con_clear)(struct vc_data *, int, int, int, int);
-	void	(*con_putc)(struct vc_data *, int, int, int);
+	void	(*con_putc)(struct vc_data *, int, vram_char_t, int);
 	void	(*con_putcs)(struct vc_data *, const unsigned short *, int, int, int);
 	void	(*con_cursor)(struct vc_data *, int);
 	int	(*con_scroll)(struct vc_data *, int, int, int, int);
@@ -49,6 +56,7 @@
 	void	(*con_invert_region)(struct vc_data *, u16 *, int);
 	u16    *(*con_screen_pos)(struct vc_data *, int);
 	unsigned long (*con_getxy)(struct vc_data *, unsigned long, int *, int *);
+	int	(*con_setterm_command)(struct vc_data *);
 };
 
 extern const struct consw *conswitchp;
@@ -56,6 +64,7 @@
 extern const struct consw dummy_con;	/* dummy console buffer */
 extern const struct consw fb_con;	/* frame buffer based console */
 extern const struct consw vga_con;	/* VGA text console */
+extern const struct consw gdc_con;	/* PC-9800 GDC text console */
 extern const struct consw newport_con;	/* SGI Newport console  */
 extern const struct consw prom_con;	/* SPARC PROM console */
 
diff -Nru linux/include/linux/console_struct.h linux98/include/linux/console_struct.h
--- linux/include/linux/console_struct.h	2002-12-10 11:45:40.000000000 +0900
+++ linux98/include/linux/console_struct.h	2002-12-16 13:25:55.000000000 +0900
@@ -9,6 +9,9 @@
  * to achieve effects such as fast scrolling by changing the origin.
  */
 
+#include <linux/config.h>
+#include <linux/console.h>
+
 #define NPAR 16
 
 struct vc_data {
@@ -25,10 +28,14 @@
 	unsigned char	vc_s_color;		/* Saved foreground & background */
 	unsigned char	vc_ulcolor;		/* Color for underline mode */
 	unsigned char	vc_halfcolor;		/* Color for half intensity mode */
+	unsigned char	vc_def_attr;		/* Default attributes */
+	unsigned char	vc_ul_attr;		/* Attribute for underline mode */
+	unsigned char	vc_half_attr;		/* Attribute for half intensity mode */
+	unsigned char	vc_bold_attr;		/* Attribute for bold mode */
 	unsigned short	vc_complement_mask;	/* [#] Xor mask for mouse pointer */
 	unsigned short	vc_hi_font_mask;	/* [#] Attribute set for upper 256 chars of font or 0 if not supported */
 	struct console_font_op vc_font;		/* Current VC font set */
-	unsigned short	vc_video_erase_char;	/* Background erase character */
+	vram_char_t	vc_video_erase_char;	/* Background erase character */
 	unsigned short	vc_s_complement_mask;	/* Saved mouse pointer mask */
 	unsigned int	vc_x, vc_y;		/* Cursor position */
 	unsigned int	vc_top, vc_bottom;	/* Scrolling region */
@@ -106,6 +113,10 @@
 #define CUR_HWMASK	0x0f
 #define CUR_SWMASK	0xfff0
 
+#ifdef CONFIG_X86_PC9800
+#define CUR_DEFAULT CUR_BLOCK
+#else
 #define CUR_DEFAULT CUR_UNDERLINE
+#endif
 
 #define CON_IS_VISIBLE(conp) (*conp->vc_display_fg == conp)
diff -Nru linux/include/linux/tty.h linux98/include/linux/tty.h
--- linux/include/linux/tty.h	Sat Oct 19 13:01:54 2002
+++ linux98/include/linux/tty.h	Mon Oct 21 14:22:18 2002
@@ -123,6 +123,10 @@
 
 #define VIDEO_TYPE_PMAC		0x60	/* PowerMacintosh frame buffer. */
 
+#define VIDEO_TYPE_98NORMAL	0xa4	/* NEC PC-9800 normal */
+#define VIDEO_TYPE_9840		0xa5	/* NEC PC-9800 normal 40 lines */
+#define VIDEO_TYPE_98HIRESO	0xa6	/* NEC PC-9800 hireso */
+
 /*
  * This character is the same as _POSIX_VDISABLE: it cannot be used as
  * a c_cc[] character, but indicates that a particular special character
diff -Nru linux/include/linux/vt.h linux98/include/linux/vt.h
--- linux/include/linux/vt.h	Sat Oct 19 13:02:30 2002
+++ linux98/include/linux/vt.h	Mon Oct 21 14:26:03 2002
@@ -50,5 +50,6 @@
 #define VT_RESIZEX      0x560A  /* set kernel's idea of screensize + more */
 #define VT_LOCKSWITCH   0x560B  /* disallow vt switching */
 #define VT_UNLOCKSWITCH 0x560C  /* allow vt switching */
+#define VT_GDC_RESIZE   0x5698
 
 #endif /* _LINUX_VT_H */
diff -Nru linux/include/linux/vt_buffer.h linux98/include/linux/vt_buffer.h
--- linux/include/linux/vt_buffer.h	Sat Oct 19 13:02:24 2002
+++ linux98/include/linux/vt_buffer.h	Mon Oct 21 14:28:40 2002
@@ -19,6 +19,10 @@
 #include <asm/vga.h>
 #endif
 
+#ifdef CONFIG_GDC_CONSOLE
+#include <asm/gdc.h>
+#endif
+
 #ifndef VT_BUF_HAVE_RW
 #define scr_writew(val, addr) (*(addr) = (val))
 #define scr_readw(addr) (*(addr))

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH] PC-9800 additional for 2.5.61-ac1 (4/21) misc core
  2003-02-20 12:16 [PATCH] PC-9800 additional for 2.5.61-ac1 (0/21) summary Osamu Tomita
                   ` (2 preceding siblings ...)
  2003-02-20 12:23 ` [PATCH] PC-9800 additional for 2.5.61-ac1 (3/21) console Osamu Tomita
@ 2003-02-20 12:24 ` Osamu Tomita
  2003-02-20 12:25 ` [PATCH] PC-9800 additional for 2.5.61-ac1 (5/21) Osamu Tomita
                   ` (15 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Osamu Tomita @ 2003-02-20 12:24 UTC (permalink / raw)
  To: Linux Kernel Mailing List; +Cc: Alan Cox

This is additional patch to support NEC PC-9800 subarchitecture
against 2.5.61-ac1. (4/21)

Small core patches for PC98. I think these are small and clean.

diff -Nru linux/include/asm-i386/io.h linux98/include/asm-i386/io.h
--- linux/include/asm-i386/io.h	2002-10-12 13:22:45.000000000 +0900
+++ linux98/include/asm-i386/io.h	2002-10-12 19:25:19.000000000 +0900
@@ -27,6 +27,8 @@
  *		Linus
  */
 
+#include <linux/config.h>
+
  /*
   *  Bit simplified and optimized by Jan Hubicka
   *  Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999.
@@ -288,7 +290,11 @@
 #ifdef SLOW_IO_BY_JUMPING
 #define __SLOW_DOWN_IO "jmp 1f; 1: jmp 1f; 1:"
 #else
+#ifdef CONFIG_X86_PC9800
+#define __SLOW_DOWN_IO "outb %%al,$0x5f;"
+#else
 #define __SLOW_DOWN_IO "outb %%al,$0x80;"
+#endif
 #endif
 
 static inline void slow_down_io(void) {
diff -Nru linux/include/asm-i386/irq.h linux98/include/asm-i386/irq.h
--- linux/include/asm-i386/irq.h	2002-09-21 00:20:16.000000000 +0900
+++ linux98/include/asm-i386/irq.h	2002-09-21 07:17:56.000000000 +0900
@@ -17,7 +17,11 @@
 
 static __inline__ int irq_cannonicalize(int irq)
 {
+#ifdef CONFIG_X86_PC9800
+	return ((irq == 7) ? 11 : irq);
+#else
 	return ((irq == 2) ? 9 : irq);
+#endif
 }
 
 extern void disable_irq(unsigned int);
diff -Nru linux/include/asm-i386/pc9800.h linux98/include/asm-i386/pc9800.h
--- linux/include/asm-i386/pc9800.h	1970-01-01 09:00:00.000000000 +0900
+++ linux98/include/asm-i386/pc9800.h	2002-08-17 21:50:18.000000000 +0900
@@ -0,0 +1,27 @@
+/*
+ *  PC-9800 machine types.
+ *
+ *  Copyright (C) 1999	TAKAI Kosuke <tak@kmc.kyoto-u.ac.jp>
+ *			(Linux/98 Project)
+ */
+
+#ifndef _ASM_PC9800_H_
+#define _ASM_PC9800_H_
+
+#include <asm/pc9800_sca.h>
+#include <asm/types.h>
+
+#define __PC9800SCA(type, pa)	(*(type *) phys_to_virt(pa))
+#define __PC9800SCA_TEST_BIT(pa, n)	\
+	((__PC9800SCA(u8, pa) & (1U << (n))) != 0)
+
+#define PC9800_HIGHRESO_P()	__PC9800SCA_TEST_BIT(PC9800SCA_BIOS_FLAG, 3)
+#define PC9800_8MHz_P()		__PC9800SCA_TEST_BIT(PC9800SCA_BIOS_FLAG, 7)
+
+				/* 0x2198 is 98 21 on memory... */
+#define PC9800_9821_P()		(__PC9800SCA(u16, PC9821SCA_ROM_ID) == 0x2198)
+
+/* Note PC9821_...() are valid only when PC9800_9821_P() was true. */
+#define PC9821_IDEIF_DOUBLE_P()	__PC9800SCA_TEST_BIT(PC9821SCA_ROM_FLAG4, 4)
+
+#endif
diff -Nru linux/include/linux/kernel.h linux98/include/linux/kernel.h
--- linux/include/linux/kernel.h	2003-01-14 14:58:03.000000000 +0900
+++ linux98/include/linux/kernel.h	2003-01-14 23:11:42.000000000 +0900
@@ -224,4 +224,10 @@
 #define __FUNCTION__ (__func__)
 #endif
 
+#ifdef CONFIG_X86_PC9800
+#define pc98 1
+#else
+#define pc98 0
+#endif
+
 #endif

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH] PC-9800 additional for 2.5.61-ac1 (5/21)
  2003-02-20 12:16 [PATCH] PC-9800 additional for 2.5.61-ac1 (0/21) summary Osamu Tomita
                   ` (3 preceding siblings ...)
  2003-02-20 12:24 ` [PATCH] PC-9800 additional for 2.5.61-ac1 (4/21) misc core Osamu Tomita
@ 2003-02-20 12:25 ` Osamu Tomita
  2003-02-20 12:26 ` [PATCH] PC-9800 additional for 2.5.61-ac1 (6/21) fs/patition Osamu Tomita
                   ` (14 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Osamu Tomita @ 2003-02-20 12:25 UTC (permalink / raw)
  To: Linux Kernel Mailing List; +Cc: Alan Cox

This is additional patch to support NEC PC-9800 subarchitecture
against 2.5.61-ac1. (5/21)

DMA support for PC98.

diff -Nru linux/include/asm-i386/dma.h linux98/include/asm-i386/dma.h
--- linux/include/asm-i386/dma.h	2002-07-21 04:52:59.000000000 +0900
+++ linux98/include/asm-i386/dma.h	2002-08-17 22:15:06.000000000 +0900
@@ -10,6 +10,9 @@
 
 #include <linux/config.h>
 #include <linux/spinlock.h>	/* And spinlocks */
+#ifdef CONFIG_X86_PC9800
+#include <asm/pc9800_dma.h>
+#else /* !CONFIG_X86_PC9800 */
 #include <asm/io.h>		/* need byte IO */
 #include <linux/delay.h>
 
@@ -72,8 +75,10 @@
 
 #define MAX_DMA_CHANNELS	8
 
+#ifndef CONFIG_X86_PC9800
 /* The maximum address that we can perform a DMA transfer to on this platform */
 #define MAX_DMA_ADDRESS      (PAGE_OFFSET+0x1000000)
+#endif
 
 /* 8237 DMA controllers */
 #define IO_DMA1_BASE	0x00	/* 8 bit slave DMA, channels 0..3 */
@@ -295,4 +300,6 @@
 #define isa_dma_bridge_buggy 	(0)
 #endif
 
+#endif /* CONFIG_X86_PC9800 */
+
 #endif /* _ASM_DMA_H */
diff -Nru linux/include/asm-i386/pc9800_dma.h linux98/include/asm-i386/pc9800_dma.h
--- linux/include/asm-i386/pc9800_dma.h	1970-01-01 09:00:00.000000000 +0900
+++ linux98/include/asm-i386/pc9800_dma.h	2002-08-17 21:15:01.000000000 +0900
@@ -0,0 +1,238 @@
+/* $Id: dma.h,v 1.7 1992/12/14 00:29:34 root Exp root $
+ * linux/include/asm/dma.h: Defines for using and allocating dma channels.
+ * Written by Hennus Bergman, 1992.
+ * High DMA channel support & info by Hannu Savolainen
+ * and John Boyd, Nov. 1992.
+ */
+
+#ifndef _ASM_PC9800_DMA_H
+#define _ASM_PC9800_DMA_H
+
+#include <linux/config.h>
+#include <asm/io.h>		/* need byte IO */
+#include <linux/delay.h>
+
+
+#ifdef HAVE_REALLY_SLOW_DMA_CONTROLLER
+#define dma_outb	outb_p
+#else
+#define dma_outb	outb
+#endif
+
+#define dma_inb		inb
+
+/*
+ * NOTES about DMA transfers:
+ *
+ *  controller 1: channels 0-3, byte operations, ports 00-1F
+ *  controller 2: channels 4-7, word operations, ports C0-DF
+ *
+ *  - ALL registers are 8 bits only, regardless of transfer size
+ *  - channel 4 is not used - cascades 1 into 2.
+ *  - channels 0-3 are byte - addresses/counts are for physical bytes
+ *  - channels 5-7 are word - addresses/counts are for physical words
+ *  - transfers must not cross physical 64K (0-3) or 128K (5-7) boundaries
+ *  - transfer count loaded to registers is 1 less than actual count
+ *  - controller 2 offsets are all even (2x offsets for controller 1)
+ *  - page registers for 5-7 don't use data bit 0, represent 128K pages
+ *  - page registers for 0-3 use bit 0, represent 64K pages
+ *
+ * DMA transfers are limited to the lower 16MB of _physical_ memory.  
+ * Note that addresses loaded into registers must be _physical_ addresses,
+ * not logical addresses (which may differ if paging is active).
+ *
+ *  Address mapping for channels 0-3:
+ *
+ *   A23 ... A16 A15 ... A8  A7 ... A0    (Physical addresses)
+ *    |  ...  |   |  ... |   |  ... |
+ *    |  ...  |   |  ... |   |  ... |
+ *    |  ...  |   |  ... |   |  ... |
+ *   P7  ...  P0  A7 ... A0  A7 ... A0   
+ * |    Page    | Addr MSB | Addr LSB |   (DMA registers)
+ *
+ *  Address mapping for channels 5-7:
+ *
+ *   A23 ... A17 A16 A15 ... A9 A8 A7 ... A1 A0    (Physical addresses)
+ *    |  ...  |   \   \   ... \  \  \  ... \  \
+ *    |  ...  |    \   \   ... \  \  \  ... \  (not used)
+ *    |  ...  |     \   \   ... \  \  \  ... \
+ *   P7  ...  P1 (0) A7 A6  ... A0 A7 A6 ... A0   
+ * |      Page      |  Addr MSB   |  Addr LSB  |   (DMA registers)
+ *
+ * Again, channels 5-7 transfer _physical_ words (16 bits), so addresses
+ * and counts _must_ be word-aligned (the lowest address bit is _ignored_ at
+ * the hardware level, so odd-byte transfers aren't possible).
+ *
+ * Transfer count (_not # bytes_) is limited to 64K, represented as actual
+ * count - 1 : 64K => 0xFFFF, 1 => 0x0000.  Thus, count is always 1 or more,
+ * and up to 128K bytes may be transferred on channels 5-7 in one operation. 
+ *
+ */
+
+#define MAX_DMA_CHANNELS	4
+
+/* The maximum address that we can perform a DMA transfer to on this platform */
+#define MAX_DMA_ADDRESS      (~0UL)
+
+/* 8237 DMA controllers */
+#define IO_DMA_BASE		0x01
+
+/* DMA controller registers */
+#define DMA_CMD_REG			((IO_DMA_BASE)+0x10) /* command register (w) */
+#define DMA_STAT_REG		((IO_DMA_BASE)+0x10) /* status register (r) */
+#define DMA_REQ_REG			((IO_DMA_BASE)+0x12) /* request register (w) */
+#define DMA_MASK_REG		((IO_DMA_BASE)+0x14) /* single-channel mask (w) */
+#define DMA_MODE_REG		((IO_DMA_BASE)+0x16) /* mode register (w) */
+#define DMA_CLEAR_FF_REG	((IO_DMA_BASE)+0x18) /* clear pointer flip-flop (w) */
+#define DMA_TEMP_REG		((IO_DMA_BASE)+0x1A) /* Temporary Register (r) */
+#define DMA_RESET_REG		((IO_DMA_BASE)+0x1A) /* Master Clear (w) */
+#define DMA_CLR_MASK_REG	((IO_DMA_BASE)+0x1C) /* Clear Mask */
+#define DMA_MASK_ALL_REG	((IO_DMA_BASE)+0x1E) /* all-channels mask (w) */
+
+#define DMA_PAGE_0			0x27	/* DMA page registers */
+#define DMA_PAGE_1			0x21
+#define DMA_PAGE_2			0x23
+#define DMA_PAGE_3			0x25
+
+#define DMA_Ex_PAGE_0		0xe05	/* DMA Extended page reg base */
+#define DMA_Ex_PAGE_1		0xe07
+#define DMA_Ex_PAGE_2		0xe09
+#define DMA_Ex_PAGE_3		0xe0b
+
+#define DMA_MODE_READ	0x44	/* I/O to memory, no autoinit, increment, single mode */
+#define DMA_MODE_WRITE	0x48	/* memory to I/O, no autoinit, increment, single mode */
+#define DMA_AUTOINIT	0x10
+
+extern spinlock_t  dma_spin_lock;
+
+static __inline__ unsigned long claim_dma_lock(void)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&dma_spin_lock, flags);
+	return flags;
+}
+
+static __inline__ void release_dma_lock(unsigned long flags)
+{
+	spin_unlock_irqrestore(&dma_spin_lock, flags);
+}
+
+/* enable/disable a specific DMA channel */
+static __inline__ void enable_dma(unsigned int dmanr)
+{
+	dma_outb(dmanr,  DMA_MASK_REG);
+}
+
+static __inline__ void disable_dma(unsigned int dmanr)
+{
+	dma_outb(dmanr | 4,  DMA_MASK_REG);
+}
+
+/* Clear the 'DMA Pointer Flip Flop'.
+ * Write 0 for LSB/MSB, 1 for MSB/LSB access.
+ * Use this once to initialize the FF to a known state.
+ * After that, keep track of it. :-)
+ * --- In order to do that, the DMA routines below should ---
+ * --- only be used while holding the DMA lock ! ---
+ */
+static __inline__ void clear_dma_ff(unsigned int dmanr)
+{
+	dma_outb(0,  DMA_CLEAR_FF_REG);
+}
+
+/* set mode (above) for a specific DMA channel */
+static __inline__ void set_dma_mode(unsigned int dmanr, char mode)
+{
+	dma_outb(mode | dmanr,  DMA_MODE_REG);
+}
+
+/* Set only the page register bits of the transfer address.
+ * This is used for successive transfers when we know the contents of
+ * the lower 16 bits of the DMA current address register, but a 64k boundary
+ * may have been crossed.
+ */
+static __inline__ void set_dma_page(unsigned int dmanr, unsigned int pagenr)
+{
+	unsigned char low=pagenr&0xff;
+	unsigned char hi=pagenr>>8;
+
+	switch(dmanr) {
+		case 0:
+			dma_outb(low, DMA_PAGE_0);
+			dma_outb(hi, DMA_Ex_PAGE_0);
+			break;
+		case 1:
+			dma_outb(low, DMA_PAGE_1);
+			dma_outb(hi, DMA_Ex_PAGE_1);
+			break;
+		case 2:
+			dma_outb(low, DMA_PAGE_2);
+			dma_outb(hi, DMA_Ex_PAGE_2);
+			break;
+		case 3:
+			dma_outb(low, DMA_PAGE_3);
+			dma_outb(hi, DMA_Ex_PAGE_3);
+			break;
+	}
+}
+
+/* Set transfer address & page bits for specific DMA channel.
+ * Assumes dma flipflop is clear.
+ */
+static __inline__ void set_dma_addr(unsigned int dmanr, unsigned int a)
+{
+	set_dma_page(dmanr, a>>16);
+	dma_outb( a & 0xff, ((dmanr&3)<<2) + IO_DMA_BASE );
+	dma_outb( (a>>8) & 0xff, ((dmanr&3)<<2) + IO_DMA_BASE );
+}
+
+
+/* Set transfer size (max 64k for DMA1..3, 128k for DMA5..7) for
+ * a specific DMA channel.
+ * You must ensure the parameters are valid.
+ * NOTE: from a manual: "the number of transfers is one more
+ * than the initial word count"! This is taken into account.
+ * Assumes dma flip-flop is clear.
+ * NOTE 2: "count" represents _bytes_ and must be even for channels 5-7.
+ */
+static __inline__ void set_dma_count(unsigned int dmanr, unsigned int count)
+{
+	count--;
+	dma_outb( count & 0xff, ((dmanr&3)<<2) + 2 + IO_DMA_BASE );
+	dma_outb( (count>>8) & 0xff, ((dmanr&3)<<2) + 2 + IO_DMA_BASE );
+}
+
+
+/* Get DMA residue count. After a DMA transfer, this
+ * should return zero. Reading this while a DMA transfer is
+ * still in progress will return unpredictable results.
+ * If called before the channel has been used, it may return 1.
+ * Otherwise, it returns the number of _bytes_ left to transfer.
+ *
+ * Assumes DMA flip-flop is clear.
+ */
+static __inline__ int get_dma_residue(unsigned int dmanr)
+{
+	/* using short to get 16-bit wrap around */
+	unsigned short count;
+
+	count = 1 + dma_inb(((dmanr&3)<<2) + 2 + IO_DMA_BASE);
+	count += dma_inb(((dmanr&3)<<2) + 2 + IO_DMA_BASE) << 8;
+	
+	return count;
+}
+
+
+/* These are in kernel/dma.c: */
+extern int request_dma(unsigned int dmanr, const char * device_id);	/* reserve a DMA channel */
+extern void free_dma(unsigned int dmanr);	/* release it again */
+
+/* From PCI */
+
+#ifdef CONFIG_PCI
+extern int isa_dma_bridge_buggy;
+#else
+#define isa_dma_bridge_buggy 	(0)
+#endif
+
+#endif /* _ASM_PC9800_DMA_H */
diff -Nru linux/include/asm-i386/scatterlist.h linux98/include/asm-i386/scatterlist.h
--- linux/include/asm-i386/scatterlist.h	2002-04-15 04:18:52.000000000 +0900
+++ linux98/include/asm-i386/scatterlist.h	2002-04-17 10:37:22.000000000 +0900
@@ -1,6 +1,8 @@
 #ifndef _I386_SCATTERLIST_H
 #define _I386_SCATTERLIST_H
 
+#include <linux/config.h>
+
 struct scatterlist {
     struct page		*page;
     unsigned int	offset;
@@ -8,6 +10,10 @@
     unsigned int	length;
 };
 
+#ifdef CONFIG_X86_PC9800
+#define ISA_DMA_THRESHOLD (0xffffffff)
+#else
 #define ISA_DMA_THRESHOLD (0x00ffffff)
+#endif
 
 #endif /* !(_I386_SCATTERLIST_H) */
diff -Nru linux/kernel/dma.c linux98/kernel/dma.c
--- linux/kernel/dma.c	2002-08-11 10:41:22.000000000 +0900
+++ linux98/kernel/dma.c	2002-08-21 09:53:59.000000000 +0900
@@ -9,6 +9,7 @@
  *   [It also happened to remove the sizeof(char *) == sizeof(int)
  *   assumption introduced because of those /proc/dma patches. -- Hennus]
  */
+#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
@@ -62,10 +63,12 @@
 	{ 0, 0 },
 	{ 0, 0 },
 	{ 0, 0 },
+#ifndef CONFIG_X86_PC9800
 	{ 1, "cascade" },
 	{ 0, 0 },
 	{ 0, 0 },
 	{ 0, 0 }
+#endif
 };
 
 

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH] PC-9800 additional for 2.5.61-ac1 (6/21) fs/patition
  2003-02-20 12:16 [PATCH] PC-9800 additional for 2.5.61-ac1 (0/21) summary Osamu Tomita
                   ` (4 preceding siblings ...)
  2003-02-20 12:25 ` [PATCH] PC-9800 additional for 2.5.61-ac1 (5/21) Osamu Tomita
@ 2003-02-20 12:26 ` Osamu Tomita
  2003-02-20 12:28 ` [PATCH] PC-9800 additional for 2.5.61-ac1 (7/21) IDE Osamu Tomita
                   ` (13 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Osamu Tomita @ 2003-02-20 12:26 UTC (permalink / raw)
  To: Linux Kernel Mailing List; +Cc: Alan Cox

This is additional patch to support NEC PC-9800 subarchitecture
against 2.5.61-ac1. (6/21)

FAT fs and partition table support for PC98.
FAT fs created by PC9800 MS-DOS has curious media descripter. (BUG?)

diff -Nru linux/fs/fat/inode.c linux98/fs/fat/inode.c
--- linux/fs/fat/inode.c	2003-01-02 12:21:53.000000000 +0900
+++ linux98/fs/fat/inode.c	2003-01-04 20:02:52.000000000 +0900
@@ -939,7 +939,9 @@
 		error = first;
 		goto out_fail;
 	}
-	if (FAT_FIRST_ENT(sb, media) != first) {
+	if (FAT_FIRST_ENT(sb, media) != first
+	    && (!pc98 || media != 0xf8 || (first & 0xff) != 0xfe))
+	{
 		if (!silent) {
 			printk(KERN_ERR "FAT: invalid first entry of FAT "
 			       "(0x%x != 0x%x)\n",
diff -Nru linux/fs/partitions/Kconfig linux98/fs/partitions/Kconfig
--- linux/fs/partitions/Kconfig	2002-11-28 07:36:18.000000000 +0900
+++ linux98/fs/partitions/Kconfig	2002-12-12 14:27:58.000000000 +0900
@@ -177,6 +177,13 @@
 
 	  If unsure, say N.
 
+config NEC98_PARTITION
+	bool "NEC PC-9800 partition table support" if PARTITION_ADVANCED
+	default y if !PARTITION_ADVANCED && X86_PC9800
+	help
+	  Say Y here if you would like to be able to read the hard disk
+	  partition table format used by NEC PC-9800 machines.
+
 config SGI_PARTITION
 	bool "SGI partition support" if PARTITION_ADVANCED
 	default y if !PARTITION_ADVANCED && (SGI_IP22 || SGI_IP27)
diff -Nru linux-2.5.60/fs/partitions/Makefile linux98-2.5.60/fs/partitions/Makefile
--- linux-2.5.60/fs/partitions/Makefile	2003-02-11 03:38:28.000000000 +0900
+++ linux98-2.5.60/fs/partitions/Makefile	2003-02-11 12:50:18.000000000 +0900
@@ -16,3 +16,4 @@
 obj-$(CONFIG_ULTRIX_PARTITION) += ultrix.o
 obj-$(CONFIG_IBM_PARTITION) += ibm.o
 obj-$(CONFIG_EFI_PARTITION) += efi.o
+obj-$(CONFIG_NEC98_PARTITION) += nec98.o msdos.o
diff -Nru linux/fs/partitions/check.c linux98/fs/partitions/check.c
--- linux/fs/partitions/check.c	2003-01-09 13:04:25.000000000 +0900
+++ linux98/fs/partitions/check.c	2003-01-10 10:19:55.000000000 +0900
@@ -28,6 +28,7 @@
 #include "ldm.h"
 #include "mac.h"
 #include "msdos.h"
+#include "nec98.h"
 #include "osf.h"
 #include "sgi.h"
 #include "sun.h"
@@ -51,6 +52,9 @@
 #ifdef CONFIG_LDM_PARTITION
 	ldm_partition,		/* this must come before msdos */
 #endif
+#ifdef CONFIG_NEC98_PARTITION
+	nec98_partition,	/* must be come before `msdos_partition' */
+#endif
 #ifdef CONFIG_MSDOS_PARTITION
 	msdos_partition,
 #endif
diff -Nru linux/fs/partitions/msdos.c linux98/fs/partitions/msdos.c
--- linux/fs/partitions/msdos.c	2002-11-28 07:36:05.000000000 +0900
+++ linux98/fs/partitions/msdos.c	2002-12-12 14:36:18.000000000 +0900
@@ -219,7 +219,7 @@
  * Create devices for BSD partitions listed in a disklabel, under a
  * dos-like partition. See parse_extended() for more information.
  */
-static void
+void
 parse_bsd(struct parsed_partitions *state, struct block_device *bdev,
 		u32 offset, u32 size, int origin, char *flavour,
 		int max_partitions)
diff -Nru linux/fs/partitions/nec98.c linux98/fs/partitions/nec98.c
--- linux/fs/partitions/nec98.c	1970-01-01 09:00:00.000000000 +0900
+++ linux98/fs/partitions/nec98.c	2003-02-13 23:55:09.000000000 +0900
@@ -0,0 +1,270 @@
+/*
+ *  NEC PC-9800 series partition supports
+ *
+ *  Copyright (C) 1999	Kyoto University Microcomputer Club
+ */
+
+#include <linux/config.h>
+#include <linux/fs.h>
+#include <linux/genhd.h>
+#include <linux/kernel.h>
+#include <linux/blk.h>
+#include <linux/major.h>
+
+#include "check.h"
+#include "nec98.h"
+
+/* #ifdef CONFIG_BLK_DEV_IDEDISK */
+#include <linux/ide.h>
+/* #endif */
+
+/* #ifdef CONFIG_BLK_DEV_SD */
+#include "../../drivers/scsi/scsi.h"
+#include "../../drivers/scsi/hosts.h"
+#include <scsi/scsicam.h>
+/* #endif */
+
+struct nec98_partition {
+	__u8	mid;		/* 0x80 - active */
+	__u8	sid;		/* 0x80 - bootable */
+	__u16	pad1;		/* dummy for padding */
+	__u8	ipl_sector;	/* IPL sector	*/
+	__u8	ipl_head;	/* IPL head	*/
+	__u16	ipl_cyl;	/* IPL cylinder	*/
+	__u8	sector;		/* starting sector	*/
+	__u8	head;		/* starting head	*/
+	__u16	cyl;		/* starting cylinder	*/
+	__u8	end_sector;	/* end sector	*/
+	__u8	end_head;	/* end head	*/
+	__u16	end_cyl;	/* end cylinder	*/
+	unsigned char name[16];
+} __attribute__((__packed__));
+
+#define NEC98_BSD_PARTITION_MID 0x14
+#define NEC98_BSD_PARTITION_SID 0x44
+#define MID_SID_16(mid, sid)	(((mid) & 0xFF) | (((sid) & 0xFF) << 8))
+#define NEC98_BSD_PARTITION_MID_SID	\
+	MID_SID_16(NEC98_BSD_PARTITION_MID, NEC98_BSD_PARTITION_SID)
+#define NEC98_VALID_PTABLE_ENTRY(P) \
+	(!(P)->pad1 && (P)->cyl <= (P)->end_cyl)
+
+extern int pc98_bios_param(struct block_device *bdev, int *ip);
+
+static inline int
+is_valid_nec98_partition_table(const struct nec98_partition *ptable,
+				__u8 nsectors, __u8 nheads)
+{
+	int i;
+	int valid = 0;
+
+	for (i = 0; i < 16; i++) {
+		if (!*(__u16 *)&ptable[i])
+			continue;	/* empty slot */
+		if (ptable[i].pad1	/* `pad1' contains junk */
+		    || ptable[i].ipl_sector	>= nsectors
+		    || ptable[i].sector		>= nsectors
+		    || ptable[i].end_sector	>= nsectors
+		    || ptable[i].ipl_head	>= nheads
+		    || ptable[i].head		>= nheads
+		    || ptable[i].end_head	>= nheads
+		    || ptable[i].cyl > ptable[i].end_cyl)
+			return 0;
+		valid = 1;	/* We have a valid partition.  */
+	}
+	/* If no valid PC-9800-style partitions found,
+	   the disk may have other type of partition table.  */
+	return valid;
+}
+
+#ifdef CONFIG_BSD_DISKLABEL
+extern void parse_bsd(struct parsed_partitions *state,
+			struct block_device *bdev,
+			u32 offset, u32 size, int origin, char *flavour,
+			int max_partitions);
+#endif
+
+int nec98_partition(struct parsed_partitions *state, struct block_device *bdev)
+{
+	unsigned int nr;
+	int g_head, g_sect;
+	Sector sect;
+	const struct nec98_partition *part;
+	unsigned char *data;
+	int sector_size = bdev_hardsect_size(bdev);
+	int major = major(to_kdev_t(bdev->bd_dev));
+	int minor = minor(to_kdev_t(bdev->bd_dev));
+
+	switch (major) {
+#if defined CONFIG_BLK_DEV_HD_ONLY
+	case HD_MAJOR:
+	{
+		extern struct hd_i_struct hd_info[2];
+
+		g_head = hd_info[minor >> 6].head;
+		g_sect = hd_info[minor >> 6].sect;
+		break;
+	}
+#endif /* CONFIG_BLK_DEV_HD_ONLY */
+#if defined CONFIG_BLK_DEV_SD || defined CONFIG_BLK_DEV_SD_MODULE
+	case SCSI_DISK0_MAJOR:
+	case SCSI_DISK1_MAJOR:
+	case SCSI_DISK2_MAJOR:
+	case SCSI_DISK3_MAJOR:
+	case SCSI_DISK4_MAJOR:
+	case SCSI_DISK5_MAJOR:
+	case SCSI_DISK6_MAJOR:
+	case SCSI_DISK7_MAJOR:
+	{
+		int diskinfo[3] = { 0, 0, 0 };
+
+		pc98_bios_param(bdev, diskinfo);
+
+		if ((g_head = diskinfo[0]) <= 0)
+			g_head = 8;
+		if ((g_sect = diskinfo[1]) <= 0)
+			g_sect = 17;
+		break;
+	}
+#endif /* CONFIG_BLK_DEV_SD(_MODULE) */
+#if defined CONFIG_BLK_DEV_IDEDISK || defined CONFIG_BLK_DEV_IDEDISK_MODULE
+	case IDE0_MAJOR:
+	case IDE1_MAJOR:
+	case IDE2_MAJOR:
+	case IDE3_MAJOR:
+	case IDE4_MAJOR:
+	case IDE5_MAJOR:
+	case IDE6_MAJOR:
+	case IDE7_MAJOR:
+	case IDE8_MAJOR:
+	case IDE9_MAJOR:
+	{
+		ide_drive_t *drive;
+		unsigned int	h;
+
+		for (h = 0; h < MAX_HWIFS; ++h) {
+			ide_hwif_t  *hwif = &ide_hwifs[h];
+			if (hwif->present && major == hwif->major) {
+				unsigned unit = minor >> PARTN_BITS;
+				if (unit < MAX_DRIVES) {
+					drive = &hwif->drives[unit];
+					if (drive->present) {
+						g_head = drive->head;
+						g_sect = drive->sect;
+						goto found;
+					}
+				}
+				break;
+			}
+		}
+	}
+#endif /* CONFIG_BLK_DEV_IDEDISK(_MODULE) */
+	default:
+		printk(" unsupported disk (major = %u)\n", major);
+		return 0;
+	}
+
+	found:
+	data = read_dev_sector(bdev, 0, &sect);
+	if (!data) {
+		if (warn_no_part)
+			printk(" unable to read partition table\n");
+		return -1;
+	}
+
+	/* magic(?) check */
+	if (*(__u16 *)(data + sector_size - 2) != NEC98_PTABLE_MAGIC) {
+		put_dev_sector(sect);
+		return 0;
+	}
+
+	put_dev_sector(sect);
+	data = read_dev_sector(bdev, 1, &sect);
+	if (!data) {
+		if (warn_no_part)
+			printk(" unable to read partition table\n");
+		return -1;
+	}
+
+	if (!is_valid_nec98_partition_table((struct nec98_partition *)data,
+					     g_sect, g_head)) {
+#if 0
+		if (warn_no_part)
+			printk(" partition table consistency check failed"
+				" (not PC-9800 disk?)\n");
+#endif
+		put_dev_sector(sect);
+		return 0;
+	}
+
+	part = (const struct nec98_partition *)data;
+	for (nr = 0; nr < 16; nr++, part++) {
+		unsigned int start_sect, end_sect;
+
+		if (part->mid == 0 || part->sid == 0)
+			continue;
+
+		if (nr)
+			printk("     ");
+
+		{	/* Print partition name. Fdisk98 might put NUL
+			   characters in partition name... */
+
+			int j;
+			unsigned char *p;
+			unsigned char buf[sizeof (part->name) * 2 + 1];
+
+			for (p = buf, j = 0; j < sizeof (part->name); j++, p++)
+				if ((*p = part->name[j]) < ' ') {
+					*p++ = '^';
+					*p = part->name[j] + '@';
+				}
+
+			*p = 0;
+			printk(" <%s>", buf);
+		}
+		start_sect = (part->cyl * g_head + part->head) * g_sect
+			+ part->sector;
+		end_sect = (part->end_cyl + 1) * g_head * g_sect;
+		if (end_sect <= start_sect) {
+			printk(" (invalid partition info)\n");
+			continue;
+		}
+
+		put_partition(state, nr + 1, start_sect, end_sect - start_sect);
+#ifdef CONFIG_BSD_DISKLABEL
+		if ((*(__u16 *)&part->mid & 0x7F7F)
+		    == NEC98_BSD_PARTITION_MID_SID) {
+			printk("!");
+			/* NEC98_BSD_PARTITION_MID_SID is not valid SYSIND for
+			   IBM PC's MS-DOS partition table, so we simply pass
+			   it to bsd_disklabel_partition;
+			   it will just print `<bsd: ... >'. */
+			parse_bsd(state, bdev, start_sect,
+					end_sect - start_sect, nr + 1,
+					"bsd98", BSD_MAXPARTITIONS);
+		}
+#endif
+		{	/* Pretty size printing. */
+			/* XXX sector size? */
+			unsigned int psize = (end_sect - start_sect) / 2;
+			int unit_char = 'K';
+
+			if (psize > 99999) {
+				psize >>= 10;
+				unit_char = 'M';
+			}
+			printk(" %5d%cB (%5d-%5d)\n", 
+			       psize, unit_char, part->cyl, part->end_cyl);
+		}
+	}
+
+	put_dev_sector(sect);
+
+	return nr ? 1 : 0;
+}
+\f
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff -Nru linux/fs/partitions/nec98.h linux98/fs/partitions/nec98.h
--- linux/fs/partitions/nec98.h	1970-01-01 09:00:00.000000000 +0900
+++ linux98/fs/partitions/nec98.h	2002-07-26 11:10:08.000000000 +0900
@@ -0,0 +1,10 @@
+/*
+ *  NEC PC-9800 series partition supports
+ *
+ *  Copyright (C) 1998-2000	Kyoto University Microcomputer Club
+ */
+
+#define NEC98_PTABLE_MAGIC	0xAA55
+
+extern int nec98_partition(struct parsed_partitions *state,
+				struct block_device *bdev);

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH] PC-9800 additional for 2.5.61-ac1 (7/21) IDE
  2003-02-20 12:16 [PATCH] PC-9800 additional for 2.5.61-ac1 (0/21) summary Osamu Tomita
                   ` (5 preceding siblings ...)
  2003-02-20 12:26 ` [PATCH] PC-9800 additional for 2.5.61-ac1 (6/21) fs/patition Osamu Tomita
@ 2003-02-20 12:28 ` Osamu Tomita
  2003-02-20 12:29 ` [PATCH] PC-9800 additional for 2.5.61-ac1 (8/21) kanji Osamu Tomita
                   ` (12 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Osamu Tomita @ 2003-02-20 12:28 UTC (permalink / raw)
  To: Linux Kernel Mailing List; +Cc: Alan Cox

This is additional patch to support NEC PC-9800 subarchitecture
against 2.5.61-ac1. (7/21)

PC98 standard IDE I/F support.

diff -Nru linux-2.5.60/drivers/ide/Kconfig linux98-2.5.60/drivers/ide/Kconfig
--- linux-2.5.60/drivers/ide/Kconfig	2003-02-11 03:38:31.000000000 +0900
+++ linux98-2.5.60/drivers/ide/Kconfig	2003-02-11 12:54:00.000000000 +0900
@@ -1054,6 +1054,11 @@
 
 	  If unsure, say N.
 
+config BLK_DEV_IDE_PC9800
+	bool
+	depends on X86_PC9800
+	default y
+
 ##if [ "$CONFIG_IDE_TASKFILE_IO" = "y" ]; then
 ##  dep_mbool CONFIG_BLK_DEV_TF_DISK $CONFIG_BLK_DEV_IDEDISK
 ##else
diff -Nru linux/drivers/ide/ide-disk.c linux98/drivers/ide/ide-disk.c
--- linux/drivers/ide/ide-disk.c	2002-11-28 11:52:55.000000000 +0900
+++ linux98/drivers/ide/ide-disk.c	2002-11-28 13:23:54.000000000 +0900
@@ -1604,6 +1604,71 @@
 		blk_queue_max_sectors(&drive->queue, 2048);
 #endif
 
+#ifdef CONFIG_X86_PC9800
+	/* XXX - need more checks */
+	if (!drive->nobios && !drive->scsi && !drive->removable) {
+		/* PC-9800's BIOS do pack drive numbers to be continuous,
+		   so extra work is needed here.  */
+
+		/* drive information passed from boot/setup.S */
+		struct drive_info_struct {
+			u16 cyl;
+			u8 sect, head;
+			u16 ssize;
+		} __attribute__ ((packed));
+		extern struct drive_info_struct drive_info[];
+
+		/* this pointer must be advanced only when *DRIVE is
+		   really hard disk. */
+		static struct drive_info_struct *info = drive_info;
+
+		if (info < &drive_info[4] && info->cyl) {
+			drive->cyl  = drive->bios_cyl  = info->cyl;
+			drive->head = drive->bios_head = info->head;
+			drive->sect = drive->bios_sect = info->sect;
+			++info;
+		}
+	}
+
+	/* =PC98 MEMO=
+	   physical capacity =< 65535*8*17 sect. : H/S=8/17 (fixed)
+	   physical capacity > 65535*8*17 sect. : use physical geometry
+	   (65535*8*17 = 8912760 sectors)
+	*/
+	printk("%s: CHS: physical %d/%d/%d, logical %d/%d/%d, BIOS %d/%d/%d\n",
+	       drive->name,
+	       id->cyls,	id->heads,	id->sectors,
+	       id->cur_cyls,	id->cur_heads,	id->cur_sectors,
+	       drive->bios_cyl,	drive->bios_head,drive->bios_sect);
+	if (!drive->cyl || !drive->head || !drive->sect) {
+		drive->cyl     = drive->bios_cyl  = id->cyls;
+		drive->head    = drive->bios_head = id->heads;
+		drive->sect    = drive->bios_sect = id->sectors;
+		printk("%s: not BIOS-supported device.\n",drive->name);
+	}
+	/* calculate drive capacity, and select LBA if possible */
+	init_idedisk_capacity(drive);
+
+	/*
+	 * if possible, give fdisk access to more of the drive,
+	 * by correcting bios_cyls:
+	 */
+	capacity = idedisk_capacity(drive);
+	if (capacity < 8912760 &&
+	   (drive->head != 8 || drive->sect != 17)) {
+		drive->head = drive->bios_head = 8;
+		drive->sect = drive->bios_sect = 17;
+		drive->cyl  = drive->bios_cyl  =
+			capacity / (drive->bios_head * drive->bios_sect);
+		printk("%s: Fixing Geometry :: CHS=%d/%d/%d to CHS=%d/%d/%d\n",
+			   drive->name,
+			   id->cur_cyls,id->cur_heads,id->cur_sectors,
+			   drive->bios_cyl,drive->bios_head,drive->bios_sect);
+		id->cur_cyls    = drive->bios_cyl;
+		id->cur_heads   = drive->bios_head;
+		id->cur_sectors = drive->bios_sect;
+	}
+#else /* !CONFIG_X86_PC9800 */
 	/* Extract geometry if we did not already have one for the drive */
 	if (!drive->cyl || !drive->head || !drive->sect) {
 		drive->cyl     = drive->bios_cyl  = id->cyls;
@@ -1637,6 +1702,8 @@
 	if ((capacity >= (drive->bios_cyl * drive->bios_sect * drive->bios_head)) &&
 	    (!drive->forced_geom) && drive->bios_sect && drive->bios_head)
 		drive->bios_cyl = (capacity / drive->bios_sect) / drive->bios_head;
+#endif  /* CONFIG_X86_PC9800 */
+
 	printk (KERN_INFO "%s: %ld sectors", drive->name, capacity);
 
 	/* Give size in megabytes (MB), not mebibytes (MiB). */
diff -Nru linux/drivers/ide/ide-probe.c linux98/drivers/ide/ide-probe.c
--- linux/drivers/ide/ide-probe.c	2002-12-16 11:08:10.000000000 +0900
+++ linux98/drivers/ide/ide-probe.c	2002-12-20 14:55:11.000000000 +0900
@@ -573,7 +573,7 @@
 
 	if (hwif->mmio == 2)
 		return 0;
-	addr_errs  = hwif_check_region(hwif, hwif->io_ports[IDE_DATA_OFFSET], 1);
+	addr_errs  = hwif_check_region(hwif, hwif->io_ports[IDE_DATA_OFFSET], pc98 ? 2 : 1);
 	for (i = IDE_ERROR_OFFSET; i <= IDE_STATUS_OFFSET; i++)
 		addr_errs += hwif_check_region(hwif, hwif->io_ports[i], 1);
 	if (hwif->io_ports[IDE_CONTROL_OFFSET])
@@ -622,7 +622,9 @@
 	}
 
 	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++)
-		hwif_request_region(hwif->io_ports[i], 1, hwif->name);
+		hwif_request_region(hwif->io_ports[i],
+					(pc98 && i == IDE_DATA_OFFSET) ? 2 : 1,
+					hwif->name);
 }
 
 //EXPORT_SYMBOL(hwif_register);
@@ -644,6 +646,9 @@
 #if CONFIG_BLK_DEV_PDC4030
 	    (hwif->chipset != ide_pdc4030 || hwif->channel == 0) &&
 #endif /* CONFIG_BLK_DEV_PDC4030 */
+#if CONFIG_BLK_DEV_IDE_PC9800
+	    (hwif->chipset != ide_pc9800 || !hwif->mate->present) &&
+#endif
 	    (hwif_check_regions(hwif))) {
 		u16 msgout = 0;
 		for (unit = 0; unit < MAX_DRIVES; ++unit) {
@@ -973,7 +978,7 @@
 	/* all CPUs; safe now that hwif->hwgroup is set up */
 	spin_unlock_irqrestore(&ide_lock, flags);
 
-#if !defined(__mc68000__) && !defined(CONFIG_APUS) && !defined(__sparc__)
+#if !defined(__mc68000__) && !defined(CONFIG_APUS) && !defined(__sparc__) && !defined(CONFIG_X86_PC9800)
 	printk("%s at 0x%03lx-0x%03lx,0x%03lx on irq %d", hwif->name,
 		hwif->io_ports[IDE_DATA_OFFSET],
 		hwif->io_ports[IDE_DATA_OFFSET]+7,
@@ -983,6 +988,11 @@
 		hwif->io_ports[IDE_DATA_OFFSET],
 		hwif->io_ports[IDE_DATA_OFFSET]+7,
 		hwif->io_ports[IDE_CONTROL_OFFSET], __irq_itoa(hwif->irq));
+#elif defined(CONFIG_X86_PC9800)
+	printk("%s at 0x%03lx-0x%03lx,0x%03lx on irq %d", hwif->name,
+		hwif->io_ports[IDE_DATA_OFFSET],
+		hwif->io_ports[IDE_DATA_OFFSET]+15,
+		hwif->io_ports[IDE_CONTROL_OFFSET], hwif->irq);
 #else
 	printk("%s at %x on irq 0x%08x", hwif->name,
 		hwif->io_ports[IDE_DATA_OFFSET], hwif->irq);
diff -Nru linux/drivers/ide/ide-proc.c linux98/drivers/ide/ide-proc.c
--- linux/drivers/ide/ide-proc.c	2002-09-16 11:18:30.000000000 +0900
+++ linux98/drivers/ide/ide-proc.c	2002-09-16 13:53:42.000000000 +0900
@@ -365,6 +365,9 @@
 		case ide_cy82c693:	name = "cy82c693";	break;
 		case ide_4drives:	name = "4drives";	break;
 		case ide_pmac:		name = "mac-io";	break;
+#ifdef CONFIG_X86_PC9800
+		case ide_pc9800:	name = "pc9800";	break;
+#endif
 		default:		name = "(unknown)";	break;
 	}
 	len = sprintf(page, "%s\n", name);
diff -Nru linux/drivers/ide/ide.c linux98/drivers/ide/ide.c
--- linux/drivers/ide/ide.c	2003-01-09 13:03:59.000000000 +0900
+++ linux98/drivers/ide/ide.c	2003-01-10 10:27:16.000000000 +0900
@@ -547,7 +547,8 @@
 	}
 	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
 		if (hwif->io_ports[i]) {
-			hwif_release_region(hwif->io_ports[i], 1);
+			hwif_release_region(hwif->io_ports[i],
+					(pc98 && i == IDE_DATA_OFFSET) ? 2 : 1);
 		}
 	}
 }
@@ -2011,6 +2012,12 @@
 	}
 #endif /* CONFIG_BLK_DEV_IDEPCI */
 
+#ifdef CONFIG_BLK_DEV_IDE_PC9800
+	{
+		extern void ide_probe_for_pc9800(void);
+		ide_probe_for_pc9800();
+	}
+#endif
 #ifdef CONFIG_ETRAX_IDE
 	{
 		extern void init_e100_ide(void);
diff -Nru linux/drivers/ide/legacy/Makefile linux98/drivers/ide/legacy/Makefile
--- linux/drivers/ide/legacy/Makefile	2002-12-16 11:07:47.000000000 +0900
+++ linux98/drivers/ide/legacy/Makefile	2002-12-17 09:42:08.000000000 +0900
@@ -2,6 +2,7 @@
 obj-$(CONFIG_BLK_DEV_ALI14XX)		+= ali14xx.o
 obj-$(CONFIG_BLK_DEV_DTC2278)		+= dtc2278.o
 obj-$(CONFIG_BLK_DEV_HT6560B)		+= ht6560b.o
+obj-$(CONFIG_BLK_DEV_IDE_PC9800)	+= pc9800.o
 obj-$(CONFIG_BLK_DEV_PDC4030)		+= pdc4030.o
 obj-$(CONFIG_BLK_DEV_QD65XX)		+= qd65xx.o
 obj-$(CONFIG_BLK_DEV_UMC8672)		+= umc8672.o
@@ -15,6 +16,10 @@
 obj-$(CONFIG_BLK_DEV_IDECS)		+= ide-cs.o
 
 # Last of all
+ifneq ($(CONFIG_X86_PC9800),y)
 obj-$(CONFIG_BLK_DEV_HD)		+= hd.o
+else
+obj-$(CONFIG_BLK_DEV_HD)		+= hd98.o
+endif
 
 EXTRA_CFLAGS	:= -Idrivers/ide
diff -Nru linux/drivers/ide/legacy/hd98.c linux98/drivers/ide/legacy/hd98.c
--- linux/drivers/ide/legacy/hd98.c	1970-01-01 09:00:00.000000000 +0900
+++ linux98/drivers/ide/legacy/hd98.c	2002-10-26 15:42:09.000000000 +0900
@@ -0,0 +1,904 @@
+/*
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ *
+ * This is the low-level hd interrupt support. It traverses the
+ * request-list, using interrupts to jump between functions. As
+ * all the functions are called within interrupts, we may not
+ * sleep. Special care is recommended.
+ *
+ *  modified by Drew Eckhardt to check nr of hd's from the CMOS.
+ *
+ *  Thanks to Branko Lankester, lankeste@fwi.uva.nl, who found a bug
+ *  in the early extended-partition checks and added DM partitions
+ *
+ *  IRQ-unmask, drive-id, multiple-mode, support for ">16 heads",
+ *  and general streamlining by Mark Lord.
+ *
+ *  Removed 99% of above. Use Mark's ide driver for those options.
+ *  This is now a lightweight ST-506 driver. (Paul Gortmaker)
+ *
+ *  Modified 1995 Russell King for ARM processor.
+ *
+ *  Bugfix: max_sectors must be <= 255 or the wheels tend to come
+ *  off in a hurry once you queue things up - Paul G. 02/2001
+ */
+
+/* Uncomment the following if you want verbose error reports. */
+/* #define VERBOSE_ERRORS */
+
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/genhd.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/ioport.h>
+#include <linux/mc146818rtc.h> /* CMOS defines */
+#include <linux/init.h>
+#include <linux/blkpg.h>
+#include <linux/hdreg.h>
+
+#define REALLY_SLOW_IO
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+
+#define MAJOR_NR HD_MAJOR
+#define DEVICE_NR(device) (minor(device)>>6)
+#include <linux/blk.h>
+
+#include "io_ports.h"
+
+#ifdef __arm__
+#undef  HD_IRQ
+#endif
+#include <asm/irq.h>
+#ifdef __arm__
+#define HD_IRQ IRQ_HARDDISK
+#endif
+
+/* Hd controller regster ports */
+
+#define HD_DATA		0x640	/* _CTL when writing */
+#define HD_ERROR	0x642	/* see err-bits */
+#define HD_NSECTOR	0x644	/* nr of sectors to read/write */
+#define HD_SECTOR	0x646	/* starting sector */
+#define HD_LCYL		0x648	/* starting cylinder */
+#define HD_HCYL		0x64a	/* high byte of starting cyl */
+#define HD_CURRENT	0x64c	/* 101dhhhh , d=drive, hhhh=head */
+#define HD_STATUS	0x64e	/* see status-bits */
+#define HD_FEATURE	HD_ERROR	/* same io address, read=error, write=feature */
+#define HD_PRECOMP	HD_FEATURE	/* obsolete use of this port - predates IDE */
+#define HD_COMMAND	HD_STATUS	/* same io address, read=status, write=cmd */
+
+#define HD_CMD		0x74c	/* used for resets */
+#define HD_ALTSTATUS	0x74c	/* same as HD_STATUS but doesn't clear irq */
+
+/* Bits of HD_STATUS */
+#define ERR_STAT		0x01
+#define INDEX_STAT		0x02
+#define ECC_STAT		0x04	/* Corrected error */
+#define DRQ_STAT		0x08
+#define SEEK_STAT		0x10
+#define SERVICE_STAT		SEEK_STAT
+#define WRERR_STAT		0x20
+#define READY_STAT		0x40
+#define BUSY_STAT		0x80
+
+/* Bits for HD_ERROR */
+#define MARK_ERR		0x01	/* Bad address mark */
+#define TRK0_ERR		0x02	/* couldn't find track 0 */
+#define ABRT_ERR		0x04	/* Command aborted */
+#define MCR_ERR			0x08	/* media change request */
+#define ID_ERR			0x10	/* ID field not found */
+#define MC_ERR			0x20	/* media changed */
+#define ECC_ERR			0x40	/* Uncorrectable ECC error */
+#define BBD_ERR			0x80	/* pre-EIDE meaning:  block marked bad */
+#define ICRC_ERR		0x80	/* new meaning:  CRC error during transfer */
+
+static spinlock_t hd_lock = SPIN_LOCK_UNLOCKED;
+
+#define TIMEOUT_VALUE	(6*HZ)
+#define	HD_DELAY	0
+
+#define MAX_ERRORS     16	/* Max read/write errors/sector */
+#define RESET_FREQ      8	/* Reset controller every 8th retry */
+#define RECAL_FREQ      4	/* Recalibrate every 4th retry */
+#define MAX_HD		2
+
+#define STAT_OK		(READY_STAT|SEEK_STAT)
+#define OK_STATUS(s)	(((s)&(STAT_OK|(BUSY_STAT|WRERR_STAT|ERR_STAT)))==STAT_OK)
+
+static void recal_intr(void);
+static void bad_rw_intr(void);
+
+static char recalibrate[MAX_HD];
+static char special_op[MAX_HD];
+
+static int reset;
+static int hd_error;
+
+#define SUBSECTOR(block) (CURRENT->current_nr_sectors > 0)
+
+/*
+ *  This struct defines the HD's and their types.
+ */
+struct hd_i_struct {
+	unsigned int head,sect,cyl,wpcom,lzone,ctl;
+};
+	
+#ifdef HD_TYPE
+struct hd_i_struct hd_info[] = { HD_TYPE };
+static int NR_HD = ((sizeof (hd_info))/(sizeof (struct hd_i_struct)));
+#else
+struct hd_i_struct hd_info[MAX_HD];
+static int NR_HD;
+#endif
+
+static struct gendisk *hd_gendisk[MAX_HD];
+
+static struct timer_list device_timer;
+
+#define TIMEOUT_VALUE (6*HZ)
+
+#define SET_TIMER							\
+	do {								\
+		mod_timer(&device_timer, jiffies + TIMEOUT_VALUE);	\
+	} while (0)
+
+static void (*do_hd)(void) = NULL;
+#define SET_HANDLER(x) \
+if ((do_hd = (x)) != NULL) \
+	SET_TIMER; \
+else \
+	del_timer(&device_timer);
+
+
+#if (HD_DELAY > 0)
+unsigned long last_req;
+
+unsigned long read_timer(void)
+{
+        extern spinlock_t i8253_lock;
+	unsigned long t, flags;
+	int i;
+
+	spin_lock_irqsave(&i8253_lock, flags);
+	t = jiffies * 11932;
+    	outb_p(0, PIT_MODE);
+	i = inb_p(PIT_CH0);
+	i |= inb(PIT_CH0) << 8;
+	spin_unlock_irqrestore(&i8253_lock, flags);
+	return(t - i);
+}
+#endif
+
+void __init hd_setup(char *str, int *ints)
+{
+	int hdind = 0;
+
+	if (ints[0] != 3)
+		return;
+	if (hd_info[0].head != 0)
+		hdind=1;
+	hd_info[hdind].head = ints[2];
+	hd_info[hdind].sect = ints[3];
+	hd_info[hdind].cyl = ints[1];
+	hd_info[hdind].wpcom = 0;
+	hd_info[hdind].lzone = ints[1];
+	hd_info[hdind].ctl = (ints[2] > 8 ? 8 : 0);
+	NR_HD = hdind+1;
+}
+
+static void dump_status (const char *msg, unsigned int stat)
+{
+	char devc;
+
+	devc = !blk_queue_empty(QUEUE) ? 'a' + DEVICE_NR(CURRENT->rq_dev) : '?';
+#ifdef VERBOSE_ERRORS
+	printk("hd%c: %s: status=0x%02x { ", devc, msg, stat & 0xff);
+	if (stat & BUSY_STAT)	printk("Busy ");
+	if (stat & READY_STAT)	printk("DriveReady ");
+	if (stat & WRERR_STAT)	printk("WriteFault ");
+	if (stat & SEEK_STAT)	printk("SeekComplete ");
+	if (stat & DRQ_STAT)	printk("DataRequest ");
+	if (stat & ECC_STAT)	printk("CorrectedError ");
+	if (stat & INDEX_STAT)	printk("Index ");
+	if (stat & ERR_STAT)	printk("Error ");
+	printk("}\n");
+	if ((stat & ERR_STAT) == 0) {
+		hd_error = 0;
+	} else {
+		hd_error = inb(HD_ERROR);
+		printk("hd%c: %s: error=0x%02x { ", devc, msg, hd_error & 0xff);
+		if (hd_error & BBD_ERR)		printk("BadSector ");
+		if (hd_error & ECC_ERR)		printk("UncorrectableError ");
+		if (hd_error & ID_ERR)		printk("SectorIdNotFound ");
+		if (hd_error & ABRT_ERR)	printk("DriveStatusError ");
+		if (hd_error & TRK0_ERR)	printk("TrackZeroNotFound ");
+		if (hd_error & MARK_ERR)	printk("AddrMarkNotFound ");
+		printk("}");
+		if (hd_error & (BBD_ERR|ECC_ERR|ID_ERR|MARK_ERR)) {
+			printk(", CHS=%d/%d/%d", (inb(HD_HCYL)<<8) + inb(HD_LCYL),
+				inb(HD_CURRENT) & 0xf, inb(HD_SECTOR));
+			if (!blk_queue_empty(QUEUE))
+				printk(", sector=%ld", CURRENT->sector);
+		}
+		printk("\n");
+	}
+#else
+	printk("hd%c: %s: status=0x%02x.\n", devc, msg, stat & 0xff);
+	if ((stat & ERR_STAT) == 0) {
+		hd_error = 0;
+	} else {
+		hd_error = inb(HD_ERROR);
+		printk("hd%c: %s: error=0x%02x.\n", devc, msg, hd_error & 0xff);
+	}
+#endif
+}
+
+void check_status(void)
+{
+	int i = inb(HD_STATUS);
+
+	if (!OK_STATUS(i)) {
+		dump_status("check_status", i);
+		bad_rw_intr();
+	}
+}
+
+static int controller_busy(void)
+{
+	int retries = 100000;
+	unsigned char status;
+
+	do {
+		status = inb(HD_STATUS);
+	} while ((status & BUSY_STAT) && --retries);
+	return status;
+}
+
+static int status_ok(void)
+{
+	unsigned char status = inb(HD_STATUS);
+
+	if (status & BUSY_STAT)
+		return 1;	/* Ancient, but does it make sense??? */
+	if (status & WRERR_STAT)
+		return 0;
+	if (!(status & READY_STAT))
+		return 0;
+	if (!(status & SEEK_STAT))
+		return 0;
+	return 1;
+}
+
+static int controller_ready(unsigned int drive, unsigned int head)
+{
+	int retry = 100;
+
+	do {
+		if (controller_busy() & BUSY_STAT)
+			return 0;
+		outb(0xA0 | (drive<<4) | head, HD_CURRENT);
+		if (status_ok())
+			return 1;
+	} while (--retry);
+	return 0;
+}
+
+static void hd_out(unsigned int drive,unsigned int nsect,unsigned int sect,
+		unsigned int head,unsigned int cyl,unsigned int cmd,
+		void (*intr_addr)(void))
+{
+	unsigned short port;
+
+#if (HD_DELAY > 0)
+	while (read_timer() - last_req < HD_DELAY)
+		/* nothing */;
+#endif
+	if (reset)
+		return;
+	if (!controller_ready(drive, head)) {
+		reset = 1;
+		return;
+	}
+	SET_HANDLER(intr_addr);
+	outb(hd_info[drive].ctl,HD_CMD);
+	port=HD_DATA + 2;
+	outb(hd_info[drive].wpcom>>2, port); port += 2;
+	outb(nsect, port); port += 2;
+	outb(sect, port); port += 2;
+	outb(cyl, port); port += 2;
+	outb(cyl>>8, port); port += 2;
+	outb(0xA0|(drive<<4)|head, port); port += 2;
+	outb(cmd, port);
+}
+
+static void hd_request (void);
+
+static int drive_busy(void)
+{
+	unsigned int i;
+	unsigned char c;
+
+	for (i = 0; i < 500000 ; i++) {
+		c = inb(HD_STATUS);
+		if ((c & (BUSY_STAT | READY_STAT | SEEK_STAT)) == STAT_OK)
+			return 0;
+	}
+	dump_status("reset timed out", c);
+	return 1;
+}
+
+static void reset_controller(void)
+{
+	int	i;
+
+	outb(4,HD_CMD);
+	for(i = 0; i < 1000; i++) barrier();
+	outb(hd_info[0].ctl & 0x0f,HD_CMD);
+	for(i = 0; i < 1000; i++) barrier();
+	if (drive_busy())
+		printk("hd: controller still busy\n");
+	else if ((hd_error = inb(HD_ERROR)) != 1)
+		printk("hd: controller reset failed: %02x\n",hd_error);
+}
+
+static void reset_hd(void)
+{
+	static int i;
+
+repeat:
+	if (reset) {
+		reset = 0;
+		i = -1;
+		reset_controller();
+	} else {
+		check_status();
+		if (reset)
+			goto repeat;
+	}
+	if (++i < NR_HD) {
+		special_op[i] = recalibrate[i] = 1;
+		hd_out(i,hd_info[i].sect,hd_info[i].sect,hd_info[i].head-1,
+			hd_info[i].cyl,WIN_SPECIFY,&reset_hd);
+		if (reset)
+			goto repeat;
+	} else
+		hd_request();
+}
+
+/*
+ * Ok, don't know what to do with the unexpected interrupts: on some machines
+ * doing a reset and a retry seems to result in an eternal loop. Right now I
+ * ignore it, and just set the timeout.
+ *
+ * On laptops (and "green" PCs), an unexpected interrupt occurs whenever the
+ * drive enters "idle", "standby", or "sleep" mode, so if the status looks
+ * "good", we just ignore the interrupt completely.
+ */
+void unexpected_hd_interrupt(void)
+{
+	unsigned int stat = inb(HD_STATUS);
+
+	if (stat & (BUSY_STAT|DRQ_STAT|ECC_STAT|ERR_STAT)) {
+		dump_status ("unexpected interrupt", stat);
+		SET_TIMER;
+	}
+}
+
+/*
+ * bad_rw_intr() now tries to be a bit smarter and does things
+ * according to the error returned by the controller.
+ * -Mika Liljeberg (liljeber@cs.Helsinki.FI)
+ */
+static void bad_rw_intr(void)
+{
+	int dev;
+
+	if (blk_queue_empty(QUEUE))
+		return;
+	dev = DEVICE_NR(CURRENT->rq_dev);
+	if (++CURRENT->errors >= MAX_ERRORS || (hd_error & BBD_ERR)) {
+		end_request(CURRENT, 0);
+		special_op[dev] = recalibrate[dev] = 1;
+	} else if (CURRENT->errors % RESET_FREQ == 0)
+		reset = 1;
+	else if ((hd_error & TRK0_ERR) || CURRENT->errors % RECAL_FREQ == 0)
+		special_op[dev] = recalibrate[dev] = 1;
+	/* Otherwise just retry */
+}
+
+static inline int wait_DRQ(void)
+{
+	int retries = 100000, stat;
+
+	while (--retries > 0)
+		if ((stat = inb(HD_STATUS)) & DRQ_STAT)
+			return 0;
+	dump_status("wait_DRQ", stat);
+	return -1;
+}
+
+static void read_intr(void)
+{
+	int i, retries = 100000;
+
+	do {
+		i = (unsigned) inb(HD_STATUS);
+		if (i & BUSY_STAT)
+			continue;
+		if (!OK_STATUS(i))
+			break;
+		if (i & DRQ_STAT)
+			goto ok_to_read;
+	} while (--retries > 0);
+	dump_status("read_intr", i);
+	bad_rw_intr();
+	hd_request();
+	return;
+ok_to_read:
+	insw(HD_DATA,CURRENT->buffer,256);
+	CURRENT->sector++;
+	CURRENT->buffer += 512;
+	CURRENT->errors = 0;
+	i = --CURRENT->nr_sectors;
+	--CURRENT->current_nr_sectors;
+#ifdef DEBUG
+	printk("hd%c: read: sector %ld, remaining = %ld, buffer=0x%08lx\n",
+		dev+'a', CURRENT->sector, CURRENT->nr_sectors,
+		(unsigned long) CURRENT->buffer+512);
+#endif
+	if (CURRENT->current_nr_sectors <= 0)
+		end_request(CURRENT, 1);
+	if (i > 0) {
+		SET_HANDLER(&read_intr);
+		return;
+	}
+	(void) inb(HD_STATUS);
+#if (HD_DELAY > 0)
+	last_req = read_timer();
+#endif
+	if (!blk_queue_empty(QUEUE))
+		hd_request();
+	return;
+}
+
+static void write_intr(void)
+{
+	int i;
+	int retries = 100000;
+
+	do {
+		i = (unsigned) inb(HD_STATUS);
+		if (i & BUSY_STAT)
+			continue;
+		if (!OK_STATUS(i))
+			break;
+		if ((CURRENT->nr_sectors <= 1) || (i & DRQ_STAT))
+			goto ok_to_write;
+	} while (--retries > 0);
+	dump_status("write_intr", i);
+	bad_rw_intr();
+	hd_request();
+	return;
+ok_to_write:
+	CURRENT->sector++;
+	i = --CURRENT->nr_sectors;
+	--CURRENT->current_nr_sectors;
+	CURRENT->buffer += 512;
+	if (!i || (CURRENT->bio && !SUBSECTOR(i)))
+		end_request(CURRENT, 1);
+	if (i > 0) {
+		SET_HANDLER(&write_intr);
+		outsw(HD_DATA,CURRENT->buffer,256);
+		local_irq_enable();
+	} else {
+#if (HD_DELAY > 0)
+		last_req = read_timer();
+#endif
+		hd_request();
+	}
+	return;
+}
+
+static void recal_intr(void)
+{
+	check_status();
+#if (HD_DELAY > 0)
+	last_req = read_timer();
+#endif
+	hd_request();
+}
+
+/*
+ * This is another of the error-routines I don't know what to do with. The
+ * best idea seems to just set reset, and start all over again.
+ */
+static void hd_times_out(unsigned long dummy)
+{
+	unsigned int dev;
+
+	do_hd = NULL;
+
+	if (blk_queue_empty(QUEUE))
+		return;
+
+	disable_irq(HD_IRQ);
+	local_irq_enable();
+	reset = 1;
+	dev = DEVICE_NR(CURRENT->rq_dev);
+	printk("hd%c: timeout\n", dev+'a');
+	if (++CURRENT->errors >= MAX_ERRORS) {
+#ifdef DEBUG
+		printk("hd%c: too many errors\n", dev+'a');
+#endif
+		end_request(CURRENT, 0);
+	}
+	local_irq_disable();
+	hd_request();
+	enable_irq(HD_IRQ);
+}
+
+int do_special_op (unsigned int dev)
+{
+	if (recalibrate[dev]) {
+		recalibrate[dev] = 0;
+		hd_out(dev,hd_info[dev].sect,0,0,0,WIN_RESTORE,&recal_intr);
+		return reset;
+	}
+	if (hd_info[dev].head > 16) {
+		printk ("hd%c: cannot handle device with more than 16 heads - giving up\n", dev+'a');
+		end_request(CURRENT, 0);
+	}
+	special_op[dev] = 0;
+	return 1;
+}
+
+/*
+ * The driver enables interrupts as much as possible.  In order to do this,
+ * (a) the device-interrupt is disabled before entering hd_request(),
+ * and (b) the timeout-interrupt is disabled before the sti().
+ *
+ * Interrupts are still masked (by default) whenever we are exchanging
+ * data/cmds with a drive, because some drives seem to have very poor
+ * tolerance for latency during I/O. The IDE driver has support to unmask
+ * interrupts for non-broken hardware, so use that driver if required.
+ */
+static void hd_request(void)
+{
+	unsigned int dev, block, nsect, sec, track, head, cyl;
+
+	if (do_hd)
+		return;
+repeat:
+	del_timer(&device_timer);
+	local_irq_enable();
+
+	if (blk_queue_empty(QUEUE)) {
+		do_hd = NULL;
+		return;
+	}
+
+	if (reset) {
+		local_irq_disable();
+		reset_hd();
+		return;
+	}
+	dev = DEVICE_NR(CURRENT->rq_dev);
+	block = CURRENT->sector;
+	nsect = CURRENT->nr_sectors;
+	if (dev >= NR_HD) {
+		printk("hd: bad disk number: %d\n", dev);
+		end_request(CURRENT, 0);
+		goto repeat;
+	}
+	if (block >= get_capacity(hd_gendisk[dev]) ||
+	    ((block+nsect) > get_capacity(hd_gendisk[dev]))) {
+		printk("%s: bad access: block=%d, count=%d\n",
+			hd_gendisk[dev]->disk_name, block, nsect);
+		end_request(CURRENT, 0);
+		goto repeat;
+	}
+
+	if (special_op[dev]) {
+		if (do_special_op(dev))
+			goto repeat;
+		return;
+	}
+	sec   = block % hd_info[dev].sect + 1;
+	track = block / hd_info[dev].sect;
+	head  = track % hd_info[dev].head;
+	cyl   = track / hd_info[dev].head;
+#ifdef DEBUG
+	printk("hd%c: %sing: CHS=%d/%d/%d, sectors=%d, buffer=0x%08lx\n",
+		dev+'a', (CURRENT->cmd == READ)?"read":"writ",
+		cyl, head, sec, nsect, (unsigned long) CURRENT->buffer);
+#endif
+	if(CURRENT->flags & REQ_CMD) {
+		switch (rq_data_dir(CURRENT)) {
+		case READ:
+			hd_out(dev,nsect,sec,head,cyl,WIN_READ,&read_intr);
+			if (reset)
+				goto repeat;
+			break;
+		case WRITE:
+			hd_out(dev,nsect,sec,head,cyl,WIN_WRITE,&write_intr);
+			if (reset)
+				goto repeat;
+			if (wait_DRQ()) {
+				bad_rw_intr();
+				goto repeat;
+			}
+			outsw(HD_DATA,CURRENT->buffer,256);
+			break;
+		default:
+			printk("unknown hd-command\n");
+			end_request(CURRENT, 0);
+			break;
+		}
+	}
+}
+
+static void do_hd_request (request_queue_t * q)
+{
+	disable_irq(HD_IRQ);
+	hd_request();
+	enable_irq(HD_IRQ);
+}
+
+static int hd_ioctl(struct inode * inode, struct file * file,
+	unsigned int cmd, unsigned long arg)
+{
+	struct hd_geometry *loc = (struct hd_geometry *) arg;
+	int dev;
+
+	if ((!inode) || kdev_none(inode->i_rdev))
+		return -EINVAL;
+	dev = DEVICE_NR(inode->i_rdev);
+	if (dev >= NR_HD)
+		return -EINVAL;
+	switch (cmd) {
+		case HDIO_GETGEO:
+		{
+			struct hd_geometry g; 
+			if (!loc)  return -EINVAL;
+			g.heads = hd_info[dev].head;
+			g.sectors = hd_info[dev].sect;
+			g.cylinders = hd_info[dev].cyl;
+			g.start = get_start_sect(inode->i_bdev);
+			return copy_to_user(loc, &g, sizeof g) ? -EFAULT : 0; 
+		}
+
+		default:
+			return -EINVAL;
+	}
+}
+
+static int hd_open(struct inode * inode, struct file * filp)
+{
+	int target =  DEVICE_NR(inode->i_rdev);
+	if (target >= NR_HD)
+		return -ENODEV;
+	return 0;
+}
+
+/*
+ * Releasing a block device means we sync() it, so that it can safely
+ * be forgotten about...
+ */
+
+extern struct block_device_operations hd_fops;
+
+static void hd_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	void (*handler)(void) = do_hd;
+
+	do_hd = NULL;
+	del_timer(&device_timer);
+	if (!handler)
+		handler = unexpected_hd_interrupt;
+	handler();
+	local_irq_enable();
+}
+
+static struct block_device_operations hd_fops = {
+	.open =		hd_open,
+	.ioctl =	hd_ioctl,
+};
+
+/*
+ * This is the hard disk IRQ description. The SA_INTERRUPT in sa_flags
+ * means we run the IRQ-handler with interrupts disabled:  this is bad for
+ * interrupt latency, but anything else has led to problems on some
+ * machines.
+ *
+ * We enable interrupts in some of the routines after making sure it's
+ * safe.
+ */
+
+static int __init hd_init(void)
+{
+	int drive;
+	if (register_blkdev(MAJOR_NR,"hd",&hd_fops)) {
+		printk("hd: unable to get major %d for hard disk\n",MAJOR_NR);
+		return -1;
+	}
+	blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_hd_request, &hd_lock);
+	blk_queue_max_sectors(BLK_DEFAULT_QUEUE(MAJOR_NR), 255);
+	init_timer(&device_timer);
+	device_timer.function = hd_times_out;
+	blk_queue_hardsect_size(QUEUE, 512);
+
+#ifdef __i386__
+	if (!NR_HD) {
+		extern struct drive_info drive_info;
+		unsigned char *BIOS = (unsigned char *) &drive_info;
+		unsigned long flags;
+#ifndef CONFIG_X86_PC9800
+		int cmos_disks;
+#endif
+
+		for (drive=0 ; drive<2 ; drive++) {
+			hd_info[drive].cyl = *(unsigned short *) BIOS;
+			hd_info[drive].head = *(3+BIOS);
+			hd_info[drive].sect = *(2+BIOS);
+			hd_info[drive].wpcom = 0;
+			hd_info[drive].ctl = *(3+BIOS) > 8 ? 8 : 0;
+			hd_info[drive].lzone = *(unsigned short *) BIOS;
+			if (hd_info[drive].cyl && NR_HD == drive)
+				NR_HD++;
+			BIOS += 6;
+		}
+
+	}
+#endif /* __i386__ */
+#ifdef __arm__
+	if (!NR_HD) {
+		/* We don't know anything about the drive.  This means
+		 * that you *MUST* specify the drive parameters to the
+		 * kernel yourself.
+		 */
+		printk("hd: no drives specified - use hd=cyl,head,sectors"
+			" on kernel command line\n");
+	}
+#endif
+	if (!NR_HD)
+		goto out;
+
+	for (drive=0 ; drive < NR_HD ; drive++) {
+		struct gendisk *disk = alloc_disk();
+		if (!disk)
+			goto Enomem;
+		disk->major = MAJOR_NR;
+		disk->first_minor = drive << 6;
+		disk->minor_shift = 6;
+		disk->fops = &hd_fops;
+		sprintf(disk->disk_name, "hd%c", 'a'+drive);
+		hd_gendisk[drive] = disk;
+	}
+	for (drive=0 ; drive < NR_HD ; drive++) {
+		sector_t size = hd_info[drive].head *
+			hd_info[drive].sect * hd_info[drive].cyl;
+		set_capacity(hd_gendisk[drive], size);
+		printk ("%s: %ldMB, CHS=%d/%d/%d\n",
+			hd_gendisk[drive]->disk_name,
+			size / 2048, hd_info[drive].cyl,
+			hd_info[drive].head, hd_info[drive].sect);
+	}
+
+	if (request_irq(HD_IRQ, hd_interrupt, SA_INTERRUPT, "hd", NULL)) {
+		printk("hd: unable to get IRQ%d for the hard disk driver\n",
+			HD_IRQ);
+		goto out1;
+	}
+
+	if (!request_region(HD_DATA, 2, "hd(data)")) {
+		printk(KERN_WARNING "hd: port 0x%x busy\n", HD_DATA);
+		NR_HD = 0;
+		free_irq(HD_IRQ, NULL);
+		return;
+	}
+
+	if (!request_region(HD_DATA + 2, 1, "hd"))
+	{
+		printk(KERN_WARNING "hd: port 0x%x busy\n", HD_DATA);
+		goto out2;
+	}
+
+	if (!request_region(HD_DATA + 4, 1, "hd"))
+	{
+		printk(KERN_WARNING "hd: port 0x%x busy\n", HD_DATA);
+		goto out3;
+	}
+
+	if (!request_region(HD_DATA + 6, 1, "hd"))
+	{
+		printk(KERN_WARNING "hd: port 0x%x busy\n", HD_DATA);
+		goto out4;
+	}
+
+	if (!request_region(HD_DATA + 8, 1, "hd"))
+	{
+		printk(KERN_WARNING "hd: port 0x%x busy\n", HD_DATA);
+		goto out5;
+	}
+
+	if (!request_region(HD_DATA + 10, 1, "hd"))
+	{
+		printk(KERN_WARNING "hd: port 0x%x busy\n", HD_DATA);
+		goto out6;
+	}
+
+	if (!request_region(HD_DATA + 12, 1, "hd"))
+	{
+		printk(KERN_WARNING "hd: port 0x%x busy\n", HD_DATA);
+		goto out7;
+	}
+
+	if (!request_region(HD_CMD, 1, "hd(cmd)"))
+	{
+		printk(KERN_WARNING "hd: port 0x%x busy\n", HD_CMD);
+		goto out8;
+	}
+
+	if (!request_region(HD_CMD + 2, 1, "hd(cmd)"))
+	{
+		printk(KERN_WARNING "hd: port 0x%x busy\n", HD_CMD);
+		goto out9;
+	}
+
+	for(drive=0; drive < NR_HD; drive++) {
+		struct hd_i_struct *p = hd_info + drive;
+		set_capacity(hd_gendisk[drive], p->head * p->sect * p->cyl);
+		add_disk(hd_gendisk[drive]);
+	}
+	return 0;
+
+out9:
+	release_region(HD_CMD, 1);
+out8:
+	release_region(HD_DATA + 12, 1);
+out7:
+	release_region(HD_DATA + 10, 1);
+out6:
+	release_region(HD_DATA + 8, 1);
+out5:
+	release_region(HD_DATA + 6, 1);
+out4:
+	release_region(HD_DATA + 4, 1);
+out3:
+	release_region(HD_DATA + 2, 1);
+out2:
+	release_region(HD_DATA, 2);
+	free_irq(HD_IRQ, NULL);
+out1:
+	for (drive = 0; drive < NR_HD; drive++)
+		put_disk(hd_gendisk[drive]);
+	NR_HD = 0;
+out:
+	del_timer(&device_timer);
+	unregister_blkdev(MAJOR_NR,"hd");
+	blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
+	return -1;
+Enomem:
+	while (drive--)
+		put_disk(hd_gendisk[drive]);
+	goto out;
+}
+
+static int parse_hd_setup (char *line) {
+	int ints[6];
+
+	(void) get_options(line, ARRAY_SIZE(ints), ints);
+	hd_setup(NULL, ints);
+
+	return 1;
+}
+__setup("hd=", parse_hd_setup);
+
+module_init(hd_init);
diff -Nru linux/drivers/ide/legacy/pc9800.c linux98/drivers/ide/legacy/pc9800.c
--- linux/drivers/ide/legacy/pc9800.c	1970-01-01 09:00:00.000000000 +0900
+++ linux98/drivers/ide/legacy/pc9800.c	2002-10-08 17:06:39.000000000 +0900
@@ -0,0 +1,82 @@
+/*
+ *  ide_pc9800.c
+ *
+ *  Copyright (C) 1997-2000  Linux/98 project,
+ *			     Kyoto University Microcomputer Club.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <linux/ide.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+#include <asm/pc9800.h>
+
+#define PC9800_IDE_BANKSELECT	0x432
+
+#define DEBUG
+
+static void
+pc9800_select(ide_drive_t *drive)
+{
+#ifdef DEBUG
+	byte old;
+
+	/* Too noisy: */
+	/* printk(KERN_DEBUG "pc9800_select(%s)\n", drive->name); */
+
+	outb(0x80, PC9800_IDE_BANKSELECT);
+	old = inb(PC9800_IDE_BANKSELECT);
+	if (old != HWIF(drive)->index)
+		printk(KERN_DEBUG "ide-pc9800: switching bank #%d -> #%d\n",
+			old, HWIF(drive)->index);
+#endif
+	outb(HWIF(drive)->index, PC9800_IDE_BANKSELECT);
+}
+
+void __init
+ide_probe_for_pc9800(void)
+{
+	byte tmp;
+
+	if (!PC9800_9821_P() /* || !PC9821_IDEIF_DOUBLE_P() */)
+		return;
+
+	if (check_region(PC9800_IDE_BANKSELECT, 1)) {
+		printk(KERN_ERR
+			"ide: bank select port (%#x) is already occupied!\n",
+			PC9800_IDE_BANKSELECT);
+		return;
+	}
+
+	/* Do actual probing. */
+	if ((tmp = inb(PC9800_IDE_BANKSELECT)) == (byte) ~0
+	    || (outb(tmp ^ 1, PC9800_IDE_BANKSELECT),
+		/* Next outb is dummy for reading status. */
+		outb(0x80, PC9800_IDE_BANKSELECT),
+		inb(PC9800_IDE_BANKSELECT) != (tmp ^ 1))) {
+		printk(KERN_INFO
+			"ide: pc9800 type bank selecting port not found\n");
+		return;
+	}
+	/* Restore original value, just in case. */
+	outb(tmp, PC9800_IDE_BANKSELECT);
+
+	request_region(PC9800_IDE_BANKSELECT, 1, "ide0/1 bank");
+
+	/* These ports are probably used by IDE I/F.  */
+	request_region(0x430, 1, "ide");
+	request_region(0x435, 1, "ide");
+
+	if (ide_hwifs[0].io_ports[IDE_DATA_OFFSET] == HD_DATA
+	    && ide_hwifs[1].io_ports[IDE_DATA_OFFSET] == HD_DATA) {
+		ide_hwifs[0].chipset = ide_pc9800;
+		ide_hwifs[0].mate = &ide_hwifs[1];
+		ide_hwifs[0].selectproc = pc9800_select;
+		ide_hwifs[1].chipset = ide_pc9800;
+		ide_hwifs[1].mate = &ide_hwifs[0];
+		ide_hwifs[1].selectproc = pc9800_select;
+	}
+}
diff -Nru linux/include/asm-i386/ide.h linux98/include/asm-i386/ide.h
--- linux/include/asm-i386/ide.h	2002-10-12 13:21:31.000000000 +0900
+++ linux98/include/asm-i386/ide.h	2002-10-13 23:17:54.000000000 +0900
@@ -26,6 +26,9 @@
 static __inline__ int ide_default_irq(ide_ioreg_t base)
 {
 	switch (base) {
+#ifdef CONFIG_X86_PC9800
+		case 0x640: return 9;
+#endif /* CONFIG_X86_PC9800 */
 		case 0x1f0: return 14;
 		case 0x170: return 15;
 		case 0x1e8: return 11;
@@ -39,7 +42,11 @@
 
 static __inline__ ide_ioreg_t ide_default_io_base(int index)
 {
+#ifdef CONFIG_X86_PC9800
+	static unsigned long ata_io_base[MAX_HWIFS] = { 0x640, 0x640, 0, 0, 0, 0 };
+#else /* CONFIG_X86_PC9800 */
 	static unsigned long ata_io_base[MAX_HWIFS] = { 0x1f0, 0x170, 0x1e8, 0x168, 0x1e0, 0x160 };
+#endif /* !CONFIG_X86_PC9800 */
 
 	return ata_io_base[index];
 }
@@ -48,13 +55,24 @@
 {
 	ide_ioreg_t reg = data_port;
 	int i;
+#ifdef CONFIG_X86_PC9800
+	ide_ioreg_t increment = data_port == 0x640 ? 2 : 1;
+#endif
 
 	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
 		hw->io_ports[i] = reg;
+#ifdef CONFIG_X86_PC9800
+		reg += increment;
+#else
 		reg += 1;
+#endif
 	}
 	if (ctrl_port) {
 		hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
+#ifdef CONFIG_X86_PC9800
+	} else if (data_port == 0x640) {
+		hw->io_ports[IDE_CONTROL_OFFSET] = 0x74c;
+#endif
 	} else {
 		hw->io_ports[IDE_CONTROL_OFFSET] = hw->io_ports[IDE_DATA_OFFSET] + 0x206;
 	}
diff -Nru linux/include/linux/hdreg.h linux98/include/linux/hdreg.h
--- linux/include/linux/hdreg.h	2003-02-15 08:51:42.000000000 +0900
+++ linux98/include/linux/hdreg.h	2003-02-20 10:18:37.000000000 +0900
@@ -5,11 +5,29 @@
  * This file contains some defines for the AT-hd-controller.
  * Various sources.
  */
+#include <linux/config.h>
 
 /* ide.c has its own port definitions in "ide.h" */
 
 #define HD_IRQ		14
 
+#ifdef CONFIG_X86_PC9800
+/* Hd controller regs. for NEC PC-9800 */
+#define HD_DATA		0x640	/* _CTL when writing */
+#define HD_ERROR	0x642	/* see err-bits */
+#define HD_NSECTOR	0x644	/* nr of sectors to read/write */
+#define HD_SECTOR	0x646	/* starting sector */
+#define HD_LCYL		0x648	/* starting cylinder */
+#define HD_HCYL		0x64a	/* high byte of starting cyl */
+#define HD_CURRENT	0x64c	/* 101dhhhh , d=drive, hhhh=head */
+#define HD_STATUS	0x64e	/* see status-bits */
+#define HD_FEATURE	HD_ERROR	/* same io address, read=error, write=feature */
+#define HD_PRECOMP	HD_FEATURE	/* obsolete use of this port - predates IDE */
+#define HD_COMMAND	HD_STATUS	/* same io address, read=status, write=cmd */
+
+#define HD_CMD		0x74c	/* used for resets */
+#define HD_ALTSTATUS	0x74c	/* same as HD_STATUS but doesn't clear irq */
+#else /* !CONFIG_X86_PC9800 */
 /* Hd controller regs. Ref: IBM AT Bios-listing */
 #define HD_DATA		0x1f0		/* _CTL when writing */
 #define HD_ERROR	0x1f1		/* see err-bits */
@@ -25,6 +43,7 @@
 
 #define HD_CMD		0x3f6		/* used for resets */
 #define HD_ALTSTATUS	0x3f6		/* same as HD_STATUS but doesn't clear irq */
+#endif /* CONFIG_X86_PC9800 */
 
 /* remainder is shared between hd.c, ide.c, ide-cd.c, and the hdparm utility */
 
diff -Nru linux/include/linux/ide.h linux98/include/linux/ide.h
--- linux/include/linux/ide.h	2002-11-11 15:46:21.000000000 +0900
+++ linux98/include/linux/ide.h	2002-11-11 16:43:43.000000000 +0900
@@ -294,7 +294,7 @@
 		ide_qd65xx,	ide_umc8672,	ide_ht6560b,
 		ide_pdc4030,	ide_rz1000,	ide_trm290,
 		ide_cmd646,	ide_cy82c693,	ide_4drives,
-		ide_pmac,	ide_etrax100,	ide_acorn
+		ide_pmac,	ide_etrax100,	ide_acorn,	ide_pc9800
 } hwif_chipset_t;
 
 typedef struct ide_io_ops_s {

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH] PC-9800 additional for 2.5.61-ac1 (8/21) kanji
  2003-02-20 12:16 [PATCH] PC-9800 additional for 2.5.61-ac1 (0/21) summary Osamu Tomita
                   ` (6 preceding siblings ...)
  2003-02-20 12:28 ` [PATCH] PC-9800 additional for 2.5.61-ac1 (7/21) IDE Osamu Tomita
@ 2003-02-20 12:29 ` Osamu Tomita
  2003-02-20 12:30 ` [PATCH] PC-9800 additional for 2.5.61-ac1 (9/21) kconfig Osamu Tomita
                   ` (11 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Osamu Tomita @ 2003-02-20 12:29 UTC (permalink / raw)
  To: Linux Kernel Mailing List; +Cc: Alan Cox, James simmons

This is additional patch to support NEC PC-9800 subarchitecture
against 2.5.61-ac1. (8/21)

Add japanese kanji character support to PC98 console.

diff -Nru linux/drivers/char/console_macros.h linux98/drivers/char/console_macros.h
--- linux/drivers/char/console_macros.h	Sat Oct 19 13:01:17 2002
+++ linux98/drivers/char/console_macros.h	Mon Oct 28 16:53:39 2002
@@ -64,6 +64,16 @@
 #define complement_mask (vc_cons[currcons].d->vc_complement_mask)
 #define s_complement_mask (vc_cons[currcons].d->vc_s_complement_mask)
 #define hi_font_mask	(vc_cons[currcons].d->vc_hi_font_mask)
+#define kanji_mode     (vc_cons[currcons].d->vc_kanji_mode)
+#define s_kanji_mode   (vc_cons[currcons].d->vc_s_kanji_mode)
+#define kanji_char1    (vc_cons[currcons].d->vc_kanji_char1)
+#define translate_ex   (vc_cons[currcons].d->vc_translate_ex)
+#define G0_charset_ex  (vc_cons[currcons].d->vc_G0_charset_ex)
+#define G1_charset_ex  (vc_cons[currcons].d->vc_G1_charset_ex)
+#define saved_G0_ex    (vc_cons[currcons].d->vc_saved_G0_ex)
+#define saved_G1_ex    (vc_cons[currcons].d->vc_saved_G1_ex)
+#define kanji_jis_mode (vc_cons[currcons].d->vc_kanji_jis_mode)
+#define s_kanji_jis_mode (vc_cons[currcons].d->vc_s_kanji_jis_mode)
 
 #define vcmode		(vt_cons[currcons]->vc_mode)
 
diff -Nru linux/drivers/char/vt.c linux98/drivers/char/vt.c
--- linux/drivers/char/vt.c	2002-12-16 11:08:16.000000000 +0900
+++ linux98/drivers/char/vt.c	2002-12-20 14:52:06.000000000 +0900
@@ -151,6 +151,10 @@
 static void blank_screen(unsigned long dummy);
 static void gotoxy(int currcons, int new_x, int new_y);
 static void save_cur(int currcons);
+#ifdef CONFIG_KANJI
+static void save_cur_kanji(int currcons);
+static void restore_cur_kanji(int currcons);
+#endif
 static void reset_terminal(int currcons, int do_clear);
 static void con_flush_chars(struct tty_struct *tty);
 static void set_vesa_blanking(unsigned long arg);
@@ -433,6 +437,25 @@
 		do_update_region(currcons, (unsigned long) p, count);
 }
 
+#ifdef CONFIG_KANJI
+/* can called form keyboard.c */
+void do_change_kanji_mode(int currcons, unsigned long mode)
+{
+	switch (mode) {
+	case 0:
+		kanji_mode = EUC_CODE;
+		break;
+	case 1:
+		kanji_mode = JIS_CODE;
+		break;
+	case 2:
+		kanji_mode = SJIS_CODE;
+		break;
+	}
+	kanji_char1 = 0;
+}
+#endif /* CONFIG_KANJI */
+
 /* used by selection: complement pointer position */
 void complement_pos(int currcons, int offset)
 {
@@ -1085,6 +1108,9 @@
 				translate = set_translate(charset == 0
 						? G0_charset
 						: G1_charset,currcons);
+#ifdef CONFIG_KANJI
+				translate_ex = (charset == 0 ? G0_charset_ex : G1_charset_ex);
+#endif
 				disp_ctrl = 0;
 				toggle_meta = 0;
 				break;
@@ -1093,6 +1119,9 @@
 				  * chars < 32 be displayed as ROM chars.
 				  */
 				translate = set_translate(IBMPC_MAP,currcons);
+#ifdef CONFIG_KANJI
+				translate_ex = 0;
+#endif
 				disp_ctrl = 1;
 				toggle_meta = 0;
 				break;
@@ -1101,6 +1130,9 @@
 				  * high bit before displaying as ROM char.
 				  */
 				translate = set_translate(IBMPC_MAP,currcons);
+#ifdef CONFIG_KANJI
+				translate_ex = 0;
+#endif
 				disp_ctrl = 1;
 				toggle_meta = 1;
 				break;
@@ -1310,6 +1342,22 @@
 		case 14: /* set vesa powerdown interval */
 			vesa_off_interval = ((par[1] < 60) ? par[1] : 60) * 60 * HZ;
 			break;
+#ifdef CONFIG_KANJI
+		case 98:
+			if (par[1] < 10) /* change kanji mode */
+				do_change_kanji_mode(currcons, par[1]); /* 0208 */
+			else if (par[1] == 10) { /* save restore kanji mode */
+				switch (par[2]) {
+				case 1:
+					save_cur_kanji(currcons);
+					break;
+				case 2:
+					restore_cur_kanji(currcons);
+					break;
+				}
+			}
+			break;
+#endif /* CONFIG_KANJI */
 	}
 }
 
@@ -1387,8 +1435,26 @@
 	need_wrap = 0;
 }
 
+#ifdef CONFIG_KANJI
+static void save_cur_kanji(int currcons)
+{
+        s_kanji_mode = kanji_mode;
+        s_kanji_jis_mode = kanji_jis_mode;
+}
+
+static void restore_cur_kanji(int currcons)
+{
+        kanji_mode = s_kanji_mode;
+        kanji_jis_mode = s_kanji_jis_mode;
+        kanji_char1 = 0;
+}
+#endif
+
 enum { ESnormal, ESesc, ESsquare, ESgetpars, ESgotpars, ESfunckey,
 	EShash, ESsetG0, ESsetG1, ESpercent, ESignore, ESnonstd,
+#ifdef CONFIG_KANJI
+	ESsetJIS, ESsetJIS2,
+#endif
 	ESpalette };
 
 /* console_sem is held (except via vc_init()) */
@@ -1398,9 +1464,18 @@
 	bottom		= video_num_lines;
 	vc_state	= ESnormal;
 	ques		= 0;
+#ifdef CONFIG_KANJI
+	translate	= set_translate(JP_MAP, currcons);
+	translate_ex    = 0;
+	G0_charset      = JP_MAP;
+	G0_charset_ex   = 0;
+	G1_charset      = GRAF_MAP;
+	G1_charset_ex   = 0;
+#else
 	translate	= set_translate(LAT1_MAP,currcons);
 	G0_charset	= LAT1_MAP;
 	G1_charset	= GRAF_MAP;
+#endif
 	charset		= 0;
 	need_wrap	= 0;
 	report_mouse	= 0;
@@ -1442,6 +1517,12 @@
 	bell_pitch = DEFAULT_BELL_PITCH;
 	bell_duration = DEFAULT_BELL_DURATION;
 
+#ifdef CONFIG_KANJI
+	kanji_mode = EUC_CODE;
+	kanji_char1 = 0;
+	kanji_jis_mode = JIS_CODE_ASCII;
+#endif
+
 	gotoxy(currcons,0,0);
 	save_cur(currcons);
 	if (do_clear)
@@ -1484,11 +1565,17 @@
 	case 14:
 		charset = 1;
 		translate = set_translate(G1_charset,currcons);
+#ifdef CONFIG_KANJI
+		translate_ex = G1_charset_ex;
+#endif
 		disp_ctrl = 1;
 		return;
 	case 15:
 		charset = 0;
 		translate = set_translate(G0_charset,currcons);
+#ifdef CONFIG_KANJI
+		translate_ex = G0_charset_ex;
+#endif
 		disp_ctrl = 0;
 		return;
 	case 24: case 26:
@@ -1545,6 +1632,11 @@
 		case ')':
 			vc_state = ESsetG1;
 			return;
+#ifdef CONFIG_KANJI
+		case '$':
+			vc_state = ESsetJIS;
+			return;
+#endif
 		case '#':
 			vc_state = EShash;
 			return;
@@ -1794,8 +1886,25 @@
 			G0_charset = IBMPC_MAP;
 		else if (c == 'K')
 			G0_charset = USER_MAP;
-		if (charset == 0)
+#ifdef CONFIG_KANJI
+		G0_charset_ex = 0;
+		if (c == 'J')
+			G0_charset = JP_MAP;
+		else if (c == 'I'){
+			G0_charset = JP_MAP;
+			G0_charset_ex = 1;
+		}
+#endif /* CONFIG_KANJI */
+		if (charset == 0) {
 			translate = set_translate(G0_charset,currcons);
+#ifdef CONFIG_KANJI
+			translate_ex = G0_charset_ex;
+#endif
+		}
+#ifdef CONFIG_KANJI
+		kanji_jis_mode = JIS_CODE_ASCII;
+		kanji_char1 = 0;
+#endif
 		vc_state = ESnormal;
 		return;
 	case ESsetG1:
@@ -1807,10 +1916,51 @@
 			G1_charset = IBMPC_MAP;
 		else if (c == 'K')
 			G1_charset = USER_MAP;
-		if (charset == 1)
+#ifdef CONFIG_KANJI
+		G1_charset_ex = 0;
+		if (c == 'J')
+			G1_charset = JP_MAP;
+		else if (c == 'I') {
+			G1_charset = JP_MAP;
+			G1_charset_ex = 1;
+		}
+#endif /* CONFIG_KANJI */
+		if (charset == 1) {
 			translate = set_translate(G1_charset,currcons);
+#ifdef CONFIG_KANJI
+			translate_ex = G1_charset_ex;
+#endif
+		}
+#ifdef CONFIG_KANJI
+		kanji_jis_mode = JIS_CODE_ASCII;
+		kanji_char1 = 0;
+#endif
+		vc_state = ESnormal;
+		return;
+#ifdef CONFIG_KANJI
+	case ESsetJIS:
+		if (c == '@')
+			kanji_jis_mode = JIS_CODE_78;
+		else if (c == 'B')
+			kanji_jis_mode = JIS_CODE_83;
+		else if (c == '('){
+			vc_state = ESsetJIS2;
+			return;
+		} else {
+		vc_state = ESnormal;
+		return;
+		}
 		vc_state = ESnormal;
+		kanji_char1 = 0;
 		return;
+	case ESsetJIS2:
+		if (c == 'D'){
+			kanji_jis_mode = JIS_CODE_90;
+			kanji_char1 = 0;
+		}
+		vc_state = ESnormal;
+		return;
+#endif /* CONIFG_KANJI */
 	default:
 		vc_state = ESnormal;
 	}
@@ -1842,7 +1992,7 @@
 	}
 #endif
 
-	int c, tc, ok, n = 0, draw_x = -1;
+	int c, tc = 0, ok, n = 0, draw_x = -1;
 	unsigned int currcons;
 	unsigned long draw_from = 0, draw_to = 0;
 	struct vt_struct *vt = (struct vt_struct *)tty->driver_data;
@@ -1899,48 +2049,151 @@
 		hide_cursor(currcons);
 
 	while (!tty->stopped && count) {
+		int realkanji = 0;
+		int kanjioverrun = 0;
 		c = *buf;
 		buf++;
 		n++;
 		count--;
 
-		if (utf) {
-		    /* Combine UTF-8 into Unicode */
-		    /* Incomplete characters silently ignored */
-		    if(c > 0x7f) {
-			if (utf_count > 0 && (c & 0xc0) == 0x80) {
-				utf_char = (utf_char << 6) | (c & 0x3f);
-				utf_count--;
-				if (utf_count == 0)
-				    tc = c = utf_char;
-				else continue;
-			} else {
-				if ((c & 0xe0) == 0xc0) {
-				    utf_count = 1;
-				    utf_char = (c & 0x1f);
-				} else if ((c & 0xf0) == 0xe0) {
-				    utf_count = 2;
-				    utf_char = (c & 0x0f);
-				} else if ((c & 0xf8) == 0xf0) {
-				    utf_count = 3;
-				    utf_char = (c & 0x07);
-				} else if ((c & 0xfc) == 0xf8) {
-				    utf_count = 4;
-				    utf_char = (c & 0x03);
-				} else if ((c & 0xfe) == 0xfc) {
-				    utf_count = 5;
-				    utf_char = (c & 0x01);
-				} else
-				    utf_count = 0;
-				continue;
-			      }
-		    } else {
-		      tc = c;
-		      utf_count = 0;
-		    }
-		} else {	/* no utf */
-		  tc = translate[toggle_meta ? (c|0x80) : c];
-		}
+#ifdef CONFIG_KANJI
+		if (vc_state == ESnormal && !disp_ctrl) {
+			switch (kanji_jis_mode) {
+			case JIS_CODE_78:
+			case JIS_CODE_83:
+			case JIS_CODE_90:
+				if (utf)
+					break;
+				if (c >= 127 || c <= 0x20) {
+					kanji_char1 = 0;
+					break;
+				}
+				if (kanji_char1) {
+					tc = (((unsigned int)kanji_char1) << 8) |
+                        (((unsigned int)c) & 0x007f);
+					kanji_char1 = 0;
+					realkanji = 1;
+				} else {
+					kanji_char1 = ((unsigned int)c) & 0x007f;
+					continue;
+				} 
+				break;
+			case JIS_CODE_ASCII:
+			default:
+				switch (kanji_mode) {
+				case SJIS_CODE:
+					if (kanji_char1) {
+                        if ((0x40 <= c && c <= 0x7E) ||
+                            (0x80 <= c && c <= 0xFC)) {
+							realkanji = 1;
+							/* SJIS to JIS */
+							kanji_char1 <<= 1; /* 81H-9FH --> 22H-3EH */
+							/* EOH-EFH --> C0H-DEH */
+							c -= 0x1f;         /* 40H-7EH --> 21H-5FH */
+							/* 80H-9EH --> 61H-7FH */
+							/* 9FH-FCH --> 80H-DDH */
+							if (!(c & 0x80)) {
+								if (c < 0x61)
+									c++;
+								c += 0xde;
+							}
+							c &= 0xff;
+							c += 0xa1;
+							kanji_char1 += 0x1f;
+							tc = (kanji_char1 << 8) + c;
+							tc &= 0x7f7f;
+							kanji_char1 = 0;
+                        }
+					} else {
+                        if ((0x81 <= c && c <= 0x9f) ||
+                            (0xE0 <= c && c <= 0xEF)) {
+							realkanji = 1;
+							kanji_char1 = c;
+							continue;
+                        } else if (0xA1 <= c && c <= 0xDF) {
+							tc = (unsigned int)translations[JP_MAP][c];
+							goto hankana_skip;
+                        }
+					}
+					break;
+				case EUC_CODE:
+					if (utf)
+                        break;
+					if (c <= 0x7f) {
+                        kanji_char1 = 0;
+                        break;
+					}
+					if (kanji_char1) {
+                        if (kanji_char1 == 0x8e) {  /* SS2 */
+							/* realkanji ha tatenai */
+							tc = (unsigned int)translations[JP_MAP][c];
+							kanji_char1 = 0;
+							goto hankana_skip;
+                        } else {
+							tc = (((unsigned int)kanji_char1) << 8) |
+								(((unsigned int)c) & 0x007f);
+							kanji_char1 = 0;
+							realkanji = 1;
+                        }
+					} else {
+                        kanji_char1 = (unsigned int)c;
+                        continue;
+					}
+					break;
+				case JIS_CODE:
+					/* to be supported */
+					break;
+				} /* switch (kanji_mode) */
+			} /* switch (kanji_jis_mode) */
+		} /* if (vc_state == ESnormal) */
+
+#endif /* CONFIG_KANJI */
+		if (!realkanji) {
+			if (utf) {
+			    /* Combine UTF-8 into Unicode */
+			    /* Incomplete characters silently ignored */
+			    if(c > 0x7f) {
+				if (utf_count > 0 && (c & 0xc0) == 0x80) {
+					utf_char = (utf_char << 6) | (c & 0x3f);
+					utf_count--;
+					if (utf_count == 0)
+					    tc = c = utf_char;
+					else continue;
+				} else {
+					if ((c & 0xe0) == 0xc0) {
+					    utf_count = 1;
+					    utf_char = (c & 0x1f);
+					} else if ((c & 0xf0) == 0xe0) {
+					    utf_count = 2;
+					    utf_char = (c & 0x0f);
+					} else if ((c & 0xf8) == 0xf0) {
+					    utf_count = 3;
+					    utf_char = (c & 0x07);
+					} else if ((c & 0xfc) == 0xf8) {
+					    utf_count = 4;
+					    utf_char = (c & 0x03);
+					} else if ((c & 0xfe) == 0xfc) {
+					    utf_count = 5;
+					    utf_char = (c & 0x01);
+					} else
+					    utf_count = 0;
+					continue;
+				      }
+			    } else {
+			      tc = c;
+			      utf_count = 0;
+			    }
+			} else {	/* no utf */
+#ifdef CONFIG_KANJI
+			  tc = translate[(toggle_meta || translate_ex) ? (c | 0x80) : c];
+#else
+			  tc = translate[toggle_meta ? (c|0x80) : c];
+#endif
+			}
+		} /* if (!realkanji) */
+#ifdef CONFIG_KANJI
+	hankana_skip:
+#endif
 
                 /* If the original code was a control character we
                  * only allow a glyph to be displayed if the code is
@@ -1957,43 +2210,71 @@
                                          : CTRL_ACTION) >> c) & 1)))
                         && (c != 127 || disp_ctrl)
 			&& (c != 128+27);
+                ok |= realkanji;
 
 		if (vc_state == ESnormal && ok) {
-			/* Now try to find out how to display it */
-			tc = conv_uni_to_pc(vc_cons[currcons].d, tc);
-			if ( tc == -4 ) {
+			if (!realkanji) {
+				/* Now try to find out how to display it */
+				tc = conv_uni_to_pc(vc_cons[currcons].d, tc);
+				if ( tc == -4 ) {
                                 /* If we got -4 (not found) then see if we have
                                    defined a replacement character (U+FFFD) */
-                                tc = conv_uni_to_pc(vc_cons[currcons].d, 0xfffd);
+       	                         tc = conv_uni_to_pc(vc_cons[currcons].d, 0xfffd);
 
 				/* One reason for the -4 can be that we just
 				   did a clear_unimap();
 				   try at least to show something. */
-				if (tc == -4)
-				     tc = c;
-                        } else if ( tc == -3 ) {
+					if (tc == -4)
+					     tc = c;
+				} else if ( tc == -3 ) {
                                 /* Bad hash table -- hope for the best */
-                                tc = c;
-                        }
-			if (tc & ~charmask)
-                                continue; /* Conversion failed */
+					tc = c;
+				}
+				if (tc & ~charmask)
+					continue; /* Conversion failed */
+			} /* !realkanji */
 
 			if (need_wrap || decim)
 				FLUSH
 			if (need_wrap) {
 				cr(currcons);
 				lf(currcons);
+				if (kanjioverrun) {
+					x++;
+					pos += 2;
+					kanjioverrun = 0;
+				}
 			}
 			if (decim)
 				insert_char(currcons, 1);
+#ifndef CONFIG_KANJI
 			scr_writew(himask ?
 				     ((attr << 8) & ~himask) + ((tc & 0x100) ? himask : 0) + (tc & 0xff) :
 				     (attr << 8) + tc,
 				   (u16 *) pos);
+#else /* CONFIG_KANJI */
+			if (realkanji) {
+				tc = ((tc >> 8) & 0xff) | ((tc << 8) & 0xff00); 
+				*((u16 *)pos) = (tc - 0x20) & 0xff7f;
+				*(pc9800_attr_offset((u16 *)pos)) = attr;
+				x ++;
+				pos += 2;
+				*((u16 *)pos) = (tc - 0x20) | 0x80;
+				*(pc9800_attr_offset((u16 *)pos)) = attr;
+			} else {
+				*((u16 *)pos) = tc & 0x00ff;
+				*(pc9800_attr_offset((u16 *)pos)) = attr;
+			}
+#endif /* !CONFIG_KANJI */
 			if (DO_UPDATE && draw_x < 0) {
 				draw_x = x;
 				draw_from = pos;
+				if (realkanji) {
+					draw_x --;
+					draw_from -= 2;
+				}
 			}
+#ifndef CONFIG_KANJI
 			if (x == video_num_columns - 1) {
 				need_wrap = decawm;
 				draw_to = pos+2;
@@ -2001,6 +2282,16 @@
 				x++;
 				draw_to = (pos+=2);
 			}
+#else /* CONFIG_KANJI */
+			if (x >= video_num_columns - 1) {
+				need_wrap = decawm;
+				kanjioverrun = x - video_num_columns + 1;
+				draw_to = pos + 2;
+			} else {
+				x++;
+				draw_to = (pos += 2);
+			}
+#endif /* !CONFIG_KANJI */
 			continue;
 		}
 		FLUSH
diff -Nru linux-2.5.61/drivers/video/console/Kconfig linux98-2.5.61/drivers/video/console/Kconfig
--- linux-2.5.61/drivers/video/console/Kconfig	2003-02-15 08:51:21.000000000 +0900
+++ linux98-2.5.61/drivers/video/console/Kconfig	2003-02-16 14:48:08.000000000 +0900
@@ -221,5 +221,9 @@
 	bool "Mini 4x6 font"
 	depends on !SPARC32 && !SPARC64 && FONTS
 
+config KANJI
+	bool "Japanese Kanji support"
+	depends on X86_PC9800
+
 endmenu
 
diff -Nru linux/include/linux/console_struct.h linux98/include/linux/console_struct.h
--- linux/include/linux/console_struct.h	2002-12-10 11:45:40.000000000 +0900
+++ linux98/include/linux/console_struct.h	2002-12-16 13:25:55.000000000 +0900
@@ -83,6 +83,18 @@
 	struct vc_data **vc_display_fg;		/* [!] Ptr to var holding fg console for this display */
 	unsigned long	vc_uni_pagedir;
 	unsigned long	*vc_uni_pagedir_loc;  /* [!] Location of uni_pagedir variable for this console */
+#ifdef CONFIG_KANJI
+	unsigned char   vc_kanji_char1;
+	unsigned char   vc_kanji_mode;
+	unsigned char   vc_kanji_jis_mode;
+	unsigned char   vc_s_kanji_mode;
+	unsigned char   vc_s_kanji_jis_mode;
+	unsigned int    vc_translate_ex;
+	unsigned char   vc_G0_charset_ex;
+	unsigned char   vc_G1_charset_ex;
+	unsigned char   vc_saved_G0_ex;
+	unsigned char   vc_saved_G1_ex;
+#endif /* CONFIG_KANJI */
 	/* additional information is in vt_kern.h */
 };
 
diff -Nru linux/include/linux/consolemap.h linux98/include/linux/consolemap.h
--- linux/include/linux/consolemap.h	Sat Oct 19 13:02:34 2002
+++ linux98/include/linux/consolemap.h	Mon Oct 21 14:19:31 2002
@@ -7,6 +7,7 @@
 #define GRAF_MAP 1
 #define IBMPC_MAP 2
 #define USER_MAP 3
+#define JP_MAP 4
 
 struct vc_data;
 

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH] PC-9800 additional for 2.5.61-ac1 (9/21) kconfig
  2003-02-20 12:16 [PATCH] PC-9800 additional for 2.5.61-ac1 (0/21) summary Osamu Tomita
                   ` (7 preceding siblings ...)
  2003-02-20 12:29 ` [PATCH] PC-9800 additional for 2.5.61-ac1 (8/21) kanji Osamu Tomita
@ 2003-02-20 12:30 ` Osamu Tomita
  2003-02-20 12:31 ` [PATCH] PC-9800 additional for 2.5.61-ac1 (10/21) network card Osamu Tomita
                   ` (10 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Osamu Tomita @ 2003-02-20 12:30 UTC (permalink / raw)
  To: Linux Kernel Mailing List; +Cc: Alan Cox

This is additional patch to support NEC PC-9800 subarchitecture
against 2.5.61-ac1. (9/21)

Add selection CONFIG_X86_PC9800.

diff -Nru linux-2.5.61-ac1/arch/i386/Kconfig linux98-2.5.61/arch/i386/Kconfig
--- linux-2.5.61-ac1/arch/i386/Kconfig	2003-02-18 08:58:20.000000000 +0900
+++ linux98-2.5.61/arch/i386/Kconfig	2003-02-18 12:58:14.000000000 +0900
@@ -75,6 +75,12 @@
 
 	  If you don't have one of these computers, you should say N here.
 
+config X86_PC9800
+	bool "PC-9800 (NEC)"
+	help
+	  To make kernel for NEC PC-9801/PC-9821 sub-architecture, say Y.
+	  If say Y, kernel works -ONLY- on PC-9800 architecture.
+
 config X86_BIGSMP
 	bool "Support for other sub-arch SMP systems with more than 8 CPUs"
 	help
@@ -1197,7 +1203,7 @@
 
 config EISA
 	bool "EISA support"
-	depends on ISA
+	depends on ISA && !X86_PC9800
 	---help---
 	  The Extended Industry Standard Architecture (EISA) bus was
 	  developed as an open alternative to the IBM MicroChannel bus.
@@ -1215,7 +1221,7 @@
 
 config MCA
 	bool "MCA support"
-	depends on !(X86_VISWS || X86_VOYAGER)
+	depends on !(X86_VISWS || X86_VOYAGER || X86_PC9800)
 	help
 	  MicroChannel Architecture is found in some IBM PS/2 machines and
 	  laptops.  It is a bus system similar to PCI or ISA. See

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH] PC-9800 additional for 2.5.61-ac1 (10/21) network card
  2003-02-20 12:16 [PATCH] PC-9800 additional for 2.5.61-ac1 (0/21) summary Osamu Tomita
                   ` (8 preceding siblings ...)
  2003-02-20 12:30 ` [PATCH] PC-9800 additional for 2.5.61-ac1 (9/21) kconfig Osamu Tomita
@ 2003-02-20 12:31 ` Osamu Tomita
  2003-02-20 12:32 ` [PATCH] PC-9800 additional for 2.5.61-ac1 (11/21) parport Osamu Tomita
                   ` (9 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Osamu Tomita @ 2003-02-20 12:31 UTC (permalink / raw)
  To: Linux Kernel Mailing List; +Cc: Alan Cox, Jeff Garzik

This is additional patch to support NEC PC-9800 subarchitecture
against 2.5.61-ac1. (10/21)

C-bus(PC98's legacy bus like ISA) network cards support.
  PCI netwwork card works fine without patch.

diff -Nru linux-2.5.61/drivers/net/3c509.c linux98-2.5.61/drivers/net/3c509.c
--- linux-2.5.61/drivers/net/3c509.c	2003-02-15 08:51:09.000000000 +0900
+++ linux98-2.5.61/drivers/net/3c509.c	2003-02-15 14:38:08.000000000 +0900
@@ -56,6 +56,10 @@
 		v1.19b 08Nov2002 Marc Zyngier <maz@wild-wind.fr.eu.org>
 		    - Introduce driver model for EISA cards.
 */
+/*
+  FIXES for PC-9800:
+  Shu Iwanaga: 3c569B(PC-9801 C-bus) support
+*/
 
 #define DRV_NAME	"3c509"
 #define DRV_VERSION	"1.19b"
@@ -257,7 +261,7 @@
 };
 #endif /* CONFIG_MCA */
 
-#ifdef __ISAPNP__
+#if defined(__ISAPNP__) && !defined(CONFIG_X86_PC9800)
 static struct isapnp_device_id el3_isapnp_adapters[] __initdata = {
 	{	ISAPNP_ANY_ID, ISAPNP_ANY_ID,
 		ISAPNP_VENDOR('T', 'C', 'M'), ISAPNP_FUNCTION(0x5090),
@@ -350,7 +354,7 @@
 		if (lp->pmdev)
 			pm_unregister(lp->pmdev);
 #endif
-#ifdef __ISAPNP__
+#if defined(__ISAPNP__) && !defined(CONFIG_X86_PC9800)
 		if (lp->type == EL3_PNP)
 			pnp_device_detach(to_pnp_dev(lp->dev));
 #endif
@@ -368,12 +372,12 @@
 	int ioaddr, irq, if_port;
 	u16 phys_addr[3];
 	static int current_tag;
-#ifdef __ISAPNP__
+#if defined(__ISAPNP__) && !defined(CONFIG_X86_PC9800)
 	static int pnp_cards;
 	struct pnp_dev *idev = NULL;
 #endif /* __ISAPNP__ */
 
-#ifdef __ISAPNP__
+#if defined(__ISAPNP__) && !defined(CONFIG_X86_PC9800)
 	if (nopnp == 1)
 		goto no_pnp;
 
@@ -421,6 +425,9 @@
 no_pnp:
 #endif /* __ISAPNP__ */
 
+#ifdef CONFIG_X86_PC9800
+	id_port = 0x71d0;
+#else
 	/* Select an open I/O location at 0x1*0 to do contention select. */
 	for ( ; id_port < 0x200; id_port += 0x10) {
 		if (check_region(id_port, 1))
@@ -435,6 +442,7 @@
 		printk(" WARNING: No I/O port available for 3c509 activation.\n");
 		return -ENODEV;
 	}
+#endif /* CONFIG_X86_PC9800 */
 	/* Next check for all ISA bus boards by sending the ID sequence to the
 	   ID_PORT.  We find cards past the first by setting the 'current_tag'
 	   on cards as they are found.  Cards with their tag set will not
@@ -465,7 +473,7 @@
 		phys_addr[i] = htons(id_read_eeprom(i));
 	}
 
-#ifdef __ISAPNP__
+#if defined(__ISAPNP__) && !defined(CONFIG_X86_PC9800)
 	if (nopnp == 0) {
 		/* The ISA PnP 3c509 cards respond to the ID sequence.
 		   This check is needed in order not to register them twice. */
@@ -490,9 +498,19 @@
 	{
 		unsigned int iobase = id_read_eeprom(8);
 		if_port = iobase >> 14;
+#ifdef CONFIG_X86_PC9800
+		ioaddr = 0x40d0 + ((iobase & 0x1f) << 8);
+#else
 		ioaddr = 0x200 + ((iobase & 0x1f) << 4);
+#endif
 	}
 	irq = id_read_eeprom(9) >> 12;
+#ifdef CONFIG_X86_PC9800
+	if (irq == 7)
+		irq = 6;
+	else if (irq == 15)
+		irq = 13;
+#endif
 
 	if (!(dev = init_etherdev(NULL, sizeof(struct el3_private))))
 			return -ENOMEM;
@@ -522,7 +540,11 @@
 	outb(0xd0 + ++current_tag, id_port);
 
 	/* Activate the adaptor at the EEPROM location. */
+#ifdef CONFIG_X86_PC9800
+	outb((ioaddr >> 8) | 0xe0, id_port);
+#else
 	outb((ioaddr >> 4) | 0xe0, id_port);
+#endif
 
 	EL3WINDOW(0);
 	if (inw(ioaddr) != 0x6d50) {
@@ -534,7 +556,7 @@
 	/* Free the interrupt so that some other card can use it. */
 	outw(0x0f00, ioaddr + WN0_IRQ);
 
-#ifdef __ISAPNP__	
+#if defined(__ISAPNP__) && !defined(CONFIG_X86_PC9800)
  found:							/* PNP jumps here... */
 #endif /* __ISAPNP__ */
 
@@ -543,7 +565,7 @@
 	dev->irq = irq;
 	dev->if_port = if_port;
 	lp = dev->priv;
-#ifdef __ISAPNP__
+#if defined(__ISAPNP__) && !defined(CONFIG_X86_PC9800)
 	lp->dev = &idev->dev;
 #endif
 
@@ -1388,6 +1410,12 @@
 	outw(0x0001, ioaddr + 4);
 
 	/* Set the IRQ line. */
+#ifdef CONFIG_X86_PC9800
+	if (dev->irq == 6)
+		dev->irq = 7;
+	else if (dev->irq == 13)
+		dev->irq = 15;
+#endif
 	outw((dev->irq << 12) | 0x0f00, ioaddr + WN0_IRQ);
 
 	/* Set the station address in window 2 each time opened. */
@@ -1550,7 +1578,7 @@
 MODULE_PARM_DESC(irq, "IRQ number(s) (assigned)");
 MODULE_PARM_DESC(xcvr,"tranceiver(s) (0=internal, 1=external)");
 MODULE_PARM_DESC(max_interrupt_work, "maximum events handled per interrupt");
-#ifdef __ISAPNP__
+#if defined(__ISAPNP__) && !defined(CONFIG_X86_PC9800)
 MODULE_PARM(nopnp, "i");
 MODULE_PARM_DESC(nopnp, "disable ISA PnP support (0-1)");
 MODULE_DEVICE_TABLE(isapnp, el3_isapnp_adapters);
diff -Nru linux-2.5.42/drivers/net/8390.h linux98-2.5.42/drivers/net/8390.h
--- linux-2.5.42/drivers/net/8390.h	2002-10-12 13:22:14.000000000 +0900
+++ linux98-2.5.42/drivers/net/8390.h	2002-10-15 23:03:22.000000000 +0900
@@ -123,7 +123,8 @@
 #define inb_p(port)   in_8(port)
 #define outb_p(val,port)  out_8(port,val)
 
-#elif defined(CONFIG_ARM_ETHERH) || defined(CONFIG_ARM_ETHERH_MODULE)
+#elif defined(CONFIG_ARM_ETHERH) || defined(CONFIG_ARM_ETHERH_MODULE) || \
+      defined(CONFIG_NET_CBUS)
 #define EI_SHIFT(x)	(ei_local->reg_offset[x])
 #else
 #define EI_SHIFT(x)	(x)
diff -Nru linux-2.5.61/drivers/net/Kconfig linux98-2.5.61/drivers/net/Kconfig
--- linux-2.5.61/drivers/net/Kconfig	2003-02-15 08:52:31.000000000 +0900
+++ linux98-2.5.61/drivers/net/Kconfig	2003-02-15 14:24:25.000000000 +0900
@@ -662,7 +662,7 @@
 	  as <file:Documentation/networking/net-modules.txt>.
 
 config EL3
-	tristate "3c509/3c529 (MCA)/3c579 \"EtherLink III\" support"
+	tristate "3c509/3c529 (MCA)/3c569B (98)/3c579 \"EtherLink III\" support"
 	depends on NET_VENDOR_3COM && (ISA || EISA || MCA)
 	---help---
 	  If you have a network (Ethernet) card belonging to the 3Com
@@ -931,7 +931,7 @@
 source "drivers/net/tulip/Kconfig"
 
 config AT1700
-	tristate "AT1700/1720 support (EXPERIMENTAL)"
+	tristate "AT1700/1720/RE1000Plus(C-Bus) support (EXPERIMENTAL)"
 	depends on NET_ETHERNET && (ISA || MCA) && EXPERIMENTAL
 	---help---
 	  If you have a network (Ethernet) card of this type, say Y and read
@@ -977,7 +977,7 @@
 
 config NET_ISA
 	bool "Other ISA cards"
-	depends on NET_ETHERNET && ISA
+	depends on NET_ETHERNET && ISA && !X86_PC9800
 	---help---
 	  If your network (Ethernet) card hasn't been mentioned yet and its
 	  bus system (that's the way the cards talks to the other components
@@ -1175,6 +1175,55 @@
 	  the Ethernet-HOWTO, available from
 	  <http://www.linuxdoc.org/docs.html#howto>.
 
+config NET_CBUS
+	bool "NEC PC-9800 C-bus cards"
+	depends on NET_ETHERNET && ISA && X86_PC9800
+	---help---
+	  If your network (Ethernet) card hasn't been mentioned yet and its
+	  bus system (that's the way the cards talks to the other components
+	  of your computer) is NEC PC-9800 C-Bus, say Y.
+
+config NE2K_CBUS
+	tristate "Most NE2000-based Ethernet support"
+	depends on NET_CBUS
+
+config NE2K_CBUS_EGY98
+	bool "Melco EGY-98 support"
+	depends on NE2K_CBUS
+
+config NE2K_CBUS_LGY98
+	bool "Melco LGY-98 support"
+	depends on NE2K_CBUS
+
+config NE2K_CBUS_ICM
+	bool "ICM IF-27xxET support"
+	depends on NE2K_CBUS
+
+config NE2K_CBUS_IOLA98
+	bool "I-O DATA LA-98 support"
+	depends on NE2K_CBUS
+
+config NE2K_CBUS_CNET98EL
+	bool "Contec C-NET(98)E/L support"
+	depends on NE2K_CBUS
+
+config NE2K_CBUS_CNET98EL_IO_BASE
+	hex "C-NET(98)E/L I/O base address (0xaaed or 0x55ed)"
+	depends on NE2K_CBUS_CNET98EL
+	default "0xaaed"
+
+config NE2K_CBUS_ATLA98
+	bool "Allied Telesis LA-98 Support"
+	depends on NE2K_CBUS
+
+config NE2K_CBUS_BDN
+	bool "ELECOM Laneed LD-BDN[123]A Support"
+	depends on NE2K_CBUS
+
+config NE2K_CBUS_NEC108
+	bool "NEC PC-9801-108 Support"
+	depends on NE2K_CBUS
+
 config SKMC
 	tristate "SKnet MCA support"
 	depends on NET_ETHERNET && MCA
diff -Nru linux-2.5.61/drivers/net/Makefile linux98-2.5.61/drivers/net/Makefile
--- linux-2.5.61/drivers/net/Makefile	2003-02-15 08:51:25.000000000 +0900
+++ linux98-2.5.61/drivers/net/Makefile	2003-02-15 14:24:25.000000000 +0900
@@ -86,6 +86,7 @@
 obj-$(CONFIG_WD80x3) += wd.o 8390.o
 obj-$(CONFIG_EL2) += 3c503.o 8390.o
 obj-$(CONFIG_NE2000) += ne.o 8390.o
+obj-$(CONFIG_NE2K_CBUS) += ne.o 8390.o
 obj-$(CONFIG_NE2_MCA) += ne2.o 8390.o
 obj-$(CONFIG_HPLAN) += hp.o 8390.o
 obj-$(CONFIG_HPLAN_PLUS) += hp-plus.o 8390.o
diff -Nru linux-2.5.42/drivers/net/Makefile.lib linux98-2.5.42/drivers/net/Makefile.lib
--- linux-2.5.42/drivers/net/Makefile.lib	2002-10-12 13:22:18.000000000 +0900
+++ linux98-2.5.42/drivers/net/Makefile.lib	2002-10-15 23:03:22.000000000 +0900
@@ -19,6 +19,7 @@
 obj-$(CONFIG_MACMACE)		+= crc32.o
 obj-$(CONFIG_MIPS_AU1000_ENET)	+= crc32.o
 obj-$(CONFIG_NATSEMI)		+= crc32.o	
+obj-$(CONFIG_NE2K_CBUS)		+= crc32.o
 obj-$(CONFIG_PCMCIA_FMVJ18X)	+= crc32.o
 obj-$(CONFIG_PCMCIA_SMC91C92)	+= crc32.o
 obj-$(CONFIG_PCMCIA_XIRTULIP)	+= crc32.o
diff -Nru linux-2.5.61/drivers/net/Space.c linux98-2.5.61/drivers/net/Space.c
--- linux-2.5.61/drivers/net/Space.c	2003-02-15 08:51:12.000000000 +0900
+++ linux98-2.5.61/drivers/net/Space.c	2003-02-15 14:24:25.000000000 +0900
@@ -233,7 +233,7 @@
 #ifdef CONFIG_E2100		/* Cabletron E21xx series. */
 	{e2100_probe, 0},
 #endif
-#ifdef CONFIG_NE2000		/* ISA (use ne2k-pci for PCI cards) */
+#if defined(CONFIG_NE2000) || defined(CONFIG_NE2K_CBUS)	/* ISA & PC-9800 CBUS (use ne2k-pci for PCI cards) */
 	{ne_probe, 0},
 #endif
 #ifdef CONFIG_LANCE		/* ISA/VLB (use pcnet32 for PCI cards) */
diff -Nru linux-2.5.57/drivers/net/at1700.c linux98-2.5.57/drivers/net/at1700.c
--- linux-2.5.57/drivers/net/at1700.c	2003-01-14 09:31:51.000000000 +0900
+++ linux98-2.5.57/drivers/net/at1700.c	2003-01-14 09:55:53.000000000 +0900
@@ -34,6 +34,10 @@
 	only is it difficult to detect, it also moves around in I/O space in
 	response to inb()s from other device probes!
 */
+/*
+	99/03/03  Allied Telesis RE1000 Plus support by T.Hagawa
+	99/12/30	port to 2.3.35 by K.Takai
+*/
 
 #include <linux/config.h>
 #include <linux/errno.h>
@@ -76,10 +80,17 @@
  *	ISA
  */
 
+#ifndef CONFIG_X86_PC9800
 static int at1700_probe_list[] __initdata = {
 	0x260, 0x280, 0x2a0, 0x240, 0x340, 0x320, 0x380, 0x300, 0
 };
 
+#else /* CONFIG_X86_PC9800 */
+static int at1700_probe_list[] __initdata = {
+	0x1d6, 0x1d8, 0x1da, 0x1d4, 0xd4, 0xd2, 0xd8, 0xd0, 0
+};
+
+#endif /* CONFIG_X86_PC9800 */
 /*
  *	MCA
  */
@@ -122,6 +133,7 @@
 
 
 /* Offsets from the base address. */
+#ifndef CONFIG_X86_PC9800
 #define STATUS			0
 #define TX_STATUS		0
 #define RX_STATUS		1
@@ -136,6 +148,7 @@
 #define TX_START		10
 #define COL16CNTL		11		/* Controll Reg for 16 collisions */
 #define MODE13			13
+#define RX_CTRL			14
 /* Configuration registers only on the '865A/B chips. */
 #define EEPROM_Ctrl 	16
 #define EEPROM_Data 	17
@@ -144,8 +157,39 @@
 #define IOCONFIG		18		/* Either read the jumper, or move the I/O. */
 #define IOCONFIG1		19
 #define	SAPROM			20		/* The station address PROM, if no EEPROM. */
+#define MODE24			24
 #define RESET			31		/* Write to reset some parts of the chip. */
 #define AT1700_IO_EXTENT	32
+#define PORT_OFFSET(o) (o)
+#else /* CONFIG_X86_PC9800 */
+#define STATUS			(0x0000)
+#define TX_STATUS		(0x0000)
+#define RX_STATUS		(0x0001)
+#define TX_INTR			(0x0200)/* Bit-mapped interrupt enable registers. */
+#define RX_INTR			(0x0201)
+#define TX_MODE			(0x0400)
+#define RX_MODE			(0x0401)
+#define CONFIG_0		(0x0600)/* Misc. configuration settings. */
+#define CONFIG_1		(0x0601)
+/* Run-time register bank 2 definitions. */
+#define DATAPORT		(0x0800)/* Word-wide DMA or programmed-I/O dataport. */
+#define TX_START		(0x0a00)
+#define COL16CNTL		(0x0a01)/* Controll Reg for 16 collisions */
+#define MODE13			(0x0c01)
+#define RX_CTRL			(0x0e00)
+/* Configuration registers only on the '865A/B chips. */
+#define EEPROM_Ctrl 	(0x1000)
+#define EEPROM_Data 	(0x1200)
+#define CARDSTATUS	16			/* FMV-18x Card Status */
+#define CARDSTATUS1	17			/* FMV-18x Card Status */
+#define IOCONFIG		(0x1400)/* Either read the jumper, or move the I/O. */
+#define IOCONFIG1		(0x1600)
+#define	SAPROM			20		/* The station address PROM, if no EEPROM. */
+#define	MODE24			(0x1800)/* The station address PROM, if no EEPROM. */
+#define RESET			(0x1e01)/* Write to reset some parts of the chip. */
+#define PORT_OFFSET(o) ({ int _o_ = (o); (_o_ & ~1) * 0x100 + (_o_ & 1); })
+#endif /* CONFIG_X86_PC9800 */
+
 
 #define TX_TIMEOUT		10
 
@@ -225,8 +269,20 @@
 	int slot, ret = -ENODEV;
 	struct net_local *lp;
 	
+#ifndef CONFIG_X86_PC9800
 	if (!request_region(ioaddr, AT1700_IO_EXTENT, dev->name))
 		return -EBUSY;
+#else
+	for (i = 0; i < 0x2000; i += 0x0200) {
+		if (!request_region(ioaddr + i, 2, dev->name)) {
+			while (i > 0) {
+				i -= 0x0200;
+				release_region(ioaddr + i, 2);
+			}
+			return -EBUSY;
+		}
+	}
+#endif
 
 		/* Resetting the chip doesn't reset the ISA interface, so don't bother.
 	   That means we have to be careful with the register values we probe for.
@@ -317,10 +373,17 @@
 		/* Reset the internal state machines. */
 	outb(0, ioaddr + RESET);
 
-	if (is_at1700)
+	if (is_at1700) {
+#ifndef CONFIG_X86_PC9800
 		irq = at1700_irqmap[(read_eeprom(ioaddr, 12)&0x04)
 						   | (read_eeprom(ioaddr, 0)>>14)];
-	else {
+#else
+		{
+			char re1000plus_irqmap[4] = {3, 5, 6, 12};
+			irq = re1000plus_irqmap[inb(ioaddr + IOCONFIG1) >> 6];
+		}
+#endif
+	} else {
 		/* Check PnP mode for FMV-183/184/183A/184A. */
 		/* This PnP routine is very poor. IO and IRQ should be known. */
 		if (inb(ioaddr + CARDSTATUS1) & 0x20) {
@@ -392,18 +455,22 @@
 	/* Set the station address in bank zero. */
 	outb(0x00, ioaddr + CONFIG_1);
 	for (i = 0; i < 6; i++)
-		outb(dev->dev_addr[i], ioaddr + 8 + i);
+		outb(dev->dev_addr[i], ioaddr + PORT_OFFSET(8 + i));
 
 	/* Switch to bank 1 and set the multicast table to accept none. */
 	outb(0x04, ioaddr + CONFIG_1);
 	for (i = 0; i < 8; i++)
-		outb(0x00, ioaddr + 8 + i);
+		outb(0x00, ioaddr + PORT_OFFSET(8 + i));
 
 
 	/* Switch to bank 2 */
 	/* Lock our I/O address, and set manual processing mode for 16 collisions. */
 	outb(0x08, ioaddr + CONFIG_1);
+#ifndef CONFIG_X86_PC9800
 	outb(dev->if_port, ioaddr + MODE13);
+#else
+	outb(0, ioaddr + MODE13);
+#endif
 	outb(0x00, ioaddr + COL16CNTL);
 
 	if (net_debug)
@@ -447,7 +514,12 @@
 	kfree(dev->priv);
 	dev->priv = NULL;
 err_out:
+#ifndef CONFIG_X86_PC9800
 	release_region(ioaddr, AT1700_IO_EXTENT);
+#else
+	for (i = 0; i < 0x2000; i += 0x0200)
+		release_region(ioaddr + i, 2);
+#endif
 	return ret;
 }
 
@@ -459,7 +531,11 @@
 #define EE_DATA_READ	0x80	/* EEPROM chip data out, in reg. 17. */
 
 /* Delay between EEPROM clock transitions. */
+#ifndef CONFIG_X86_PC9800
 #define eeprom_delay()	do { } while (0)
+#else
+#define eeprom_delay()	__asm__ ("out%B0 %%al,%0" :: "N"(0x5f))
+#endif
 
 /* The EEPROM commands include the alway-set leading bit. */
 #define EE_WRITE_CMD	(5 << 6)
@@ -542,12 +618,12 @@
 		inw (ioaddr + STATUS), inb (ioaddr + TX_STATUS) & 0x80
 		? "IRQ conflict" : "network cable problem");
 	printk ("%s: timeout registers: %04x %04x %04x %04x %04x %04x %04x %04x.\n",
-	 dev->name, inw (ioaddr + 0), inw (ioaddr + 2), inw (ioaddr + 4),
-		inw (ioaddr + 6), inw (ioaddr + 8), inw (ioaddr + 10),
-		inw (ioaddr + 12), inw (ioaddr + 14));
+	 dev->name, inw(ioaddr + TX_STATUS), inw(ioaddr + TX_INTR), inw(ioaddr + TX_MODE),
+		inw(ioaddr + CONFIG_0), inw(ioaddr + DATAPORT), inw(ioaddr + TX_START),
+		inw(ioaddr + MODE13 - 1), inw(ioaddr + RX_CTRL));
 	lp->stats.tx_errors++;
 	/* ToDo: We should try to restart the adaptor... */
-	outw (0xffff, ioaddr + 24);
+	outw(0xffff, ioaddr + MODE24);
 	outw (0xffff, ioaddr + TX_STATUS);
 	outb (0x5a, ioaddr + CONFIG_0);
 	outb (0xe8, ioaddr + CONFIG_1);
@@ -704,7 +780,7 @@
 				   dev->name, inb(ioaddr + RX_MODE), status);
 #ifndef final_version
 		if (status == 0) {
-			outb(0x05, ioaddr + 14);
+			outb(0x05, ioaddr + RX_CTRL);
 			break;
 		}
 #endif
@@ -724,7 +800,7 @@
 					   dev->name, pkt_len);
 				/* Prime the FIFO and then flush the packet. */
 				inw(ioaddr + DATAPORT); inw(ioaddr + DATAPORT);
-				outb(0x05, ioaddr + 14);
+				outb(0x05, ioaddr + RX_CTRL);
 				lp->stats.rx_errors++;
 				break;
 			}
@@ -734,7 +810,7 @@
 					   dev->name, pkt_len);
 				/* Prime the FIFO and then flush the packet. */
 				inw(ioaddr + DATAPORT); inw(ioaddr + DATAPORT);
-				outb(0x05, ioaddr + 14);
+				outb(0x05, ioaddr + RX_CTRL);
 				lp->stats.rx_dropped++;
 				break;
 			}
@@ -761,7 +837,7 @@
 			if ((inb(ioaddr + RX_MODE) & 0x40) == 0x40)
 				break;
 			inw(ioaddr + DATAPORT);				/* dummy status read */
-			outb(0x05, ioaddr + 14);
+			outb(0x05, ioaddr + RX_CTRL);
 		}
 
 		if (net_debug > 5)
@@ -851,7 +927,7 @@
 		/* Switch to bank 1 and set the multicast table. */
 		outw((saved_bank & ~0x0C00) | 0x0480, ioaddr + CONFIG_0);
 		for (i = 0; i < 8; i++)
-			outb(mc_filter[i], ioaddr + 8 + i);
+			outb(mc_filter[i], ioaddr + PORT_OFFSET(8 + i));
 		memcpy(lp->mc_filter, mc_filter, sizeof(mc_filter));
 		outw(saved_bank, ioaddr + CONFIG_0);
 	}
@@ -861,7 +937,12 @@
 
 #ifdef MODULE
 static struct net_device dev_at1700;
+#ifndef CONFIG_X86_PC9800
 static int io = 0x260;
+#else
+static int io = 0xd0;
+#endif
+
 static int irq;
 
 MODULE_PARM(io, "i");
@@ -901,7 +982,15 @@
 
 	/* If we don't do this, we can't re-insmod it later. */
 	free_irq(dev_at1700.irq, NULL);
+#ifndef CONFIG_X86_PC9800
 	release_region(dev_at1700.base_addr, AT1700_IO_EXTENT);
+#else
+	{
+		int i;
+		for (i = 0; i < 0x2000; i += 0x200)
+			release_region(dev_at1700.base_addr + i, 2);
+	}
+#endif
 }
 #endif /* MODULE */
 MODULE_LICENSE("GPL");
diff -Nru linux-2.5.61/drivers/net/ne.c linux98-2.5.61/drivers/net/ne.c
--- linux-2.5.61/drivers/net/ne.c	2003-02-15 08:51:42.000000000 +0900
+++ linux98-2.5.61/drivers/net/ne.c	2003-02-16 11:49:42.000000000 +0900
@@ -109,6 +109,10 @@
     {"PCM-4823", "PCM-4823", {0x00, 0xc0, 0x6c}}, /* Broken Advantech MoBo */
     {"REALTEK", "RTL8019", {0x00, 0x00, 0xe8}}, /* no-name with Realtek chip */
     {"LCS-8834", "LCS-8836", {0x04, 0x04, 0x37}}, /* ShinyNet (SET) */
+    {"LA/T-98?", "LA/T-98", {0x00, 0xa0, 0xb0}},	/* I/O Data */
+    {"EGY-98?", "EGY-98", {0x00, 0x40, 0x26}},		/* Melco EGY98 */
+    {"ICM?", "ICM-27xx-ET", {0x00, 0x80, 0xc8}},	/* ICM IF-27xx-ET */
+    {"CNET-98/EL?", "CNET(98)E/L", {0x00, 0x80, 0x4C}},	/* Contec CNET-98/EL */
     {0,}
 };
 #endif
@@ -116,9 +120,10 @@
 /* ---- No user-serviceable parts below ---- */
 
 #define NE_BASE	 (dev->base_addr)
-#define NE_CMD	 	0x00
-#define NE_DATAPORT	0x10	/* NatSemi-defined port window offset. */
-#define NE_RESET	0x1f	/* Issue a read to reset, a write to clear. */
+#define NE_CMD	 	EI_SHIFT(0x00)
+#define NE_DATAPORT	EI_SHIFT(0x10)	/* NatSemi-defined port window offset. */
+#define NE_RESET	EI_SHIFT(0x1f) /* Issue a read to reset, a write to clear. */
+
 #define NE_IO_EXTENT	0x20
 
 #define NE1SM_START_PG	0x20	/* First page of TX buffer */
@@ -126,9 +131,15 @@
 #define NESM_START_PG	0x40	/* First page of TX buffer */
 #define NESM_STOP_PG	0x80	/* Last page +1 of RX ring */
 
+#ifdef CONFIG_NET_CBUS
+#include "ne2k_cbus.h"
+#endif
+
 int ne_probe(struct net_device *dev);
 static int ne_probe1(struct net_device *dev, int ioaddr);
+#ifndef CONFIG_NET_CBUS
 static int ne_probe_isapnp(struct net_device *dev);
+#endif
 
 static int ne_open(struct net_device *dev);
 static int ne_close(struct net_device *dev);
@@ -163,6 +174,8 @@
 	E2010	 starts at 0x100 and ends at 0x4000.
 	E2010-x starts at 0x100 and ends at 0xffff.  */
 
+#ifndef CONFIG_NET_CBUS
+
 int __init ne_probe(struct net_device *dev)
 {
 	unsigned int base_addr = dev->base_addr;
@@ -236,6 +249,116 @@
 	return -ENODEV;
 }
 
+#else /* CONFIG_NET_CBUS */
+
+int __init ne_probe(struct net_device *dev)
+{
+	unsigned int base_addr = dev->base_addr;
+
+	SET_MODULE_OWNER(dev);
+
+	if (ei_debug > 2)
+		printk(KERN_DEBUG "ne_probe(): entered.\n");
+
+	/* If CONFIG_NET_CBUS,
+	   we need dev->priv->reg_offset BEFORE to probe */
+	if (ne2k_cbus_init(dev) != 0) {
+		return -ENOMEM;
+	}
+
+	/* First check any supplied i/o locations. User knows best. <cough> */
+	if (base_addr > 0) {
+		int result;
+		const struct ne2k_cbus_hwinfo *hw = ne2k_cbus_get_hwinfo((int)(dev->mem_start & NE2K_CBUS_HARDWARE_TYPE_MASK));
+
+		if (ei_debug > 2)
+			printk(KERN_DEBUG "ne_probe(): call ne_probe_cbus(base_addr=0x%x)\n", base_addr);
+
+		result = ne_probe_cbus(dev, hw, base_addr);
+		if (result != 0)
+			ne2k_cbus_destroy(dev);
+
+		return result;
+	}
+
+	if (ei_debug > 2)
+		printk(KERN_DEBUG "ne_probe(): base_addr is not specified.\n");
+
+#ifndef MODULE
+	/* Last resort. The semi-risky C-Bus auto-probe. */
+	if (ei_debug > 2)
+		printk(KERN_DEBUG "ne_probe(): auto-probe start.\n");
+
+	{
+		const struct ne2k_cbus_hwinfo *hw = ne2k_cbus_get_hwinfo((int)(dev->mem_start & NE2K_CBUS_HARDWARE_TYPE_MASK));
+
+		if (hw && hw->hwtype) {
+			const unsigned short *plist;
+			for (plist = hw->portlist; *plist; plist++) {
+				const struct ne2k_cbus_region *rlist;
+				for (rlist = hw->regionlist; rlist->range; rlist++) {
+					if (check_region(*plist+rlist->start, rlist->range))
+						break;
+				}
+				if (rlist->range) {
+					/* check_region() failed */ 
+					continue; /* try next base port */
+				}
+				/* check_region() succeeded */
+				if (ne_probe_cbus(dev,hw,*plist) == 0)
+					return 0;
+			}
+		} else {
+			for (hw = &ne2k_cbus_hwinfo_list[0]; hw->hwtype; hw++) {
+				const unsigned short *plist;
+				for(plist=hw->portlist; *plist; plist++){
+					const struct ne2k_cbus_region *rlist;
+
+					for (rlist = hw->regionlist; rlist->range; rlist++) {
+						if (check_region(*plist+rlist->start, rlist->range))
+							break;
+					}
+					if (rlist->range) {
+						/* check_region() failed */ 
+						continue; /* try next base port */
+					}
+					/* check_region() succeeded */
+					if (ne_probe_cbus(dev,hw,*plist) == 0)
+						return 0;
+				}
+			}
+		}
+	}
+#endif
+
+	ne2k_cbus_destroy(dev);
+
+	return -ENODEV;
+}
+
+static int __init ne_probe_cbus(struct net_device *dev, const struct ne2k_cbus_hwinfo *hw, int ioaddr)
+{
+	if (ei_debug > 2)
+		printk(KERN_DEBUG "ne_probe_cbus(): entered. (called from %p)\n",
+		       __builtin_return_address(0));
+
+	if (hw && hw->hwtype) {
+		ne2k_cbus_set_hwtype(dev, hw, ioaddr);
+		return ne_probe1(dev, ioaddr);
+	} else {
+		/* auto detect */
+
+		printk(KERN_DEBUG "ne_probe_cbus(): try to determine hardware types.\n");
+		for (hw = &ne2k_cbus_hwinfo_list[0]; hw->hwtype; hw++) {
+			ne2k_cbus_set_hwtype(dev, hw, ioaddr);
+			if (ne_probe1(dev, ioaddr)==0)
+				return 0;
+		}
+	}
+	return ENODEV;
+}
+#endif /* !CONFIG_NET_CBUS */
+
 static int __init ne_probe1(struct net_device *dev, int ioaddr)
 {
 	int i;
@@ -243,30 +366,62 @@
 	int wordlength = 2;
 	const char *name = NULL;
 	int start_page, stop_page;
-	int neX000, ctron, copam, bad_card;
+	int neX000, bad_card;
+#ifndef CONFIG_NET_CBUS
+	int ctron, copam;
+#endif
 	int reg0, ret;
 	static unsigned version_printed;
+#ifdef CONFIG_NET_CBUS
+	const struct ne2k_cbus_hwinfo *hw = ne2k_cbus_get_hwinfo((int)(dev->mem_start & NE2K_CBUS_HARDWARE_TYPE_MASK));
+	struct ei_device *ei_local = (struct ei_device *)(dev->priv);
+#endif
+
+#ifdef CONFIG_NE2K_CBUS_CNET98EL
+	if (hw->hwtype == NE2K_CBUS_HARDWARE_TYPE_CNET98EL) {
+		outb_p(0, CONFIG_NE2K_CBUS_CNET98EL_IO_BASE);
+		/* udelay(5000);	*/
+		outb_p(1, CONFIG_NE2K_CBUS_CNET98EL_IO_BASE);
+		/* udelay(5000);	*/
+		outb_p((ioaddr & 0xf000) >> 8 | 0x08 | 0x01, CONFIG_NE2K_CBUS_CNET98EL_IO_BASE + 2);
+		/* udelay(5000); */
+	}
+#endif
 
+#ifndef CONFIG_NET_CBUS
 	if (!request_region(ioaddr, NE_IO_EXTENT, dev->name))
 		return -EBUSY;
+#else /* CONFIG_NET_CBUS */
+	{
+		const struct ne2k_cbus_region *rlist;
+		for (rlist = hw->regionlist; rlist->range; rlist++) {
+			if (!request_region(ioaddr + rlist->start,
+						rlist->range, dev->name))
+				return -EBUSY;
+		}
+	}
+#endif /* !CONFIG_NET_CBUS */
 
-	reg0 = inb_p(ioaddr);
+	reg0 = inb_p(ioaddr + EI_SHIFT(0));
 	if (reg0 == 0xFF) {
 		ret = -ENODEV;
 		goto err_out;
 	}
 
 	/* Do a preliminary verification that we have a 8390. */
+#ifdef CONFIG_NE2K_CBUS_CNET98EL
+	if (hw->hwtype != NE2K_CBUS_HARDWARE_TYPE_CNET98EL)
+#endif
 	{
 		int regd;
 		outb_p(E8390_NODMA+E8390_PAGE1+E8390_STOP, ioaddr + E8390_CMD);
-		regd = inb_p(ioaddr + 0x0d);
-		outb_p(0xff, ioaddr + 0x0d);
+		regd = inb_p(ioaddr + EI_SHIFT(0x0d));
+		outb_p(0xff, ioaddr + EI_SHIFT(0x0d));
 		outb_p(E8390_NODMA+E8390_PAGE0, ioaddr + E8390_CMD);
 		inb_p(ioaddr + EN0_COUNTER0); /* Clear the counter by reading. */
 		if (inb_p(ioaddr + EN0_COUNTER0) != 0) {
 			outb_p(reg0, ioaddr);
-			outb_p(regd, ioaddr + 0x0d);	/* Restore the old values. */
+			outb_p(regd, ioaddr + EI_SHIFT(0x0d));	/* Restore the old values. */
 			ret = -ENODEV;
 			goto err_out;
 		}
@@ -290,6 +445,11 @@
 	{
 		unsigned long reset_start_time = jiffies;
 
+#ifdef CONFIG_NET_CBUS
+		/* derived from CNET98EL-patch for bad clones */
+		outb_p(E8390_NODMA | E8390_STOP, ioaddr+E8390_CMD);
+#endif
+
 		/* DON'T change these to inb_p/outb_p or reset will fail on clones. */
 		outb(inb(ioaddr + NE_RESET), ioaddr + NE_RESET);
 
@@ -308,15 +468,86 @@
 		outb_p(0xff, ioaddr + EN0_ISR);		/* Ack all intr. */
 	}
 
+#ifdef CONFIG_NE2K_CBUS_CNET98EL
+	if (hw->hwtype == NE2K_CBUS_HARDWARE_TYPE_CNET98EL) {
+		static const char pat[32] ="AbcdeFghijKlmnoPqrstUvwxyZ789012";
+		char buf[32];
+		int maxwait = 200;
+
+		if (ei_debug > 2) {
+			printk(" [CNET98EL-specific initialize...");
+		}
+		outb_p(E8390_NODMA | E8390_STOP, ioaddr+E8390_CMD); /* 0x20|0x1 */
+		i=inb(ioaddr);
+		if ((i & ~0x2) != (0x20 | 0x01))
+			return ENODEV;
+		if ((inb(ioaddr + 0x7) & 0x80) != 0x80)
+			return ENODEV;
+		outb_p(E8390_RXOFF, ioaddr+EN0_RXCR); /* out(ioaddr+0xc, 0x20) */
+		/* outb_p(ENDCFG_WTS|ENDCFG_FT1|ENDCFG_LS, ioaddr+EN0_DCFG); */
+		outb_p(ENDCFG_WTS|0x48, ioaddr+EN0_DCFG); /* 0x49 */
+		outb_p(CNET98EL_START_PG, ioaddr+EN0_STARTPG);
+		outb_p(CNET98EL_STOP_PG, ioaddr+EN0_STOPPG);
+		if (ei_debug > 2) {
+			printk("memory check");
+		}
+		for (i = 0; i < 65536; i += 1024) {
+			if (ei_debug > 2) {
+				printk(" %04x",i);
+			}
+			ne2k_cbus_writemem(dev,ioaddr, i, pat, 32);
+			while (((inb(ioaddr + EN0_ISR) & ENISR_RDC) != ENISR_RDC) && --maxwait)
+				;
+			ne2k_cbus_readmem(dev, ioaddr, i, buf, 32);
+			if (memcmp(pat, buf, 32)) {
+				if (ei_debug > 2) {
+					printk(" failed.");
+				}
+				break;
+			}
+		}
+		if (i != 16384) {
+			if (ei_debug > 2) {
+				printk("] ");
+			}
+			printk("memory failure at %x\n", i);
+			return ENODEV;
+		}
+		if (ei_debug > 2) {
+			printk(" good...");
+		}
+		if (!dev->irq) {
+			if (ei_debug > 2) {
+				printk("] ");
+			}
+			printk("IRQ must be specified for C-NET(98)E/L. probe failed.\n");
+			return ENODEV;
+		}
+		outb((dev->irq>5) ? (dev->irq&4):(dev->irq>>1), ioaddr + (0x2 | 0x400));
+		outb(0x7e, ioaddr + (0x4 | 0x400));
+		ne2k_cbus_readmem(dev, ioaddr, 16384, SA_prom, 32);
+		outb(0xff, ioaddr + EN0_ISR);
+		if (ei_debug > 2) {
+			printk("done]");
+		}
+	} else
+#endif /* CONFIG_NE2K_CBUS_CNET98EL */
 	/* Read the 16 bytes of station address PROM.
 	   We must first initialize registers, similar to NS8390_init(eifdev, 0).
 	   We can't reliably read the SAPROM address without this.
 	   (I learned the hard way!). */
 	{
-		struct {unsigned char value, offset; } program_seq[] =
+		struct {unsigned char value; unsigned short offset;} program_seq[] = 
 		{
 			{E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD}, /* Select page 0*/
+#ifndef CONFIG_NET_CBUS
 			{0x48,	EN0_DCFG},	/* Set byte-wide (0x48) access. */
+#else
+			/* NEC PC-9800: some board can only handle word-wide access? */
+			{0x48 | ENDCFG_WTS,	EN0_DCFG},	/* Set word-wide (0x48) access. */
+			{16384 / 256, EN0_STARTPG},
+			{32768 / 256, EN0_STOPPG},
+#endif
 			{0x00,	EN0_RCNTLO},	/* Clear the count regs. */
 			{0x00,	EN0_RCNTHI},
 			{0x00,	EN0_IMR},	/* Mask completion irq. */
@@ -332,29 +563,42 @@
 
 		for (i = 0; i < sizeof(program_seq)/sizeof(program_seq[0]); i++)
 			outb_p(program_seq[i].value, ioaddr + program_seq[i].offset);
-
-	}
+#ifndef CONFIG_NET_CBUS
 	for(i = 0; i < 32 /*sizeof(SA_prom)*/; i+=2) {
 		SA_prom[i] = inb(ioaddr + NE_DATAPORT);
 		SA_prom[i+1] = inb(ioaddr + NE_DATAPORT);
 		if (SA_prom[i] != SA_prom[i+1])
 			wordlength = 1;
 	}
+#else
+	insw(ioaddr + NE_DATAPORT, SA_prom, 32 >> 1);
+#endif
+
+	}
 
 	if (wordlength == 2)
 	{
 		for (i = 0; i < 16; i++)
 			SA_prom[i] = SA_prom[i+i];
+#ifndef CONFIG_NET_CBUS
 		/* We must set the 8390 for word mode. */
 		outb_p(0x49, ioaddr + EN0_DCFG);
+#endif
 		start_page = NESM_START_PG;
 		stop_page = NESM_STOP_PG;
+#ifdef CONFIG_NE2K_CBUS_CNET98EL
+		if (hw->hwtype == NE2K_CBUS_HARDWARE_TYPE_CNET98EL) {
+			start_page = CNET98EL_START_PG;
+			stop_page = CNET98EL_STOP_PG;
+		}
+#endif
 	} else {
 		start_page = NE1SM_START_PG;
 		stop_page = NE1SM_STOP_PG;
 	}
 
 	neX000 = (SA_prom[14] == 0x57  &&  SA_prom[15] == 0x57);
+#ifndef CONFIG_NET_CBUS
 	ctron =  (SA_prom[0] == 0x00 && SA_prom[1] == 0x00 && SA_prom[2] == 0x1d);
 	copam =  (SA_prom[14] == 0x49 && SA_prom[15] == 0x00);
 
@@ -368,6 +612,11 @@
 		start_page = 0x01;
 		stop_page = (wordlength == 2) ? 0x40 : 0x20;
 	}
+#else
+	if (neX000) {
+		name = "C-Bus-NE2K-compat";
+	}
+#endif
 	else
 	{
 #ifdef SUPPORT_NE_BAD_CLONES
@@ -414,10 +663,18 @@
 		dev->irq = probe_irq_off(cookie);
 		if (ei_debug > 2)
 			printk(" autoirq is %d\n", dev->irq);
-	} else if (dev->irq == 2)
+	} else
+#ifndef CONFIG_X86_PC9800
+	if (dev->irq == 2)
 		/* Fixup for users that don't know that IRQ 2 is really IRQ 9,
 		   or don't know which one to set. */
 		dev->irq = 9;
+#else
+	if (dev->irq == 7)
+		/* Fixup for users that don't know that IRQ 7 is really IRQ 11,
+		   or don't know which one to set. */
+		dev->irq = 11;
+#endif
 
 	if (! dev->irq) {
 		printk(" failed to detect IRQ line.\n");
@@ -448,8 +705,13 @@
 		dev->dev_addr[i] = SA_prom[i];
 	}
 
+#ifndef CONFIG_NET_CBUS
 	printk("\n%s: %s found at %#x, using IRQ %d.\n",
 		dev->name, name, ioaddr, dev->irq);
+#else
+	printk("\n%s: %s found at %#x, hardware type %d(%s), using IRQ %d.\n",
+		   dev->name, name, ioaddr, hw->hwtype, hw->hwident, dev->irq);
+#endif
 
 	ei_status.name = name;
 	ei_status.tx_start_page = start_page;
@@ -473,10 +735,23 @@
 	return 0;
 
 err_out_kfree:
+#ifndef CONFIG_NET_CBUS
 	kfree(dev->priv);
 	dev->priv = NULL;
+#else
+	ne2k_cbus_destroy(dev);
+#endif
 err_out:
+#ifndef CONFIG_NET_CBUS
 	release_region(ioaddr, NE_IO_EXTENT);
+#else
+	{
+		const struct ne2k_cbus_region *rlist;
+		for (rlist = hw->regionlist; rlist->range; rlist++) {
+			release_region(ioaddr + rlist->start, rlist->range);
+		}
+	}
+#endif
 	return ret;
 }
 
@@ -500,10 +775,18 @@
 static void ne_reset_8390(struct net_device *dev)
 {
 	unsigned long reset_start_time = jiffies;
+#ifdef CONFIG_NET_CBUS
+	struct ei_device *ei_local = (struct ei_device *)(dev->priv);
+#endif
 
 	if (ei_debug > 1)
 		printk(KERN_DEBUG "resetting the 8390 t=%ld...", jiffies);
 
+#ifdef CONFIG_NET_CBUS
+	/* derived from CNET98EL-patch for bad clones... */
+	outb_p(E8390_NODMA | E8390_STOP, NE_BASE + E8390_CMD);  /* 0x20 | 0x1 */
+#endif
+
 	/* DON'T change these to inb_p/outb_p or reset will fail on clones. */
 	outb(inb(NE_BASE + NE_RESET), NE_BASE + NE_RESET);
 
@@ -526,6 +809,9 @@
 static void ne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
 {
 	int nic_base = dev->base_addr;
+#ifdef CONFIG_NET_CBUS
+	struct ei_device *ei_local = (struct ei_device *)(dev->priv);
+#endif
 
 	/* This *shouldn't* happen. If it does, it's the last thing you'll see */
 
@@ -568,6 +854,9 @@
 #endif
 	int nic_base = dev->base_addr;
 	char *buf = skb->data;
+#ifdef CONFIG_NET_CBUS
+	struct ei_device *ei_local = (struct ei_device *)(dev->priv);
+#endif
 
 	/* This *shouldn't* happen. If it does, it's the last thing you'll see */
 	if (ei_status.dmaing)
@@ -578,6 +867,12 @@
 		return;
 	}
 	ei_status.dmaing |= 0x01;
+
+#ifdef CONFIG_NET_CBUS
+	/* round up count to a word (derived from ICM-patch) */
+	count = (count + 1) & ~1;
+#endif
+
 	outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
 	outb_p(count & 0xff, nic_base + EN0_RCNTLO);
 	outb_p(count >> 8, nic_base + EN0_RCNTHI);
@@ -635,6 +930,9 @@
 #ifdef NE_SANITY_CHECK
 	int retries = 0;
 #endif
+#ifdef CONFIG_NET_CBUS
+	struct ei_device *ei_local = (struct ei_device *)(dev->priv);
+#endif
 
 	/* Round the count up for word writes.  Do we need to do this?
 	   What effect will an odd byte count have on the 8390?
@@ -738,13 +1036,22 @@
 static int io[MAX_NE_CARDS];
 static int irq[MAX_NE_CARDS];
 static int bad[MAX_NE_CARDS];	/* 0xbad = bad sig or no reset ack */
+#ifdef CONFIG_NET_CBUS
+static int hwtype[MAX_NE_CARDS] = { 0, }; /* board type */
+#endif
 
 MODULE_PARM(io, "1-" __MODULE_STRING(MAX_NE_CARDS) "i");
 MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_NE_CARDS) "i");
 MODULE_PARM(bad, "1-" __MODULE_STRING(MAX_NE_CARDS) "i");
+#ifdef CONFIG_NET_CBUS
+MODULE_PARM(hwtype, "1-" __MODULE_STRING(MAX_NE_CARDS) "i");
+#endif
 MODULE_PARM_DESC(io, "I/O base address(es),required");
 MODULE_PARM_DESC(irq, "IRQ number(s)");
 MODULE_PARM_DESC(bad, "Accept card(s) with bad signatures");
+#ifdef CONFIG_NET_CBUS
+MODULE_PARM_DESC(hwtype, "Board type of PC-9800 C-Bus NIC");
+#endif
 MODULE_DESCRIPTION("NE1000/NE2000 ISA/PnP Ethernet driver");
 MODULE_LICENSE("GPL");
 
@@ -762,6 +1069,9 @@
 		dev->irq = irq[this_dev];
 		dev->mem_end = bad[this_dev];
 		dev->base_addr = io[this_dev];
+#ifdef CONFIG_NET_CBUS
+		dev->mem_start = hwtype[this_dev];
+#endif
 		dev->init = ne_probe;
 		if (register_netdev(dev) == 0) {
 			found++;
@@ -791,9 +1101,23 @@
 			if (idev)
 				pnp_device_detach(idev);
 			free_irq(dev->irq, dev);
+#ifndef CONFIG_NET_CBUS
 			release_region(dev->base_addr, NE_IO_EXTENT);
+#else /* CONFIG_NET_CBUS */
+			{
+				const struct ne2k_cbus_hwinfo *hw = ne2k_cbus_get_hwinfo((int)(dev->mem_start & NE2K_CBUS_HARDWARE_TYPE_MASK));
+				const struct ne2k_cbus_region *rlist;
+				for (rlist = hw->regionlist; rlist->range; rlist++) {
+					release_region(dev->base_addr + rlist->start, rlist->range);
+				}
+			}
+#endif /* !CONFIG_NET_CBUS */
 			unregister_netdev(dev);
+#ifndef CONFIG_NET_CBUS
 			kfree(priv);
+#else
+			ne2k_cbus_destroy(dev);
+#endif
 		}
 	}
 }
diff -Nru linux-2.5.50/drivers/net/ne2k_cbus.h linux98-2.5.50/drivers/net/ne2k_cbus.h
--- linux-2.5.42/drivers/net/ne2k_cbus.h	1970-01-01 09:00:00.000000000 +0900
+++ linux98-2.5.42/drivers/net/ne2k_cbus.h	2002-12-15 10:56:15.000000000 +0900
@@ -0,0 +1,481 @@
+/* ne2k_cbus.h: 
+   vender-specific information definition for NEC PC-9800
+   C-bus Ethernet Cards
+   Used in ne.c 
+
+   (C)1998,1999 KITAGWA Takurou & Linux/98 project
+*/
+
+#include <linux/config.h>
+
+#undef NE_RESET
+#define NE_RESET EI_SHIFT(0x11) /* Issue a read to reset, a write to clear. */
+
+#ifdef CONFIG_NE2K_CBUS_CNET98EL
+#ifndef CONFIG_NE2K_CBUS_CNET98EL_IO_BASE
+#warning CONFIG_NE2K_CBUS_CNET98EL_IO_BASE is not defined(config error?)
+#warning use 0xaaed as default
+#define CONFIG_NE2K_CBUS_CNET98EL_IO_BASE 0xaaed /* or 0x55ed */
+#endif
+#define CNET98EL_START_PG 0x00
+#define CNET98EL_STOP_PG 0x40
+#endif
+
+/* Hardware type definition (derived from *BSD) */
+#define NE2K_CBUS_HARDWARE_TYPE_MASK 0xff
+
+/* 0: reserved for auto-detect */
+/* 1: (not tested)
+   Allied Telesis CentreCom LA-98-T */
+#define NE2K_CBUS_HARDWARE_TYPE_ATLA98 1
+/* 2: (not tested)
+   ELECOM Laneed
+   LD-BDN[123]A
+   PLANET SMART COM 98 EN-2298-C
+   MACNICA ME98 */
+#define NE2K_CBUS_HARDWARE_TYPE_BDN 2
+/* 3:
+   Melco EGY-98
+   Contec C-NET(98)E*A/L*A,C-NET(98)P */
+#define NE2K_CBUS_HARDWARE_TYPE_EGY98 3
+/* 4:
+   Melco LGY-98,IND-SP,IND-SS
+   MACNICA NE2098 */
+#define NE2K_CBUS_HARDWARE_TYPE_LGY98 4
+/* 5:
+   ICM DT-ET-25,DT-ET-T5,IF-2766ET,IF-2771ET
+   PLANET SMART COM 98 EN-2298-T,EN-2298P-T
+   D-Link DE-298PT,DE-298PCAT
+   ELECOM Laneed LD-98P */
+#define NE2K_CBUS_HARDWARE_TYPE_ICM 5
+/* 6: (reserved for SIC-98, which is not supported in this driver.) */
+/* 7: (unused in *BSD?)
+   <Original NE2000 compatible>
+   <for PCI/PCMCIA cards>
+*/
+#define NE2K_CBUS_HARDWARE_TYPE_NE2K 7
+/* 8:
+   NEC PC-9801-108 */
+#define NE2K_CBUS_HARDWARE_TYPE_NEC108 8
+/* 9:
+   I-O DATA LA-98,LA/T-98 */
+#define NE2K_CBUS_HARDWARE_TYPE_IOLA98 9
+/* 10: (reserved for C-NET(98), which is not supported in this driver.) */
+/* 11:
+   Contec C-NET(98)E,L */
+#define NE2K_CBUS_HARDWARE_TYPE_CNET98EL 11
+
+#define NE2K_CBUS_HARDWARE_TYPE_MAX 11
+
+/* HARDWARE TYPE ID 12-31: reserved */
+
+struct ne2k_cbus_offsetinfo {
+	unsigned short skip;
+	unsigned short offset8; /* +0x8 - +0xf */
+	unsigned short offset10; /* +0x10 */
+	unsigned short offset1f; /* +0x1f */
+};
+
+struct ne2k_cbus_region {
+	unsigned short start;
+	short range;
+};
+
+struct ne2k_cbus_hwinfo {
+	const unsigned short hwtype;
+	const unsigned char *hwident;
+#ifndef MODULE
+	const unsigned short *portlist;
+#endif
+	const struct ne2k_cbus_offsetinfo *offsetinfo;
+	const struct ne2k_cbus_region *regionlist;
+};
+
+#ifdef CONFIG_NE2K_CBUS_ATLA98
+#ifndef MODULE
+static unsigned short atla98_portlist[] __initdata = {
+	0xd0,
+	0
+};
+#endif
+#define atla98_offsetinfo ne2k_offsetinfo
+#define atla98_regionlist ne2k_regionlist
+#endif /* CONFIG_NE2K_CBUS_ATLA98 */
+
+#ifdef CONFIG_NE2K_CBUS_BDN
+#ifndef MODULE
+static unsigned short bdn_portlist[] __initdata = {
+	0xd0,
+	0
+};
+#endif
+static struct ne2k_cbus_offsetinfo bdn_offsetinfo __initdata = {
+#if 0
+	/* comes from FreeBSD(98) ed98.h */
+	0x1000, 0x8000, 0x100, 0xc200 /* ??? */
+#else
+	/* comes from NetBSD/pc98 if_ne_isa.c */
+	0x1000, 0x8000, 0x100, 0x7f00 /* ??? */
+#endif
+};
+static struct ne2k_cbus_region bdn_regionlist[] __initdata = {
+	{0x0, 1}, {0x1000, 1}, {0x2000, 1}, {0x3000,1},
+	{0x4000, 1}, {0x5000, 1}, {0x6000, 1}, {0x7000, 1},
+	{0x8000, 1}, {0x9000, 1}, {0xa000, 1}, {0xb000, 1},
+	{0xc000, 1}, {0xd000, 1}, {0xe000, 1}, {0xf000, 1},
+	{0x100, 1}, {0x7f00, 1},
+	{0x0, 0}
+};
+#endif /* CONFIG_NE2K_CBUS_BDN */
+
+#ifdef CONFIG_NE2K_CBUS_EGY98
+#ifndef MODULE
+static unsigned short egy98_portlist[] __initdata = {
+	0xd0,
+	0
+};
+#endif
+static struct ne2k_cbus_offsetinfo egy98_offsetinfo __initdata = {
+	0x02, 0x100, 0x200, 0x300
+};
+static struct ne2k_cbus_region egy98_regionlist[] __initdata = {
+	{0x0, 1}, {0x2, 1}, {0x4, 1}, {0x6, 1},
+	{0x8, 1}, {0xa, 1}, {0xc, 1}, {0xe, 1},
+	{0x100, 1}, {0x102, 1}, {0x104, 1}, {0x106, 1},
+	{0x108, 1}, {0x10a, 1}, {0x10c, 1}, {0x10e, 1},
+	{0x200, 1}, {0x300, 1},
+	{0x0, 0}
+};
+#endif /* CONFIG_NE2K_CBUS_EGY98 */
+
+#ifdef CONFIG_NE2K_CBUS_LGY98
+#ifndef MODULE
+static unsigned short lgy98_portlist[] __initdata = {
+	0xd0, 0x10d0, 0x20d0, 0x30d0, 0x40d0, 0x50d0, 0x60d0, 0x70d0,
+	0
+};
+#endif
+static struct ne2k_cbus_offsetinfo lgy98_offsetinfo __initdata = {
+	0x01, 0x08, 0x200, 0x300
+};
+static struct ne2k_cbus_region lgy98_regionlist[] __initdata = {
+	{0x0, 16}, {0x200, 1}, {0x300, 1},
+	{0x0, 0}
+};
+#endif /* CONFIG_NE2K_CBUS_LGY98 */
+
+#ifdef CONFIG_NE2K_CBUS_ICM
+#ifndef MODULE
+static unsigned short icm_portlist[] __initdata = {
+	/* ICM */
+	0x56d0,
+	/* LD-98PT */
+	0x46d0, 0x66d0, 0x76d0, 0x86d0, 0x96d0, 0xa6d0, 0xb6d0, 0xc6d0,
+	0
+};
+#endif
+static struct ne2k_cbus_offsetinfo icm_offsetinfo __initdata = {
+	0x01, 0x08, 0x100, 0x10f
+};
+static struct ne2k_cbus_region icm_regionlist[] __initdata = {
+	{0x0, 16}, {0x100, 16},
+	{0x0, 0}
+};
+#endif /* CONFIG_NE2K_CBUS_ICM */
+
+#if defined(CONFIG_NE2K_CBUS_NE2K) && !defined(MODULE)
+static unsigned short ne2k_portlist[] __initdata = {
+	0xd0, 0x300, 0x280, 0x320, 0x340, 0x360, 0x380,
+	0
+};
+#endif
+#if defined(CONFIG_NE2K_CBUS_NE2K) || defined(CONFIG_NE2K_CBUS_ATLA98)
+static struct ne2k_cbus_offsetinfo ne2k_offsetinfo __initdata = {
+	0x01, 0x08, 0x10, 0x1f
+};
+static struct ne2k_cbus_region ne2k_regionlist[] __initdata = {
+	{0x0, 32},
+	{0x0, 0}
+};
+#endif
+
+#ifdef CONFIG_NE2K_CBUS_NEC108
+#ifndef MODULE
+static unsigned short nec108_portlist[] __initdata = {
+	0x770, 0x2770, 0x4770, 0x6770,
+	0
+};
+#endif
+static struct ne2k_cbus_offsetinfo nec108_offsetinfo __initdata = {
+	0x02, 0x1000, 0x888, 0x88a
+};
+static struct ne2k_cbus_region nec108_regionlist[] __initdata = {
+	{0x0, 1}, {0x2, 1}, {0x4, 1}, {0x6, 1},
+	{0x8, 1}, {0xa, 1}, {0xc, 1}, {0xe, 1},
+	{0x1000, 1}, {0x1002, 1}, {0x1004, 1}, {0x1006, 1},
+	{0x1008, 1}, {0x100a, 1}, {0x100c, 1}, {0x100e, 1},
+	{0x888, 1}, {0x88a, 1}, {0x88c, 1}, {0x88e, 1},
+	{0x0, 0}
+};
+#endif
+
+#ifdef CONFIG_NE2K_CBUS_IOLA98
+#ifndef MODULE
+static unsigned short iola98_portlist[] __initdata = {
+	0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde,
+	0
+};
+#endif
+static struct ne2k_cbus_offsetinfo iola98_offsetinfo __initdata = {
+	0x1000, 0x8000, 0x100, 0xf100
+};
+static struct ne2k_cbus_region iola98_regionlist[] __initdata = {
+	{0x0, 1}, {0x1000, 1}, {0x2000, 1}, {0x3000, 1},
+	{0x4000, 1}, {0x5000, 1}, {0x6000, 1}, {0x7000, 1},
+	{0x8000, 1}, {0x9000, 1}, {0xa000, 1}, {0xb000, 1},
+	{0xc000, 1}, {0xd000, 1}, {0xe000, 1}, {0xf000, 1},
+	{0x100, 1}, {0xf100, 1},
+	{0x0,0}
+};
+#endif /* CONFIG_NE2K_CBUS_IOLA98 */
+
+#ifdef CONFIG_NE2K_CBUS_CNET98EL
+#ifndef MODULE
+static unsigned short cnet98el_portlist[] __initdata = {
+	0x3d0, 0x13d0, 0x23d0, 0x33d0, 0x43d0, 0x53d0, 0x60d0, 0x70d0,
+	0
+};
+#endif
+static struct ne2k_cbus_offsetinfo cnet98el_offsetinfo __initdata = {
+	0x01, 0x08, 0x40e, 0x400
+};
+static struct ne2k_cbus_region cnet98el_regionlist[] __initdata = {
+	{0x0, 16}, {0x400, 16},
+	{0x0, 0}
+};
+#endif
+
+
+/* port information table (for ne.c initialize/probe process) */
+
+static struct ne2k_cbus_hwinfo ne2k_cbus_hwinfo_list[] __initdata = {
+#ifdef CONFIG_NE2K_CBUS_ATLA98
+/* NOT TESTED */
+	{
+		NE2K_CBUS_HARDWARE_TYPE_ATLA98,
+		"LA-98-T",
+#ifndef MODULE
+		atla98_portlist,
+#endif
+		&atla98_offsetinfo, atla98_regionlist
+	},
+#endif
+#ifdef CONFIG_NE2K_CBUS_BDN
+/* NOT TESTED */
+	{
+		NE2K_CBUS_HARDWARE_TYPE_BDN,
+		"LD-BDN[123]A",
+#ifndef MODULE
+		bdn_portlist,
+#endif
+		&bdn_offsetinfo, bdn_regionlist
+	},
+#endif
+#ifdef CONFIG_NE2K_CBUS_ICM
+	{
+		NE2K_CBUS_HARDWARE_TYPE_ICM,
+		"IF-27xxET",
+#ifndef MODULE
+		icm_portlist,
+#endif
+		&icm_offsetinfo, icm_regionlist
+	},
+#endif
+#ifdef CONFIG_NE2K_CBUS_NE2K
+	{
+		NE2K_CBUS_HARDWARE_TYPE_NE2K,
+		"NE2000 compat.",
+#ifndef MODULE
+		ne2k_portlist,
+#endif
+		&ne2k_offsetinfo, ne2k_regionlist
+	},
+#endif
+#ifdef CONFIG_NE2K_CBUS_NEC108
+	{
+		NE2K_CBUS_HARDWARE_TYPE_NEC108,
+		"PC-9801-108",
+#ifndef MODULE
+		nec108_portlist,
+#endif
+		&nec108_offsetinfo, nec108_regionlist
+	},
+#endif
+#ifdef CONFIG_NE2K_CBUS_IOLA98
+	{
+		NE2K_CBUS_HARDWARE_TYPE_IOLA98,
+		"LA-98",
+#ifndef MODULE
+		iola98_portlist,
+#endif
+		&iola98_offsetinfo, iola98_regionlist
+	},
+#endif
+#ifdef CONFIG_NE2K_CBUS_CNET98EL
+	{
+		NE2K_CBUS_HARDWARE_TYPE_CNET98EL,
+		"C-NET(98)E/L",
+#ifndef MODULE
+		cnet98el_portlist,
+#endif
+		&cnet98el_offsetinfo, cnet98el_regionlist
+	},
+#endif
+/* NOTE: LGY98 must be probed before EGY98, or system stalled!? */
+#ifdef CONFIG_NE2K_CBUS_LGY98
+	{
+		NE2K_CBUS_HARDWARE_TYPE_LGY98,
+		"LGY-98",
+#ifndef MODULE
+		lgy98_portlist,
+#endif
+		&lgy98_offsetinfo, lgy98_regionlist
+	},
+#endif
+#ifdef CONFIG_NE2K_CBUS_EGY98
+	{
+		NE2K_CBUS_HARDWARE_TYPE_EGY98,
+		"EGY-98",
+#ifndef MODULE
+		egy98_portlist,
+#endif
+		&egy98_offsetinfo, egy98_regionlist
+	},
+#endif
+	{
+		0,
+		"unsupported hardware",
+#ifndef MODULE
+		NULL,
+#endif
+		NULL, NULL
+	}
+};
+
+static int __init ne2k_cbus_init(struct net_device *dev)
+{
+	struct ei_device *ei_local;
+	if (dev->priv == NULL) {
+		ei_local = kmalloc(sizeof(struct ei_device), GFP_KERNEL);
+		if (ei_local == NULL)
+			return -ENOMEM;
+		memset(ei_local, 0, sizeof(struct ei_device));
+		ei_local->reg_offset = kmalloc(sizeof(typeof(*ei_local->reg_offset))*18, GFP_KERNEL);
+		if (ei_local->reg_offset == NULL) {
+			kfree(ei_local);
+			return -ENOMEM;
+		}
+		spin_lock_init(&ei_local->page_lock);
+		dev->priv = ei_local;
+	}
+	return 0;
+}
+
+static void ne2k_cbus_destroy(struct net_device *dev)
+{
+	struct ei_device *ei_local = (struct ei_device *)(dev->priv);
+	if (ei_local != NULL) {
+		if (ei_local->reg_offset)
+			kfree(ei_local->reg_offset);
+		kfree(dev->priv);
+		dev->priv = NULL;
+	}
+}
+
+static const struct ne2k_cbus_hwinfo * __init ne2k_cbus_get_hwinfo(int hwtype)
+{
+	const struct ne2k_cbus_hwinfo *hw;
+
+	for (hw = &ne2k_cbus_hwinfo_list[0]; hw->hwtype; hw++) {
+		if (hw->hwtype == hwtype) break;
+	}
+	return hw;
+}
+
+static void __init ne2k_cbus_set_hwtype(struct net_device *dev, const struct ne2k_cbus_hwinfo *hw, int ioaddr)
+{
+	struct ei_device *ei_local = (struct ei_device *)(dev->priv);
+	int i;
+	int hwtype_old = dev->mem_start & NE2K_CBUS_HARDWARE_TYPE_MASK;
+
+	if (!ei_local)
+		panic("Gieee! ei_local == NULL!! (from %p)",
+		       __builtin_return_address(0));
+
+	dev->mem_start &= ~NE2K_CBUS_HARDWARE_TYPE_MASK;
+	dev->mem_start |= hw->hwtype & NE2K_CBUS_HARDWARE_TYPE_MASK;
+
+	if (ei_debug > 2) {
+		printk(KERN_DEBUG "hwtype changed: %d -> %d\n",hwtype_old,(int)(dev->mem_start & NE2K_CBUS_HARDWARE_TYPE_MASK));
+	}
+
+	if (hw->offsetinfo) {
+		for (i = 0; i < 8; i++) {
+			ei_local->reg_offset[i] = hw->offsetinfo->skip * i;
+		}
+		for (i = 8; i < 16; i++) {
+			ei_local->reg_offset[i] =
+				hw->offsetinfo->skip*(i-8) + hw->offsetinfo->offset8;
+		}
+#ifdef CONFIG_NE2K_CBUS_NEC108
+		if (hw->hwtype == NE2K_CBUS_HARDWARE_TYPE_NEC108) {
+			int adj = (ioaddr & 0xf000) /2;
+			ei_local->reg_offset[16] = 
+				(hw->offsetinfo->offset10 | adj) - ioaddr;
+			ei_local->reg_offset[17] = 
+				(hw->offsetinfo->offset1f | adj) - ioaddr;
+		} else {
+#endif /* CONFIG_NE2K_CBUS_NEC108 */
+			ei_local->reg_offset[16] = hw->offsetinfo->offset10;
+			ei_local->reg_offset[17] = hw->offsetinfo->offset1f;
+#ifdef CONFIG_NE2K_CBUS_NEC108
+		}
+#endif
+	} else {
+		/* make dummmy offset list */
+		for (i = 0; i < 16; i++) {
+			ei_local->reg_offset[i] = i;
+		}
+		ei_local->reg_offset[16] = 0x10;
+		ei_local->reg_offset[17] = 0x1f;
+	}
+}
+
+#if defined(CONFIG_NE2K_CBUS_ICM) || defined(CONFIG_NE2K_CBUS_CNET98EL)
+static void __init ne2k_cbus_readmem(struct net_device *dev, int ioaddr, unsigned short memaddr, char *buf, unsigned short len)
+{
+	struct ei_device *ei_local = (struct ei_device *)(dev->priv);
+	outb_p(E8390_NODMA | E8390_START, ioaddr+E8390_CMD);
+	outb_p(len & 0xff, ioaddr+EN0_RCNTLO);
+	outb_p(len >> 8, ioaddr+EN0_RCNTHI);
+	outb_p(memaddr & 0xff, ioaddr+EN0_RSARLO);
+	outb_p(memaddr >> 8, ioaddr+EN0_RSARHI);
+	outb_p(E8390_RREAD | E8390_START, ioaddr+E8390_CMD);
+	insw(ioaddr+NE_DATAPORT, buf, len >> 1);
+}
+static void __init ne2k_cbus_writemem(struct net_device *dev, int ioaddr, unsigned short memaddr, const char *buf, unsigned short len)
+{
+	struct ei_device *ei_local = (struct ei_device *)(dev->priv);
+	outb_p(E8390_NODMA | E8390_START, ioaddr+E8390_CMD);
+	outb_p(ENISR_RDC, ioaddr+EN0_ISR);
+	outb_p(len & 0xff, ioaddr+EN0_RCNTLO);
+	outb_p(len >> 8, ioaddr+EN0_RCNTHI);
+	outb_p(memaddr & 0xff, ioaddr+EN0_RSARLO);
+	outb_p(memaddr >> 8, ioaddr+EN0_RSARHI);
+	outb_p(E8390_RWRITE | E8390_START, ioaddr+E8390_CMD);
+	outsw(ioaddr+NE_DATAPORT, buf, len >> 1);
+}
+#endif
+
+static int ne_probe_cbus(struct net_device *dev, const struct ne2k_cbus_hwinfo *hw, int ioaddr);
+/* End of ne2k_cbus.h */

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH] PC-9800 additional for 2.5.61-ac1 (11/21) parport
  2003-02-20 12:16 [PATCH] PC-9800 additional for 2.5.61-ac1 (0/21) summary Osamu Tomita
                   ` (9 preceding siblings ...)
  2003-02-20 12:31 ` [PATCH] PC-9800 additional for 2.5.61-ac1 (10/21) network card Osamu Tomita
@ 2003-02-20 12:32 ` Osamu Tomita
  2003-02-20 12:33 ` [PATCH] PC-9800 additional for 2.5.61-ac1 (12/21) PCI Osamu Tomita
                   ` (8 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Osamu Tomita @ 2003-02-20 12:32 UTC (permalink / raw)
  To: Linux Kernel Mailing List; +Cc: Alan Cox

This is additional patch to support NEC PC-9800 subarchitecture
against 2.5.61-ac1. (11/21)

Parallel port support.

diff -Nru linux/drivers/parport/parport_pc.c linux98/drivers/parport/parport_pc.c
--- linux/drivers/parport/parport_pc.c	2002-12-16 11:08:22.000000000 +0900
+++ linux98/drivers/parport/parport_pc.c	2002-12-22 20:51:23.000000000 +0900
@@ -332,7 +332,10 @@
 
 unsigned char parport_pc_read_status(struct parport *p)
 {
-	return inb (STATUS (p));
+	if (pc98 && p->base == 0x40)
+		return ((inb(0x42) & 0x04) << 5) | PARPORT_STATUS_ERROR;
+	else
+		return inb (STATUS (p));
 }
 
 void parport_pc_disable_irq(struct parport *p)
@@ -1644,6 +1647,8 @@
 {
 	unsigned char r, w;
 
+	if (pc98 && pb->base == 0x40)
+		return PARPORT_MODE_PCSPP;
 	/*
 	 * first clear an eventually pending EPP timeout 
 	 * I (sailer@ife.ee.ethz.ch) have an SMSC chipset
@@ -1777,6 +1782,9 @@
 {
 	int ok = 0;
   
+	if (pc98 && pb->base == 0x40)
+		return 0;  /* never support */
+
 	clear_epp_timeout(pb);
 
 	/* try to tri-state the buffer */
@@ -1908,6 +1916,9 @@
 			config & 0x80 ? "Level" : "Pulses");
 
 		configb = inb (CONFIGB (pb));
+		if (pc98 && (CONFIGB(pb) == 0x14d) && ((configb & 0x38) == 0x30))
+			configb = (configb & ~0x38) | 0x28; /* IRQ 14 */
+
 		printk (KERN_DEBUG "0x%lx: ECP port cfgA=0x%02x cfgB=0x%02x\n",
 			pb->base, config, configb);
 		printk (KERN_DEBUG "0x%lx: ECP settings irq=", pb->base);
@@ -2048,6 +2059,9 @@
 	ECR_WRITE (pb, ECR_CNF << 5); /* Configuration MODE */
 
 	intrLine = (inb (CONFIGB (pb)) >> 3) & 0x07;
+	if (pc98 && (CONFIGB(pb) == 0x14d) && (intrLine == 6))
+		intrLine = 5; /* IRQ 14 */
+
 	irq = lookup[intrLine];
 
 	ECR_WRITE (pb, oecr);
@@ -2212,7 +2226,14 @@
 	struct parport tmp;
 	struct parport *p = &tmp;
 	int probedirq = PARPORT_IRQ_NONE;
-	if (check_region(base, 3)) return NULL;
+	if (pc98 && base == 0x40) {
+		int i;
+		for (i = 0; i < 8; i += 2)
+			if (check_region(base + i, 1)) return NULL;
+	} else {
+		if (check_region(base, 3)) return NULL;
+	}
+
 	priv = kmalloc (sizeof (struct parport_pc_private), GFP_KERNEL);
 	if (!priv) {
 		printk (KERN_DEBUG "parport (0x%lx): no memory!\n", base);
@@ -2245,7 +2266,7 @@
 	if (base_hi && !check_region(base_hi,3))
 		parport_ECR_present(p);
 
-	if (base != 0x3bc) {
+	if (!pc98 && base != 0x3bc) {
 		if (!check_region(base+0x3, 5)) {
 			if (!parport_EPP_supported(p))
 				parport_ECPEPP_supported(p);
@@ -2343,7 +2364,12 @@
 		printk(KERN_INFO "%s: irq %d detected\n", p->name, probedirq);
 	parport_proc_register(p);
 
-	request_region (p->base, 3, p->name);
+	if (pc98 && p->base == 0x40) {
+		int i;
+		for (i = 0; i < 8; i += 2)
+			request_region(p->base + i, 1, p->name);
+	} else
+		request_region (p->base, 3, p->name);
 	if (p->size > 3)
 		request_region (p->base + 3, p->size - 3, p->name);
 	if (p->modes & PARPORT_MODE_ECP)
@@ -2413,7 +2439,13 @@
 		free_dma(p->dma);
 	if (p->irq != PARPORT_IRQ_NONE)
 		free_irq(p->irq, p);
-	release_region(p->base, 3);
+	if (pc98 && p->base == 0x40) {
+		int i;
+		for (i = 0; i < 8; i += 2)
+			release_region(p->base + i, 1);
+	} else
+		release_region(p->base, 3);
+
 	if (p->size > 3)
 		release_region(p->base + 3, p->size - 3);
 	if (p->modes & PARPORT_MODE_ECP)
@@ -2996,6 +3028,30 @@
 {
 	int count = 0;
 
+	if (pc98) {
+		/* Set default resource settings for old style parport */
+		int	base = 0x40;
+		int	base_hi = 0;
+		int	irq = PARPORT_IRQ_NONE;
+		int	dma = PARPORT_DMA_NONE;
+
+		/* Check PC9800 old style parport */
+		outb(inb(0x149) & ~0x10, 0x149); /* disable IEEE1284 */
+		if (!(inb(0x149) & 0x10)) {  /* IEEE1284 disabled ? */
+			outb(inb(0x149) | 0x10, 0x149); /* enable IEEE1284 */
+			if (inb(0x149) & 0x10) {  /* IEEE1284 enabled ? */
+				/* Set default settings for IEEE1284 parport */
+				base = 0x140;
+				base_hi = 0x14c;
+				irq = 14;
+				/* dma = PARPORT_DMA_NONE; */
+			}
+		}
+
+		if (parport_pc_probe_port(base, base_hi, irq, dma, NULL))
+			count++;
+	}
+
 	if (parport_pc_probe_port(0x3bc, 0x7bc, autoirq, autodma, NULL))
 		count++;
 	if (parport_pc_probe_port(0x378, 0x778, autoirq, autodma, NULL))
diff -Nru linux/include/linux/parport_pc.h linux98/include/linux/parport_pc.h
--- linux/include/linux/parport_pc.h	2002-06-12 11:15:27.000000000 +0900
+++ linux98/include/linux/parport_pc.h	2002-08-19 14:13:09.000000000 +0900
@@ -119,6 +119,11 @@
 #endif
 	ctr = (ctr & ~mask) ^ val;
 	ctr &= priv->ctr_writable; /* only write writable bits. */
+#ifdef CONFIG_X86_PC9800
+	if (p->base == 0x40 && ((priv->ctr) ^ ctr) & 0x01)
+		outb(0x0e | ((ctr & 0x01) ^ 0x01), 0x46);
+	else
+#endif /* CONFIG_X86_PC9800 */
 	outb (ctr, CONTROL (p));
 	priv->ctr = ctr;	/* Update soft copy */
 	return ctr;
@@ -191,6 +196,11 @@
 
 extern __inline__ unsigned char parport_pc_read_status(struct parport *p)
 {
+#ifdef CONFIG_X86_PC9800
+	if (p->base == 0x40)
+		return ((inb(0x42) & 0x04) << 5) | PARPORT_STATUS_ERROR;
+	else
+#endif /* CONFIG_X86_PC9800 */
 	return inb(STATUS(p));
 }
 

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH] PC-9800 additional for 2.5.61-ac1 (12/21) PCI
  2003-02-20 12:16 [PATCH] PC-9800 additional for 2.5.61-ac1 (0/21) summary Osamu Tomita
                   ` (10 preceding siblings ...)
  2003-02-20 12:32 ` [PATCH] PC-9800 additional for 2.5.61-ac1 (11/21) parport Osamu Tomita
@ 2003-02-20 12:33 ` Osamu Tomita
  2003-02-20 12:34 ` [PATCH] PC-9800 additional for 2.5.61-ac1 (13/21) PCMCIA Osamu Tomita
                   ` (7 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Osamu Tomita @ 2003-02-20 12:33 UTC (permalink / raw)
  To: Linux Kernel Mailing List; +Cc: Alan Cox

This is additional patch to support NEC PC-9800 subarchitecture
against 2.5.61-ac1. (12/21)

Small changes for PCI support.
Fix for difference of IRQ numbers and IO addresses.

diff -Nru linux/arch/i386/pci/irq.c linux98/arch/i386/pci/irq.c
--- linux/arch/i386/pci/irq.c	2002-10-12 13:22:46.000000000 +0900
+++ linux98/arch/i386/pci/irq.c	2002-10-12 14:18:52.000000000 +0900
@@ -5,6 +5,7 @@
  */
 
 #include <linux/config.h>
+#include <linux/pci_ids.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
@@ -25,6 +26,7 @@
 
 static struct irq_routing_table *pirq_table;
 
+#ifndef CONFIG_X86_PC9800
 /*
  * Never use: 0, 1, 2 (timer, keyboard, and cascade)
  * Avoid using: 13, 14 and 15 (FP error and IDE).
@@ -36,6 +38,20 @@
 	1000000, 1000000, 1000000, 1000, 1000, 0, 1000, 1000,
 	0, 0, 0, 0, 1000, 100000, 100000, 100000
 };
+#else
+/*
+ * Never use: 0, 1, 2, 7 (timer, keyboard, CRT VSYNC and cascade)
+ * Avoid using: 8, 9 and 15 (FP error and IDE).
+ * Penalize: 4, 5, 11, 12, 13, 14 (known ISA uses: serial, floppy, sound, mouse
+ *                                 and parallel)
+ */
+unsigned int pcibios_irq_mask = 0xff78;
+
+static int pirq_penalty[16] = {
+	1000000, 1000000, 1000000, 0, 1000, 1000, 0, 1000000,
+	100000, 100000, 0, 1000, 1000, 1000, 1000, 100000
+};
+#endif
 
 struct irq_router {
 	char *name;
@@ -612,6 +628,17 @@
 		r->set(pirq_router_dev, dev, pirq, 11);
 	}
 
+#ifdef CONFIG_X86_PC9800
+	if ((dev->class >> 8) == PCI_CLASS_BRIDGE_CARDBUS) {
+		if (pci_find_device(PCI_VENDOR_ID_INTEL,
+				PCI_DEVICE_ID_INTEL_82439TX, NULL) != NULL) {
+			if (mask & 0x0040) {
+				mask &= 0x0040;	/* assign IRQ 6 only */
+				printk("pci-irq: Use IRQ6 for CardBus controller\n");
+			}
+		}
+	}
+#endif
 	/*
 	 * Find the best IRQ to assign: use the one
 	 * reported by the device if possible.
diff -Nru linux/drivers/pcmcia/yenta.c linux98/drivers/pcmcia/yenta.c
--- linux/drivers/pcmcia/yenta.c	2002-11-18 13:29:48.000000000 +0900
+++ linux98/drivers/pcmcia/yenta.c	2002-11-19 11:02:09.000000000 +0900
@@ -8,6 +8,7 @@
  * 	Dynamically adjust the size of the bridge resource
  * 	
  */
+#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/pci.h>
 #include <linux/sched.h>
@@ -510,6 +511,7 @@
 	add_timer(&socket->poll_timer);
 }
 
+#ifndef CONFIG_X86_PC9800
 /*
  * Only probe "regular" interrupts, don't
  * touch dangerous spots like the mouse irq,
@@ -520,6 +522,10 @@
  * Default to 11, 10, 9, 7, 6, 5, 4, 3.
  */
 static u32 isa_interrupts = 0x0ef8;
+#else
+/* Default to 12, 10, 6, 5, 3. */
+static u32 isa_interrupts = 0x1468;
+#endif
 
 static unsigned int yenta_probe_irq(pci_socket_t *socket, u32 isa_irq_mask)
 {
diff -Nru linux/include/asm-i386/pci.h linux98/include/asm-i386/pci.h
--- linux/include/asm-i386/pci.h	2002-06-09 14:29:24.000000000 +0900
+++ linux98/include/asm-i386/pci.h	2002-06-10 20:49:15.000000000 +0900
@@ -17,7 +17,11 @@
 #endif
 
 extern unsigned long pci_mem_start;
+#ifdef CONFIG_X86_PC9800
+#define PCIBIOS_MIN_IO		0x4000
+#else
 #define PCIBIOS_MIN_IO		0x1000
+#endif
 #define PCIBIOS_MIN_MEM		(pci_mem_start)
 
 void pcibios_config_init(void);

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH] PC-9800 additional for 2.5.61-ac1 (13/21) PCMCIA
  2003-02-20 12:16 [PATCH] PC-9800 additional for 2.5.61-ac1 (0/21) summary Osamu Tomita
                   ` (11 preceding siblings ...)
  2003-02-20 12:33 ` [PATCH] PC-9800 additional for 2.5.61-ac1 (12/21) PCI Osamu Tomita
@ 2003-02-20 12:34 ` Osamu Tomita
  2003-02-20 12:34 ` [PATCH] PC-9800 additional for 2.5.61-ac1 (14/21) PNP Osamu Tomita
                   ` (6 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Osamu Tomita @ 2003-02-20 12:34 UTC (permalink / raw)
  To: Linux Kernel Mailing List; +Cc: Alan Cox

This is additional patch to support NEC PC-9800 subarchitecture
against 2.5.61-ac1. (13/21)

Small change for PCMCIA (16bits) support.
For fix usable IRQ number.

diff -Nru linux-2.5.50-ac1/drivers/pcmcia/i82365.c linux98-2.5.50-ac1/drivers/pcmcia/i82365.c
--- linux-2.5.50-ac1/drivers/pcmcia/i82365.c	2002-11-28 07:36:18.000000000 +0900
+++ linux98-2.5.50-ac1/drivers/pcmcia/i82365.c	2002-12-12 16:40:13.000000000 +0900
@@ -187,7 +187,11 @@
 };
 
 /* Default ISA interrupt mask */
+#ifndef CONFIG_X86_PC9800
 #define I365_MASK	0xdeb8	/* irq 15,14,12,11,10,9,7,5,4,3 */
+#else
+#define I365_MASK	0xd668	/* irq 15,14,12,10,9,6,5,3 */
+#endif
 
 #ifdef CONFIG_ISA
 static int grab_irq;

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH] PC-9800 additional for 2.5.61-ac1 (14/21) PNP
  2003-02-20 12:16 [PATCH] PC-9800 additional for 2.5.61-ac1 (0/21) summary Osamu Tomita
                   ` (12 preceding siblings ...)
  2003-02-20 12:34 ` [PATCH] PC-9800 additional for 2.5.61-ac1 (13/21) PCMCIA Osamu Tomita
@ 2003-02-20 12:34 ` Osamu Tomita
  2003-02-20 12:35 ` [PATCH] PC-9800 additional for 2.5.61-ac1 (15/21) RTC Osamu Tomita
                   ` (5 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Osamu Tomita @ 2003-02-20 12:34 UTC (permalink / raw)
  To: Linux Kernel Mailing List; +Cc: Alan Cox

This is additional patch to support NEC PC-9800 subarchitecture
against 2.5.61-ac1. (14/21)

Small change for Legacy bus PNP support.
For fix IO port address.

diff -Nru linux/drivers/pnp/isapnp/core.c linux98/drivers/pnp/isapnp/core.c
--- linux/drivers/pnp/isapnp/core.c	2003-01-02 12:22:18.000000000 +0900
+++ linux98/drivers/pnp/isapnp/core.c	2003-01-04 16:40:40.000000000 +0900
@@ -72,8 +72,13 @@
 MODULE_PARM_DESC(isapnp_verbose, "ISA Plug & Play verbose mode");
 MODULE_LICENSE("GPL");
 
+#ifdef CONFIG_X86_PC9800
+#define _PIDXR		0x259
+#define _PNPWRP		0xa59
+#else
 #define _PIDXR		0x279
 #define _PNPWRP		0xa79
+#endif
 
 /* short tags */
 #define _STAG_PNPVERNO		0x01

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH] PC-9800 additional for 2.5.61-ac1 (15/21) RTC
  2003-02-20 12:16 [PATCH] PC-9800 additional for 2.5.61-ac1 (0/21) summary Osamu Tomita
                   ` (13 preceding siblings ...)
  2003-02-20 12:34 ` [PATCH] PC-9800 additional for 2.5.61-ac1 (14/21) PNP Osamu Tomita
@ 2003-02-20 12:35 ` Osamu Tomita
  2003-02-20 12:36 ` [PATCH] PC-9800 additional for 2.5.61-ac1 (17/21) serial Osamu Tomita
                   ` (4 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Osamu Tomita @ 2003-02-20 12:35 UTC (permalink / raw)
  To: Linux Kernel Mailing List; +Cc: Alan Cox

This is additional patch to support NEC PC-9800 subarchitecture
against 2.5.61-ac1. (15/21)

Support RTC for PC98, using mach-* scheme.

diff -Nru linux-2.5.60/arch/i386/kernel/time.c linux98-2.5.60/arch/i386/kernel/time.c
--- linux-2.5.60/arch/i386/kernel/time.c	2003-02-11 03:38:37.000000000 +0900
+++ linux98-2.5.60/arch/i386/kernel/time.c	2003-02-11 10:52:52.000000000 +0900
@@ -55,12 +55,15 @@
 #include <asm/processor.h>
 #include <asm/timer.h>
 
-#include <linux/mc146818rtc.h>
+#include "mach_time.h"
+
 #include <linux/timex.h>
 #include <linux/config.h>
 
 #include <asm/arch_hooks.h>
 
+#include "io_ports.h"
+
 extern spinlock_t i8259A_lock;
 int pit_latch_buggy;              /* extern */
 
@@ -137,69 +140,13 @@
 	write_sequnlock_irq(&xtime_lock);
 }
 
-/*
- * In order to set the CMOS clock precisely, set_rtc_mmss has to be
- * called 500 ms after the second nowtime has started, because when
- * nowtime is written into the registers of the CMOS clock, it will
- * jump to the next second precisely 500 ms later. Check the Motorola
- * MC146818A or Dallas DS12887 data sheet for details.
- *
- * BUG: This routine does not handle hour overflow properly; it just
- *      sets the minutes. Usually you'll only notice that after reboot!
- */
 static int set_rtc_mmss(unsigned long nowtime)
 {
-	int retval = 0;
-	int real_seconds, real_minutes, cmos_minutes;
-	unsigned char save_control, save_freq_select;
+	int retval;
 
 	/* gets recalled with irq locally disabled */
 	spin_lock(&rtc_lock);
-	save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */
-	CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
-
-	save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset prescaler */
-	CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
-
-	cmos_minutes = CMOS_READ(RTC_MINUTES);
-	if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
-		BCD_TO_BIN(cmos_minutes);
-
-	/*
-	 * since we're only adjusting minutes and seconds,
-	 * don't interfere with hour overflow. This avoids
-	 * messing with unknown time zones but requires your
-	 * RTC not to be off by more than 15 minutes
-	 */
-	real_seconds = nowtime % 60;
-	real_minutes = nowtime / 60;
-	if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1)
-		real_minutes += 30;		/* correct for half hour time zone */
-	real_minutes %= 60;
-
-	if (abs(real_minutes - cmos_minutes) < 30) {
-		if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
-			BIN_TO_BCD(real_seconds);
-			BIN_TO_BCD(real_minutes);
-		}
-		CMOS_WRITE(real_seconds,RTC_SECONDS);
-		CMOS_WRITE(real_minutes,RTC_MINUTES);
-	} else {
-		printk(KERN_WARNING
-		       "set_rtc_mmss: can't update from %d to %d\n",
-		       cmos_minutes, real_minutes);
-		retval = -1;
-	}
-
-	/* The following flags have to be released exactly in this order,
-	 * otherwise the DS12887 (popular MC146818A clone with integrated
-	 * battery and quartz) will not reset the oscillator and will not
-	 * update precisely 500 ms later. You won't find this mentioned in
-	 * the Dallas Semiconductor data sheets, but who believes data
-	 * sheets anyway ...                           -- Markus Kuhn
-	 */
-	CMOS_WRITE(save_control, RTC_CONTROL);
-	CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
+	retval = mach_set_rtc_mmss(nowtime);
 	spin_unlock(&rtc_lock);
 
 	return retval;
@@ -225,9 +172,9 @@
 		 * on an 82489DX-based system.
 		 */
 		spin_lock(&i8259A_lock);
-		outb(0x0c, 0x20);
+		outb(0x0c, PIC_MASTER_OCW3);
 		/* Ack the IRQ; AEOI will end it automatically. */
-		inb(0x20);
+		inb(PIC_MASTER_POLL);
 		spin_unlock(&i8259A_lock);
 	}
 #endif
@@ -241,14 +188,14 @@
 	 */
 	if ((time_status & STA_UNSYNC) == 0 &&
 	    xtime.tv_sec > last_rtc_update + 660 &&
-	    (xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 &&
-	    (xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2) {
+	    (xtime.tv_nsec / 1000) >= TIME1 - ((unsigned) TICK_SIZE) / 2 &&
+	    (xtime.tv_nsec / 1000) <= TIME2 + ((unsigned) TICK_SIZE) / 2) {
 		if (set_rtc_mmss(xtime.tv_sec) == 0)
 			last_rtc_update = xtime.tv_sec;
 		else
 			last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
 	}
-	    
+
 #ifdef CONFIG_MCA
 	if( MCA_bus ) {
 		/* The PS/2 uses level-triggered interrupts.  You can't
@@ -329,43 +276,15 @@
 /* not static: needed by APM */
 unsigned long get_cmos_time(void)
 {
-	unsigned int year, mon, day, hour, min, sec;
-	int i;
+	unsigned long retval;
 
 	spin_lock(&rtc_lock);
-	/* The Linux interpretation of the CMOS clock register contents:
-	 * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
-	 * RTC registers show the second which has precisely just started.
-	 * Let's hope other operating systems interpret the RTC the same way.
-	 */
-	/* read RTC exactly on falling edge of update flag */
-	for (i = 0 ; i < 1000000 ; i++)	/* may take up to 1 second... */
-		if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)
-			break;
-	for (i = 0 ; i < 1000000 ; i++)	/* must try at least 2.228 ms */
-		if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP))
-			break;
-	do { /* Isn't this overkill ? UIP above should guarantee consistency */
-		sec = CMOS_READ(RTC_SECONDS);
-		min = CMOS_READ(RTC_MINUTES);
-		hour = CMOS_READ(RTC_HOURS);
-		day = CMOS_READ(RTC_DAY_OF_MONTH);
-		mon = CMOS_READ(RTC_MONTH);
-		year = CMOS_READ(RTC_YEAR);
-	} while (sec != CMOS_READ(RTC_SECONDS));
-	if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
-	  {
-	    BCD_TO_BIN(sec);
-	    BCD_TO_BIN(min);
-	    BCD_TO_BIN(hour);
-	    BCD_TO_BIN(day);
-	    BCD_TO_BIN(mon);
-	    BCD_TO_BIN(year);
-	  }
+
+	retval = mach_get_cmos_time();
+
 	spin_unlock(&rtc_lock);
-	if ((year += 1900) < 1970)
-		year += 100;
-	return mktime(year, mon, day, hour, min, sec);
+
+	return retval;
 }
 
 /* XXX this driverfs stuff should probably go elsewhere later -john */
diff -Nru linux/include/asm-i386/mach-default/mach_time.h linux98/include/asm-i386/mach-default/mach_time.h
--- linux/include/asm-i386/mach-default/mach_time.h	1970-01-01 09:00:00.000000000 +0900
+++ linux98/include/asm-i386/mach-default/mach_time.h	2002-10-21 10:07:35.000000000 +0900
@@ -0,0 +1,122 @@
+/*
+ *  include/asm-i386/mach-default/mach_time.h
+ *
+ *  Machine specific set RTC function for generic.
+ *  Split out from time.c by Osamu Tomita <tomita@cinet.co.jp>
+ */
+#ifndef _MACH_TIME_H
+#define _MACH_TIME_H
+
+#include <linux/mc146818rtc.h>
+
+/* for check timing call set_rtc_mmss() 500ms     */
+/* used in arch/i386/time.c::do_timer_interrupt() */
+#define TIME1	500000
+#define TIME2	500000
+
+/*
+ * In order to set the CMOS clock precisely, set_rtc_mmss has to be
+ * called 500 ms after the second nowtime has started, because when
+ * nowtime is written into the registers of the CMOS clock, it will
+ * jump to the next second precisely 500 ms later. Check the Motorola
+ * MC146818A or Dallas DS12887 data sheet for details.
+ *
+ * BUG: This routine does not handle hour overflow properly; it just
+ *      sets the minutes. Usually you'll only notice that after reboot!
+ */
+static inline int mach_set_rtc_mmss(unsigned long nowtime)
+{
+	int retval = 0;
+	int real_seconds, real_minutes, cmos_minutes;
+	unsigned char save_control, save_freq_select;
+
+	save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */
+	CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
+
+	save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset prescaler */
+	CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
+
+	cmos_minutes = CMOS_READ(RTC_MINUTES);
+	if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
+		BCD_TO_BIN(cmos_minutes);
+
+	/*
+	 * since we're only adjusting minutes and seconds,
+	 * don't interfere with hour overflow. This avoids
+	 * messing with unknown time zones but requires your
+	 * RTC not to be off by more than 15 minutes
+	 */
+	real_seconds = nowtime % 60;
+	real_minutes = nowtime / 60;
+	if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1)
+		real_minutes += 30;		/* correct for half hour time zone */
+	real_minutes %= 60;
+
+	if (abs(real_minutes - cmos_minutes) < 30) {
+		if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
+			BIN_TO_BCD(real_seconds);
+			BIN_TO_BCD(real_minutes);
+		}
+		CMOS_WRITE(real_seconds,RTC_SECONDS);
+		CMOS_WRITE(real_minutes,RTC_MINUTES);
+	} else {
+		printk(KERN_WARNING
+		       "set_rtc_mmss: can't update from %d to %d\n",
+		       cmos_minutes, real_minutes);
+		retval = -1;
+	}
+
+	/* The following flags have to be released exactly in this order,
+	 * otherwise the DS12887 (popular MC146818A clone with integrated
+	 * battery and quartz) will not reset the oscillator and will not
+	 * update precisely 500 ms later. You won't find this mentioned in
+	 * the Dallas Semiconductor data sheets, but who believes data
+	 * sheets anyway ...                           -- Markus Kuhn
+	 */
+	CMOS_WRITE(save_control, RTC_CONTROL);
+	CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
+
+	return retval;
+}
+
+static inline unsigned long mach_get_cmos_time(void)
+{
+	unsigned int year, mon, day, hour, min, sec;
+	int i;
+
+	/* The Linux interpretation of the CMOS clock register contents:
+	 * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
+	 * RTC registers show the second which has precisely just started.
+	 * Let's hope other operating systems interpret the RTC the same way.
+	 */
+	/* read RTC exactly on falling edge of update flag */
+	for (i = 0 ; i < 1000000 ; i++)	/* may take up to 1 second... */
+		if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)
+			break;
+	for (i = 0 ; i < 1000000 ; i++)	/* must try at least 2.228 ms */
+		if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP))
+			break;
+	do { /* Isn't this overkill ? UIP above should guarantee consistency */
+		sec = CMOS_READ(RTC_SECONDS);
+		min = CMOS_READ(RTC_MINUTES);
+		hour = CMOS_READ(RTC_HOURS);
+		day = CMOS_READ(RTC_DAY_OF_MONTH);
+		mon = CMOS_READ(RTC_MONTH);
+		year = CMOS_READ(RTC_YEAR);
+	} while (sec != CMOS_READ(RTC_SECONDS));
+	if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
+	  {
+	    BCD_TO_BIN(sec);
+	    BCD_TO_BIN(min);
+	    BCD_TO_BIN(hour);
+	    BCD_TO_BIN(day);
+	    BCD_TO_BIN(mon);
+	    BCD_TO_BIN(year);
+	  }
+	if ((year += 1900) < 1970)
+		year += 100;
+
+	return mktime(year, mon, day, hour, min, sec);
+}
+
+#endif /* !_MACH_TIME_H */
diff -Nru linux/include/asm-i386/mach-pc9800/mach_time.h linux98/include/asm-i386/mach-pc9800/mach_time.h
--- linux/include/asm-i386/mach-pc9800/mach_time.h	1970-01-01 09:00:00.000000000 +0900
+++ linux98/include/asm-i386/mach-pc9800/mach_time.h	2002-10-21 11:23:06.000000000 +0900
@@ -0,0 +1,136 @@
+/*
+ *  include/asm-i386/mach-pc9800/mach_time.h
+ *
+ *  Machine specific set RTC function for PC-9800.
+ *  Written by Osamu Tomita <tomita@cinet.co.jp>
+ */
+#ifndef _MACH_TIME_H
+#define _MACH_TIME_H
+
+#include <linux/upd4990a.h>
+
+/* for check timing call set_rtc_mmss() */
+/* used in arch/i386/time.c::do_timer_interrupt() */
+/*
+ * Because PC-9800's RTC (NEC uPD4990A) does not allow setting
+ * time partially, we always have to read-modify-write the
+ * entire time (including year) so that set_rtc_mmss() will
+ * take quite much time to execute.  You may want to relax
+ * RTC resetting interval (currently ~11 minuts)...
+ */
+#define TIME1	1000000
+#define TIME2	0
+
+static inline int mach_set_rtc_mmss(unsigned long nowtime)
+{
+	int retval = 0;
+	int real_seconds, real_minutes, cmos_minutes;
+	struct upd4990a_raw_data data;
+
+	upd4990a_get_time(&data, 1);
+	cmos_minutes = (data.min >> 4) * 10 + (data.min & 0xf);
+
+	/*
+	 * since we're only adjusting minutes and seconds,
+	 * don't interfere with hour overflow. This avoids
+	 * messing with unknown time zones but requires your
+	 * RTC not to be off by more than 15 minutes
+	 */
+	real_seconds = nowtime % 60;
+	real_minutes = nowtime / 60;
+	if (((abs(real_minutes - cmos_minutes) + 15) / 30) & 1)
+		real_minutes += 30;	/* correct for half hour time zone */
+	real_minutes %= 60;
+
+	if (abs(real_minutes - cmos_minutes) < 30) {
+		u8 temp_seconds = (real_seconds / 10) * 16 + real_seconds % 10;
+		u8 temp_minutes = (real_minutes / 10) * 16 + real_minutes % 10;
+
+		if (data.sec != temp_seconds || data.min != temp_minutes) {
+			data.sec = temp_seconds;
+			data.min = temp_minutes;
+			upd4990a_set_time(&data, 1);
+		}
+	} else {
+		printk(KERN_WARNING
+		       "set_rtc_mmss: can't update from %d to %d\n",
+		       cmos_minutes, real_minutes);
+		retval = -1;
+	}
+
+	/* uPD4990A users' manual says we should issue Register Hold
+	 * command after reading time, or future Time Read command
+	 * may not work.  When we have set the time, this also starts
+	 * the clock.
+	 */
+	upd4990a_serial_command(UPD4990A_REGISTER_HOLD);
+
+	return retval;
+}
+
+#define RTC_SANITY_CHECK
+
+static inline unsigned long mach_get_cmos_time(void)
+{
+	int i;
+	u8 prev, cur;
+	unsigned int year;
+#ifdef RTC_SANITY_CHECK
+	int retry_count;
+#endif
+
+	struct upd4990a_raw_data data;
+
+#ifdef RTC_SANITY_CHECK
+	retry_count = 0;
+ retry:
+#endif
+	/* Connect uPD4990A's DATA OUT pin to its 1Hz reference clock. */
+	upd4990a_serial_command(UPD4990A_REGISTER_HOLD);
+
+	/* Catch rising edge of reference clock.  */
+	prev = ~UPD4990A_READ_DATA();
+	for (i = 0; i < 1800000; i++) { /* may take up to 1 second... */
+		__asm__ ("outb %%al,%0" : : "N" (0x5f)); /* 0.6usec delay */
+		cur = UPD4990A_READ_DATA();
+		if (!(prev & cur & 1))
+			break;
+		prev = ~cur;
+	}
+
+	upd4990a_get_time(&data, 0);
+
+#ifdef RTC_SANITY_CHECK
+# define BCD_VALID_P(x, hi)	(((x) & 0x0f) <= 9 && (x) <= 0x ## hi)
+# define DATA			((const unsigned char *) &data)
+
+	if (!BCD_VALID_P(data.sec, 59) ||
+	    !BCD_VALID_P(data.min, 59) ||
+	    !BCD_VALID_P(data.hour, 23) ||
+	    data.mday == 0 || !BCD_VALID_P(data.mday, 31) ||
+	    data.wday > 6 ||
+	    data.mon < 1 || 12 < data.mon ||
+	    !BCD_VALID_P(data.year, 99)) {
+		printk(KERN_ERR "RTC clock data is invalid! "
+			"(%02X %02X %02X %02X %02X %02X) - ",
+			DATA[0], DATA[1], DATA[2], DATA[3], DATA[4], DATA[5]);
+		if (++retry_count < 3) {
+			printk("retrying (%d)\n", retry_count);
+			goto retry;
+		}
+		printk("giving up, continuing\n");
+	}
+
+# undef BCD_VALID_P
+# undef DATA
+#endif /* RTC_SANITY_CHECK */
+
+#define CVT(x)	(((x) & 0xF) + ((x) >> 4) * 10)
+	if ((year = CVT(data.year) + 1900) < 1995)
+		year += 100;
+	return mktime(year, data.mon, CVT(data.mday),
+		       CVT(data.hour), CVT(data.min), CVT(data.sec));
+#undef CVT
+}
+
+#endif /* !_MACH_TIME_H */

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH] PC-9800 additional for 2.5.61-ac1 (17/21) serial
  2003-02-20 12:16 [PATCH] PC-9800 additional for 2.5.61-ac1 (0/21) summary Osamu Tomita
                   ` (14 preceding siblings ...)
  2003-02-20 12:35 ` [PATCH] PC-9800 additional for 2.5.61-ac1 (15/21) RTC Osamu Tomita
@ 2003-02-20 12:36 ` Osamu Tomita
  2003-02-20 12:37 ` [PATCH] PC-9800 additional for 2.5.61-ac1 (18/21) setup Osamu Tomita
                   ` (3 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Osamu Tomita @ 2003-02-20 12:36 UTC (permalink / raw)
  To: Linux Kernel Mailing List; +Cc: Alan Cox

This is additional patch to support NEC PC-9800 subarchitecture
against 2.5.61-ac1. (17/21)

Serial port support for PC98.
- Patch for onboard modem.
- New driver for 1st COM port.
  PC98 has 2 COM ports. 1st port uses 8251 upper compatible chip
  and 2nd port uses 16550A compatible chip.

diff -Nru linux/drivers/serial/8250_pnp.c linux98/drivers/serial/8250_pnp.c
--- linux/drivers/serial/8250_pnp.c	2002-12-11 13:10:07.000000000 +0900
+++ linux98/drivers/serial/8250_pnp.c	2002-12-11 13:16:51.000000000 +0900
@@ -188,6 +188,8 @@
 	{	"MVX00A1",		0	},
 	/* PC Rider K56 Phone System PnP */
 	{	"MVX00F2",		0	},
+	/* NEC 98NOTE SPEAKER PHONE FAX MODEM(33600bps) */
+	{	"nEC8241",		0	},
 	/* Pace 56 Voice Internal Plug & Play Modem */
 	{	"PMC2430",		0	},
 	/* Generic */
@@ -373,6 +375,9 @@
 			    ((port->min == 0x2f8) ||
 			     (port->min == 0x3f8) ||
 			     (port->min == 0x2e8) ||
+#ifdef CONFIG_X86_PC9800
+			     (port->min == 0x8b0) ||
+#endif
 			     (port->min == 0x3e8)))
 				return 0;
 	}
diff -Nru linux/drivers/serial/Kconfig linux98/drivers/serial/Kconfig
--- linux/drivers/serial/Kconfig	2003-01-14 14:59:16.000000000 +0900
+++ linux98/drivers/serial/Kconfig	2003-01-17 13:07:46.000000000 +0900
@@ -372,14 +372,25 @@
 	bool "Use NEC V850E on-chip UART for console"
 	depends on V850E_NB85E_UART
 
+config SERIAL98
+	tristate "PC-9800 8251-based primary serial port support"
+	depends on X86_PC9800
+	help
+	  If you want to use standard primary serial ports on PC-9800, 
+	  say Y.  Otherwise, say N.
+
+config SERIAL98_CONSOLE
+        bool "Support for console on PC-9800 standard serial port"
+        depends on SERIAL98=y
+
 config SERIAL_CORE
 	tristate
-	default m if SERIAL_AMBA!=y && SERIAL_CLPS711X!=y && SERIAL_21285!=y && !SERIAL_SA1100 && !SERIAL_ANAKIN && !SERIAL_UART00 && SERIAL_8250!=y && SERIAL_MUX!=y && !SERIAL_ROCKETPORT && !SERIAL_SUNCORE && !V850E_NB85E_UART && (SERIAL_AMBA=m || SERIAL_CLPS711X=m || SERIAL_21285=m || SERIAL_8250=m || SERIAL_MUX=m)
-	default y if SERIAL_AMBA=y || SERIAL_CLPS711X=y || SERIAL_21285=y || SERIAL_SA1100 || SERIAL_ANAKIN || SERIAL_UART00 || SERIAL_8250=y || SERIAL_MUX=y || SERIAL_ROCKETPORT || SERIAL_SUNCORE || V850E_NB85E_UART
+	default m if SERIAL_AMBA!=y && SERIAL_CLPS711X!=y && SERIAL_21285!=y && !SERIAL_SA1100 && !SERIAL_ANAKIN && !SERIAL_UART00 && SERIAL_8250!=y && SERIAL_MUX!=y && !SERIAL_ROCKETPORT && !SERIAL_SUNCORE && !V850E_NB85E_UART && (SERIAL_AMBA=m || SERIAL_CLPS711X=m || SERIAL_21285=m || SERIAL_8250=m || SERIAL_MUX=m || SERIAL98=m)
+	default y if SERIAL_AMBA=y || SERIAL_CLPS711X=y || SERIAL_21285=y || SERIAL_SA1100 || SERIAL_ANAKIN || SERIAL_UART00 || SERIAL_8250=y || SERIAL_MUX=y || SERIAL_ROCKETPORT || SERIAL_SUNCORE || V850E_NB85E_UART || SERIAL98=y
 
 config SERIAL_CORE_CONSOLE
 	bool
-	depends on SERIAL_AMBA_CONSOLE || SERIAL_CLPS711X_CONSOLE || SERIAL_21285_CONSOLE || SERIAL_SA1100_CONSOLE || SERIAL_ANAKIN_CONSOLE || SERIAL_UART00_CONSOLE || SERIAL_8250_CONSOLE || SERIAL_MUX_CONSOLE || SERIAL_SUNCORE || V850E_NB85E_UART_CONSOLE
+	depends on SERIAL_AMBA_CONSOLE || SERIAL_CLPS711X_CONSOLE || SERIAL_21285_CONSOLE || SERIAL_SA1100_CONSOLE || SERIAL_ANAKIN_CONSOLE || SERIAL_UART00_CONSOLE || SERIAL_8250_CONSOLE || SERIAL_MUX_CONSOLE || SERIAL_SUNCORE || V850E_NB85E_UART_CONSOLE || SERIAL98_CONSOLE
 	default y
 
 config SERIAL_68328
diff -Nru linux-2.5.60/drivers/serial/Makefile linux98-2.5.60/drivers/serial/Makefile
--- linux-2.5.60/drivers/serial/Makefile	2003-02-11 03:38:32.000000000 +0900
+++ linux98-2.5.60/drivers/serial/Makefile	2003-02-11 13:32:49.000000000 +0900
@@ -27,3 +27,4 @@
 obj-$(CONFIG_SERIAL_68360) += 68360serial.o
 obj-$(CONFIG_SERIAL_COLDFIRE) += mcfserial.o
 obj-$(CONFIG_V850E_NB85E_UART) += nb85e_uart.o
+obj-$(CONFIG_SERIAL98) += serial98.o
diff -Nru linux/drivers/serial/serial98.c linux98/drivers/serial/serial98.c
--- linux/drivers/serial/serial98.c	1970-01-01 09:00:00.000000000 +0900
+++ linux98/drivers/serial/serial98.c	2003-01-17 21:16:43.000000000 +0900
@@ -0,0 +1,1125 @@
+/*
+ *  linux/drivers/serial/serial98.c
+ *
+ *  Driver for NEC PC-9801/PC-9821 standard serial ports
+ *
+ *  Based on drivers/serial/8250.c, by Russell King.
+ *  Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
+ *
+ *  Copyright (C) 2002 Osamu Tomita <tomita@cinet.co.jp>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/tty.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <linux/console.h>
+#include <linux/sysrq.h>
+#include <linux/serial_reg.h>
+#include <linux/delay.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/pc9800.h>
+#include <asm/pc9800_sca.h>
+
+#if defined(CONFIG_SERIAL98_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+#define SUPPORT_SYSRQ
+#endif
+
+#include <linux/serial_core.h>
+
+#define SERIAL98_NR		1
+#define SERIAL98_ISR_PASS_LIMIT	256
+#define SERIAL98_EXT		0x434
+
+//#define RX_8251F		0x130	/* In: Receive buffer */
+//#define TX_8251F		0x130	/* Out: Transmit buffer */
+//#define LSR_8251F		0x132	/* In: Line Status Register */
+//#define MSR_8251F		0x134	/* In: Modem Status Register */
+#define IIR_8251F		0x136	/* In: Interrupt ID Register */
+#define FCR_8251F		0x138	/* I/O: FIFO Control Register */
+#define VFAST_8251F		0x13a	/* I/O: VFAST mode Register */
+
+#define CMD_8251F		0x32	/* Out: 8251 Command Resister */
+#define IER2_8251F		0x34	/* I/O: Interrupt Enable Register */
+#define IER1_8251F		0x35	/* I/O: Interrupt Enable Register */
+#define IER1_CTL		0x37	/* Out: Interrupt Enable Register */
+#define DIS_RXR_INT		0x00	/* disable RxRDY Interrupt */
+#define ENA_RXR_INT		0x01	/* enable RxRDY Interrupt */
+#define DIS_TXE_INT		0x02	/* disable TxEMPTY Interrupt */
+#define ENA_TXE_INT		0x03	/* enable TxEMPTY Interrupt */
+#define DIS_TXR_INT		0x04	/* disable TxRDY Interrupt */
+#define ENA_TXR_INT		0x05	/* enable TxRDY Interrupt */
+
+#define CMD_RESET		0x40	/* Reset Command */
+#define CMD_RTS			0x20	/* Set RTS line */
+#define CMD_CLR_ERR		0x10	/* Clear error flag */
+#define CMD_BREAK		0x08	/* Send Break */
+#define CMD_RXE			0x04	/* Enable receive */
+#define CMD_DTR			0x02	/* Set DTR line */
+#define CMD_TXE			0x01	/* Enable send */
+#define CMD_DUMMY		0x00	/* Dummy Command */
+
+#define VFAST_ENABLE		0x80	/* V.Fast mode Enable */
+
+/* Interrupt masks */
+#define INTR_8251_TXRE		0x04
+#define INTR_8251_TXEE		0x02
+#define INTR_8251_RXRE		0x01
+/* I/O Port */
+//#define PORT_8251_DATA	0
+//#define PORT_8251_CMD		2
+//#define PORT_8251_MOD		2
+//#define PORT_8251_STS		2
+/* status read */
+#define STAT_8251_TXRDY		0x01
+#define STAT_8251_RXRDY		0x02
+#define STAT_8251_TXEMP		0x04
+#define STAT_8251_PER		0x08
+#define STAT_8251_OER		0x10
+#define STAT_8251_FER		0x20
+#define STAT_8251_BRK		0x40
+#define STAT_8251_DSR		0x80
+#if 1
+#define STAT_8251F_TXEMP	0x01
+#define STAT_8251F_TXRDY	0x02
+#define STAT_8251F_RXRDY	0x04
+#define STAT_8251F_DSR		0x08
+#define STAT_8251F_OER		0x10
+#define STAT_8251F_PER		0x20
+#define STAT_8251F_FER		0x40
+#define STAT_8251F_BRK		0x80
+#else
+#define STAT_8251F_TXEMP	0x01
+#define STAT_8251F_TEMT		0x01
+#define STAT_8251F_TXRDY	0x02
+#define STAT_8251F_THRE		0x02
+#define STAT_8251F_RXRDY	0x04
+#define STAT_8251F_DSR		0x04
+#define STAT_8251F_PER		0x08
+#define STAT_8251F_OER		0x10
+#define STAT_8251F_FER		0x20
+#define STAT_8251F_BRK		0x40
+#endif
+
+/*
+ * We wrap our port structure around the generic uart_port.
+ */
+struct serial98_port {
+	struct uart_port	port;
+	unsigned int		type;
+	unsigned int		ext;
+	unsigned int		lsr_break_flag;
+	unsigned char		cmd;
+	unsigned char		mode;
+	unsigned char		msr;
+	unsigned char		ier;
+	unsigned char		rxchk;
+	unsigned char		txemp;
+	unsigned char		txrdy;
+	unsigned char		rxrdy;
+	unsigned char		brk;
+	unsigned char		fe;
+	unsigned char		oe;
+	unsigned char		pe;
+	unsigned char		dr;
+};
+
+#ifdef CONFIG_SERIAL98_CONSOLE
+static void
+serial98_console_write(struct console *co, const char *s, unsigned int count);
+static kdev_t serial98_console_device(struct console *co);
+static int __init serial98_console_setup(struct console *co, char *options);
+
+static struct console serial98_console = {
+	.name		= "ttyS",
+	.write		= serial98_console_write,
+	.device		= serial98_console_device,
+	.setup		= serial98_console_setup,
+	.flags		= CON_PRINTBUFFER,
+	.index		= -1,
+};
+
+#define SERIAL98_CONSOLE	&serial98_console
+#else
+#define SERIAL98_CONSOLE	NULL
+#endif
+
+static struct uart_driver serial98_reg = {
+	.owner			= THIS_MODULE,
+	.driver_name		= "serial98",
+	.dev_name		= "ttyS%d",
+	.major			= TTY_MAJOR,
+	.minor			= 64,
+	.nr			= SERIAL98_NR,
+	.cons			= SERIAL98_CONSOLE,
+};
+
+static int serial98_clk;
+static char type_str[48];
+
+#define PORT98 ((struct serial98_port *)port)
+#define PORT (PORT98->port)
+
+static void serial98_fifo_enable(struct uart_port *port, int enable)
+{
+	unsigned char fcr;
+
+	if (PORT.type == PORT_FIFO_PC98 || PORT.type == PORT_VFAST_PC98) {
+		fcr = inb(FCR_8251F);
+		if (enable)
+			fcr |= UART_FCR_ENABLE_FIFO;
+		else
+			fcr &= ~UART_FCR_ENABLE_FIFO;
+		outb(fcr, FCR_8251F);
+	}
+
+	if (!enable)
+		return;
+
+	outb(0, 0x5f);	/* wait */
+	outb(0, 0x5f);
+	outb(0, 0x5f);
+	outb(0, 0x5f);
+}
+
+static void serial98_cmd_out(struct uart_port *port, unsigned char cmd)
+{
+	serial98_fifo_enable(port, 0);
+	outb(cmd, CMD_8251F);
+	serial98_fifo_enable(port, 1);
+}
+
+static void serial98_mode_set(struct uart_port *port)
+{
+	serial98_cmd_out(port, CMD_DUMMY);
+	serial98_cmd_out(port, CMD_DUMMY);
+	serial98_cmd_out(port, CMD_DUMMY);
+	serial98_cmd_out(port, CMD_RESET);
+	serial98_cmd_out(port, PORT98->mode);
+}
+
+static unsigned char serial98_msr_in(struct uart_port *port)
+{
+	unsigned long flags;
+	unsigned int ms, st;
+	unsigned int tmp;
+
+	spin_lock_irqsave(&PORT.lock, flags);
+	if (PORT.type == PORT_FIFO_PC98 || PORT.type == PORT_VFAST_PC98) {
+		PORT98->msr = inb(PORT.iobase + 4);
+	} else {
+		ms = inb(0x33);
+		st = inb(0x32);
+		tmp = 0;
+		if(!(ms & 0x20))
+			tmp |= UART_MSR_DCD;
+		if(!(ms & 0x80)) {
+			tmp |= UART_MSR_RI;
+			PORT98->msr |= UART_MSR_RI;
+		}
+		if(!(ms & 0x40))
+			tmp |= UART_MSR_CTS;
+		if(st & 0x80)
+			tmp |= UART_MSR_DSR;
+		PORT98->msr = ((PORT98->msr ^ tmp) >> 4) | tmp;
+	}
+
+	spin_unlock_irqrestore(&PORT.lock, flags);
+	return PORT98->msr;
+}
+
+static void serial98_stop_tx(struct uart_port *port, unsigned int tty_stop)
+{
+	unsigned int ier = inb(IER1_8251F);
+
+	ier &= ~(INTR_8251_TXRE | INTR_8251_TXEE);
+	outb(ier, IER1_8251F);
+}
+
+static void serial98_start_tx(struct uart_port *port, unsigned int tty_start)
+{
+	unsigned int ier = inb(IER1_8251F);
+
+	ier |= INTR_8251_TXRE | INTR_8251_TXEE;
+	outb(ier, IER1_8251F);
+}
+
+static void serial98_stop_rx(struct uart_port *port)
+{
+	PORT.read_status_mask &= ~PORT98->dr;
+	outb(DIS_RXR_INT, IER1_CTL);
+}
+
+static void serial98_enable_ms(struct uart_port *port)
+{
+	outb(PORT98->ier | 0x80, IER2_8251F);
+}
+
+static void serial98_rx_chars(struct uart_port *port, int *status,
+				struct pt_regs *regs)
+{
+	struct tty_struct *tty = PORT.info->tty;
+	unsigned char ch;
+	int max_count = 256;
+
+	do {
+		if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) {
+			tty->flip.work.func((void *)tty);
+			if (tty->flip.count >= TTY_FLIPBUF_SIZE)
+				return; // if TTY_DONT_FLIP is set
+		}
+		ch = inb(PORT.iobase);
+		*tty->flip.char_buf_ptr = ch;
+		*tty->flip.flag_buf_ptr = TTY_NORMAL;
+		PORT.icount.rx++;
+
+		if (unlikely(*status & (PORT98->brk | PORT98->pe |
+				       PORT98->fe | PORT98->oe))) {
+			/*
+			 * For statistics only
+			 */
+			if (*status & PORT98->brk) {
+				*status &= ~(PORT98->fe | PORT98->pe);
+				PORT.icount.brk++;
+				/*
+				 * We do the SysRQ and SAK checking
+				 * here because otherwise the break
+				 * may get masked by ignore_status_mask
+				 * or read_status_mask.
+				 */
+				if (uart_handle_break(&PORT))
+					goto ignore_char;
+			} else if (*status & PORT98->pe)
+				PORT.icount.parity++;
+			else if (*status & PORT98->fe)
+				PORT.icount.frame++;
+			if (*status & PORT98->oe)
+				PORT.icount.overrun++;
+
+			/*
+			 * Mask off conditions which should be ingored.
+			 */
+			*status &= PORT.read_status_mask;
+
+#ifdef CONFIG_SERIAL98_CONSOLE
+			if (PORT.line == PORT.cons->index) {
+				/* Recover the break flag from console xmit */
+				*status |= PORT98->lsr_break_flag;
+				PORT98->lsr_break_flag = 0;
+			}
+#endif
+			if (*status & PORT98->brk) {
+				*tty->flip.flag_buf_ptr = TTY_BREAK;
+			} else if (*status & PORT98->pe)
+				*tty->flip.flag_buf_ptr = TTY_PARITY;
+			else if (*status & PORT98->fe)
+				*tty->flip.flag_buf_ptr = TTY_FRAME;
+		}
+		if (uart_handle_sysrq_char(&PORT, ch, regs))
+			goto ignore_char;
+		if ((*status & PORT.ignore_status_mask) == 0) {
+			tty->flip.flag_buf_ptr++;
+			tty->flip.char_buf_ptr++;
+			tty->flip.count++;
+		}
+		if ((*status & PORT98->oe) &&
+		    tty->flip.count < TTY_FLIPBUF_SIZE) {
+			/*
+			 * Overrun is special, since it's reported
+			 * immediately, and doesn't affect the current
+			 * character.
+			 */
+			*tty->flip.flag_buf_ptr = TTY_OVERRUN;
+			tty->flip.flag_buf_ptr++;
+			tty->flip.char_buf_ptr++;
+			tty->flip.count++;
+		}
+	ignore_char:
+		*status = inb(PORT.iobase + 2);
+	} while ((*status & PORT98->rxchk) && (max_count-- > 0));
+	tty_flip_buffer_push(tty);
+}
+
+static void serial98_tx_chars(struct uart_port *port)
+{
+	struct circ_buf *xmit = &PORT.info->xmit;
+	int count;
+
+	if (PORT.x_char) {
+		outb(PORT.x_char, PORT.iobase);
+		PORT.icount.tx++;
+		PORT.x_char = 0;
+		return;
+	}
+	if (uart_circ_empty(xmit) || uart_tx_stopped(&PORT)) {
+		serial98_stop_tx(port, 0);
+		return;
+	}
+
+	count = PORT.fifosize;
+	do {
+		outb(xmit->buf[xmit->tail], PORT.iobase);
+		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+		PORT.icount.tx++;
+		if (uart_circ_empty(xmit))
+			break;
+	} while (--count > 0);
+
+	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+		uart_write_wakeup(&PORT);
+
+	if (uart_circ_empty(xmit))
+		serial98_stop_tx(&PORT, 0);
+}
+
+static void serial98_modem_status(struct uart_port *port)
+{
+	int status;
+
+	status = serial98_msr_in(port);
+
+	if ((status & UART_MSR_ANY_DELTA) == 0)
+		return;
+
+	if (status & UART_MSR_TERI)
+		PORT.icount.rng++;
+	if (status & UART_MSR_DDSR)
+		PORT.icount.dsr++;
+	if (status & UART_MSR_DDCD)
+		uart_handle_dcd_change(&PORT, status & UART_MSR_DCD);
+	if (status & UART_MSR_DCTS)
+		uart_handle_cts_change(&PORT, status & UART_MSR_CTS);
+
+	wake_up_interruptible(&PORT.info->delta_msr_wait);
+}
+
+static void serial98_int(int irq, void *port, struct pt_regs *regs)
+{
+	unsigned int status;
+
+	spin_lock(&PORT.lock);
+	status = inb(PORT.iobase + 2);
+	if (status & PORT98->rxrdy) {
+		serial98_rx_chars(port, &status, regs);
+	}
+	serial98_modem_status(port);
+	if (status & PORT98->txrdy) {
+		serial98_tx_chars(port);
+	}
+	spin_unlock(&PORT.lock);
+}
+
+static unsigned int serial98_tx_empty(struct uart_port *port)
+{
+	unsigned long flags;
+	unsigned int ret = 0;
+
+	spin_lock_irqsave(&PORT.lock, flags);
+	if (inb(PORT.iobase + 2) & PORT98->txemp)
+			ret = TIOCSER_TEMT;
+
+	spin_unlock_irqrestore(&PORT.lock, flags);
+	return ret;
+}
+
+static unsigned int serial98_get_mctrl(struct uart_port *port)
+{
+	unsigned char status;
+	unsigned int ret = 0;
+
+	status = serial98_msr_in(port);
+	if (status & UART_MSR_DCD)
+		ret |= TIOCM_CAR;
+	if (status & UART_MSR_RI)
+		ret |= TIOCM_RNG;
+	if (status & UART_MSR_DSR)
+		ret |= TIOCM_DSR;
+	if (status & UART_MSR_CTS)
+		ret |= TIOCM_CTS;
+	return ret;
+}
+
+static void serial98_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+	PORT98->cmd &= 0xdd;
+	if (mctrl & TIOCM_RTS)
+		PORT98->cmd |= CMD_RTS;
+
+	if (mctrl & TIOCM_DTR)
+		PORT98->cmd |= CMD_DTR;
+
+	serial98_cmd_out(port, PORT98->cmd);
+}
+
+static void serial98_break_ctl(struct uart_port *port, int break_state)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&PORT.lock, flags);
+	if (break_state == -1)
+		PORT98->cmd |= CMD_BREAK;
+	else
+		PORT98->cmd &= ~CMD_BREAK;
+
+	serial98_cmd_out(port, PORT98->cmd);
+	spin_unlock_irqrestore(&PORT.lock, flags);
+}
+
+static int serial98_startup(struct uart_port *port)
+{
+	int retval;
+
+	if (PORT.type == PORT_8251_PC98) {
+		/* Wake up UART */
+		PORT98->mode = 0xfc;
+		serial98_mode_set(port);
+		outb(DIS_RXR_INT, IER1_CTL);
+		outb(DIS_TXE_INT, IER1_CTL);
+		outb(DIS_TXR_INT, IER1_CTL);
+		PORT98->mode = 0;
+		serial98_mode_set(port);
+	}
+
+	/*
+	 * Clear the FIFO buffers and disable them.
+	 * (they will be reeanbled in set_termios())
+	 */
+	if (PORT.type == PORT_FIFO_PC98 || PORT.type == PORT_VFAST_PC98) {
+		outb(UART_FCR_ENABLE_FIFO, FCR_8251F);
+		outb((UART_FCR_ENABLE_FIFO
+			| UART_FCR_CLEAR_RCVR
+			| UART_FCR_CLEAR_XMIT), FCR_8251F);
+		outb(0, FCR_8251F);
+	}
+
+	/* Clear the interrupt registers. */
+	inb(0x30);
+	inb(0x32);
+	if (PORT.type == PORT_FIFO_PC98 || PORT.type == PORT_VFAST_PC98) {
+		inb(PORT.iobase);
+		inb(PORT.iobase + 2);
+		inb(PORT.iobase + 4);
+		inb(PORT.iobase + 6);
+	}
+
+	/* Allocate the IRQ */
+	retval = request_irq(PORT.irq, serial98_int, 0,
+				serial98_reg.driver_name, port);
+	if (retval)
+		return retval;
+
+	/*
+	 * Now, initialize the UART
+	 */
+	PORT98->mode = 0x4e;
+	serial98_mode_set(port);
+	PORT98->cmd = 0x15;
+	serial98_cmd_out(port, PORT98->cmd);
+	PORT98->cmd = 0x05;
+
+	/*
+	 * Finally, enable interrupts
+	 */
+	outb(0x00, IER2_8251F);
+	outb(ENA_RXR_INT, IER1_CTL);
+
+	/*
+	 * And clear the interrupt registers again for luck.
+	 */
+	inb(0x30);
+	inb(0x32);
+	if (PORT.type == PORT_FIFO_PC98 || PORT.type == PORT_VFAST_PC98) {
+		inb(PORT.iobase);
+		inb(PORT.iobase + 2);
+		inb(PORT.iobase + 4);
+		inb(PORT.iobase + 6);
+	}
+
+	return 0;
+}
+
+static void serial98_shutdown(struct uart_port *port)
+{
+	unsigned long flags;
+
+	/*
+	 * disable all interrupts
+	 */
+	spin_lock_irqsave(&PORT.lock, flags);
+	if (PORT.type == PORT_VFAST_PC98)
+		outb(0, VFAST_8251F);		/* V.FAST mode off */
+
+	/* disnable all modem status interrupt */
+	outb(0x80, IER2_8251F);
+
+	/* disnable TX/RX interrupt */
+	outb(0x00, IER2_8251F);
+	outb(DIS_RXR_INT, IER1_CTL);
+	outb(DIS_TXE_INT, IER1_CTL);
+	outb(DIS_TXR_INT, IER1_CTL);
+	PORT98->ier = 0;
+
+	spin_unlock_irqrestore(&PORT.lock, flags);
+
+	/*
+	 * Free the interrupt
+	 */
+	free_irq(PORT.irq, port);
+
+	/* disable break condition and disable the port */
+	serial98_mode_set(port);
+
+	/* disable FIFO's */	
+	if (PORT.type == PORT_FIFO_PC98 || PORT.type == PORT_VFAST_PC98) {
+		outb((UART_FCR_ENABLE_FIFO
+			| UART_FCR_CLEAR_RCVR
+			| UART_FCR_CLEAR_XMIT), FCR_8251F);
+		outb(0, FCR_8251F);
+	}
+
+	inb(PORT.iobase);
+}
+
+static void
+serial98_set_termios(struct uart_port *port, struct termios *termios,
+		       struct termios *old)
+{
+	unsigned char stopbit, cval, fcr = 0, ier = 0;
+	unsigned long flags;
+	unsigned int quot;
+
+	stopbit = 0x80;
+	switch (termios->c_cflag & CSIZE) {
+		case CS5:
+			cval = 0x42;
+			stopbit = 0xc0;
+			break;
+		case CS6:
+			cval = 0x46;
+			break;
+		case CS7:
+			cval = 0x4a;
+			break;
+		default:
+		case CS8:
+			cval = 0x4e;
+			break;
+	}
+
+	if (termios->c_cflag & CSTOPB)
+		cval ^= stopbit;
+	if (termios->c_cflag & PARENB)
+		cval |= 0x10;
+	if (!(termios->c_cflag & PARODD))
+		cval |= 0x20;
+
+	/*
+	 * Ask the core to calculate the divisor for us.
+	 */
+	quot = uart_get_divisor(port, termios, old);
+
+	if (PORT.type == PORT_FIFO_PC98 || PORT.type == PORT_VFAST_PC98) {
+		if ((PORT.uartclk / quot) < (2400 * 16))
+			fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1;
+		else
+			fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_8;
+	}
+
+	/*
+	 * Ok, we're now changing the port state.  Do it with
+	 * interrupts disabled.
+	 */
+	spin_lock_irqsave(&PORT.lock, flags);
+
+	/*
+	 * Update the per-port timeout.
+	 */
+	uart_update_timeout(port, termios->c_cflag, quot);
+
+	PORT.read_status_mask = PORT98->oe | PORT98->txemp | PORT98->dr;
+	if (termios->c_iflag & INPCK)
+		PORT.read_status_mask |= PORT98->fe | PORT98->pe;
+
+	if (termios->c_iflag & (BRKINT | PARMRK))
+		PORT.read_status_mask |= PORT98->brk;
+	/*
+	 * Characteres to ignore
+	 */
+	PORT.ignore_status_mask = 0;
+	if (termios->c_iflag & IGNPAR)
+		PORT.ignore_status_mask |= PORT98->fe | PORT98->pe;
+
+	if (termios->c_iflag & IGNBRK) {
+		PORT.ignore_status_mask |= PORT98->brk;
+		/*
+		 * If we're ignoring parity and break indicators,
+		 * ignore overruns too (for real raw support).
+		 */
+		if (termios->c_iflag & IGNPAR)
+			PORT.ignore_status_mask |= PORT98->oe;
+	}
+
+	/*
+	 * ignore all characters if CREAD is not set
+	 */
+	if ((termios->c_cflag & CREAD) == 0)
+		PORT.ignore_status_mask |= PORT98->dr;
+
+	/*
+	 * CTS flow control flag and modem status interrupts
+	 */
+	if (PORT.flags & UPF_HARDPPS_CD)
+		ier |= 0x80;	/* enable modem status interrupt */
+	if (termios->c_cflag & CRTSCTS) {
+		ier |= 0x08;	/* enable CTS interrupt */
+		ier |= 0x80;	/* enable modem status interrupt */
+	}
+	if (!(termios->c_cflag & CLOCAL)) {
+		ier |= 0x20;	/* enable CD interrupt */
+		ier |= 0x80;	/* enable modem status interrupt */
+	}
+	PORT98->ier = ier;
+
+	PORT98->mode = cval;
+	serial98_mode_set(port);
+	if (PORT.type == PORT_VFAST_PC98 && quot <= 48) {
+		quot /= 4;
+		if (quot < 1)
+			quot = 1;
+		outb(quot | VFAST_ENABLE, VFAST_8251F);
+	} else {
+		quot /= 3;
+		if (quot < 1)
+			quot = 1;
+		if (PORT.type == PORT_VFAST_PC98)
+			outb(0, VFAST_8251F);		/* V.FAST mode off */
+		outb(0xb6, 0x77);
+		outb(quot & 0xff, 0x75);		/* LS of divisor */
+		outb(quot >> 8, 0x75);			/* MS of divisor */
+	}
+
+	if (fcr & UART_FCR_ENABLE_FIFO) {
+		outb(UART_FCR_ENABLE_FIFO, FCR_8251F);
+		outb(fcr, FCR_8251F);
+	}
+
+	/* enable RX/TX */
+	PORT98->cmd = 0x15;
+	serial98_cmd_out(port, PORT98->cmd);
+	PORT98->cmd = 0x05;
+	/* enable interrupts */
+	outb(0x00, IER2_8251F);
+	outb(ENA_RXR_INT, IER1_CTL);
+	spin_unlock_irqrestore(&PORT.lock, flags);
+}
+
+static const char *serial98_type(struct uart_port *port)
+{
+	char *p;
+
+	switch (PORT.type) {
+		case PORT_8251_PC98:
+			p = "PC98 onboard legacy 8251";
+			break;
+		case PORT_19K_PC98:
+			p =  "PC98 onboard max 19200bps";
+			break;
+		case PORT_FIFO_PC98:
+			p = "PC98 onboard with FIFO";
+			break;
+		case PORT_VFAST_PC98:
+			p = "PC98 onboard V.FAST";
+			break;
+		case PORT_PC9861:
+			p = "PC-9861K RS-232C ext. board";
+			break;
+		case PORT_PC9801_101:
+			p = "PC-9801-101 RS-232C ext. board";
+			break;
+		default:
+			return NULL;
+	}
+
+	sprintf(type_str, "%s  Clock %dMHz", p, serial98_clk);
+	return type_str;
+}
+
+/* Release the region(s) being used by 'port' */
+static void serial98_release_port(struct uart_port *port)
+{
+	switch (PORT.type) {
+		case PORT_VFAST_PC98:
+			release_region(PORT.iobase + 0xa, 1);
+		case PORT_FIFO_PC98:
+			release_region(PORT.iobase + 8, 1);
+			release_region(PORT.iobase + 6, 1);
+			release_region(PORT.iobase + 4, 1);
+			release_region(PORT.iobase + 2, 1);
+			release_region(PORT.iobase, 1);
+		case PORT_19K_PC98:
+			release_region(SERIAL98_EXT, 1);
+			release_region(0x34, 1);
+		case PORT_8251_PC98:
+			release_region(0x32, 1);
+			release_region(0x30, 1);
+	}
+}
+
+/* Request the region(s) being used by 'port' */
+#define REQ_REGION98(base) (request_region((base), 1, serial98_reg.driver_name))
+static int serial98_request_region(unsigned int type)
+{
+	if (!REQ_REGION98(0x30))
+		return -EBUSY;
+	if (REQ_REGION98(0x32)) {
+		if (type == PORT_8251_PC98)
+			return 0;
+		if (REQ_REGION98(0x34)) {
+			if (REQ_REGION98(SERIAL98_EXT)) {
+				unsigned long base;
+
+				if (type == PORT_19K_PC98)
+					return 0;
+				for (base = 0x130; base <= 0x138; base += 2) {
+					if (!REQ_REGION98(base)) {
+						base -= 2;
+						goto err;
+					}
+				}
+				if (type == PORT_FIFO_PC98)
+					return 0;
+				if (type == PORT_VFAST_PC98) {
+					if (REQ_REGION98(0x13a))
+						return 0;
+				}
+				err:
+				while (base >= 0x130) {
+					release_region(base, 1);
+					base -= 2;
+				}
+				release_region(SERIAL98_EXT, 1);
+			}
+			release_region(0x34, 1);
+		}
+		release_region(0x32, 1);
+	}
+	release_region(0x30, 1);
+	return -EBUSY;
+}
+
+static int serial98_request_port(struct uart_port *port)
+{
+	return serial98_request_region(PORT.type);
+}
+
+/*
+ * Configure/autoconfigure the port.
+ */
+static void serial98_config_port(struct uart_port *port, int flags)
+{
+	if (flags & UART_CONFIG_TYPE)
+		PORT.type = PORT98->type;
+}
+
+/*
+ * verify the new serial_struct (for TIOCSSERIAL).
+ */
+static int serial98_verify_port(struct uart_port *port, struct serial_struct *ser)
+{
+	switch (ser->type) {
+		case PORT_VFAST_PC98:
+		case PORT_FIFO_PC98:
+		case PORT_19K_PC98:
+		case PORT_8251_PC98:
+		/* not implemented yet
+		case PORT_PC9861:
+		case PORT_PC9801_101:
+		*/
+		case PORT_UNKNOWN:
+			break;
+		default:
+			return -EINVAL;
+	}
+	if (ser->irq < 0 || ser->irq >= NR_IRQS)
+		return -EINVAL;
+	if (ser->baud_base < 9600)
+		return -EINVAL;
+	return 0;
+}
+
+static struct uart_ops serial98_ops = {
+	.tx_empty	= serial98_tx_empty,
+	.set_mctrl	= serial98_set_mctrl,
+	.get_mctrl	= serial98_get_mctrl,
+	.stop_tx	= serial98_stop_tx,
+	.start_tx	= serial98_start_tx,
+	.stop_rx	= serial98_stop_rx,
+	.enable_ms	= serial98_enable_ms,
+	.break_ctl	= serial98_break_ctl,
+	.startup	= serial98_startup,
+	.shutdown	= serial98_shutdown,
+	.set_termios	= serial98_set_termios,
+	.type		= serial98_type,
+	.release_port	= serial98_release_port,
+	.request_port	= serial98_request_port,
+	.config_port	= serial98_config_port,
+	.verify_port	= serial98_verify_port,
+};
+
+static struct serial98_port serial98_ports[SERIAL98_NR] = {
+	{
+		.port =	{
+				.iobase		= 0x30,
+				.iotype		= SERIAL_IO_PORT,
+				.irq		= 4,
+				.fifosize	= 1,
+				.ops		= &serial98_ops,
+				.flags		= ASYNC_BOOT_AUTOCONF,
+				.line		= 0,
+			},
+		.rxchk = STAT_8251_RXRDY,
+		.txemp = STAT_8251_TXEMP,
+		.txrdy = STAT_8251_TXRDY,
+		.rxrdy = STAT_8251_RXRDY,
+		.brk = STAT_8251_BRK,
+		.fe = STAT_8251_FER,
+		.oe = STAT_8251_OER,
+		.pe = STAT_8251_PER,
+		.dr = STAT_8251_DSR,
+	},
+};
+
+#ifdef CONFIG_SERIAL98_CONSOLE
+
+#define BOTH_EMPTY (PORT98->txemp | PORT98->txrdy)
+
+/*
+ *	Wait for transmitter & holding register to empty
+ */
+static inline void wait_for_xmitr(struct uart_port *port)
+{
+	unsigned int status, tmout = 10000;
+
+	/* Wait up to 10ms for the character(s) to be sent. */
+	do {
+		status = inb(PORT.iobase + 2);
+
+		if (status & PORT98->brk)
+			PORT98->lsr_break_flag = PORT98->brk;
+
+		if (--tmout == 0)
+			break;
+		udelay(1);
+	} while ((status & BOTH_EMPTY) != BOTH_EMPTY);
+
+	/* Wait up to 1s for flow control if necessary */
+	if (PORT.flags & UPF_CONS_FLOW) {
+		tmout = 1000000;
+		while (--tmout &&
+		       ((serial98_msr_in(port) & UART_MSR_CTS) == 0))
+			udelay(1);
+	}
+}
+
+/*
+ *	Print a string to the serial port trying not to disturb
+ *	any possible real use of the port...
+ *
+ *	The console_lock must be held when we get here.
+ */
+static void
+serial98_console_write(struct console *co, const char *s, unsigned int count)
+{
+	struct uart_port *port = (struct uart_port *)&serial98_ports[co->index];
+	unsigned int ier1, ier2;
+	int i;
+
+	/*
+	 *	First save the UER then disable the interrupts
+	 */
+	ier1 = inb(IER1_8251F);
+	ier2 = inb(IER2_8251F);
+	/* disnable all modem status interrupt */
+	outb(0x80, IER2_8251F);
+
+	/* disnable TX/RX interrupt */
+	outb(0x00, IER2_8251F);
+	outb(DIS_RXR_INT, IER1_CTL);
+	outb(DIS_TXE_INT, IER1_CTL);
+	outb(DIS_TXR_INT, IER1_CTL);
+
+	/*
+	 *	Now, do each character
+	 */
+	for (i = 0; i < count; i++, s++) {
+		wait_for_xmitr(port);
+
+		/*
+		 *	Send the character out.
+		 *	If a LF, also do CR...
+		 */
+		outb(*s, PORT.iobase);
+		if (*s == 10) {
+			wait_for_xmitr(port);
+			outb(13, PORT.iobase);
+		}
+	}
+
+	/*
+	 *	Finally, wait for transmitter to become empty
+	 *	and restore the IER
+	 */
+	wait_for_xmitr(port);
+
+	/* restore TX/RX interrupt */
+	outb(0x00, IER2_8251F);
+	if (ier1 & 0x01)
+		outb(ENA_RXR_INT, IER1_CTL);
+	if (ier1 & 0x02)
+		outb(ENA_TXE_INT, IER1_CTL);
+	if (ier1 & 0x04)
+		outb(ENA_TXR_INT, IER1_CTL);
+
+	/* restore modem status interrupt */
+	outb(ier2, IER2_8251F);
+}
+
+static kdev_t serial98_console_device(struct console *co)
+{
+	return mk_kdev(TTY_MAJOR, 64 + co->index);
+}
+
+static int __init serial98_console_setup(struct console *co, char *options)
+{
+	struct uart_port *port;
+	int baud = 9600;
+	int bits = 8;
+	int parity = 'n';
+	int flow = 'n';
+
+	/*
+	 * Check whether an invalid uart number has been specified, and
+	 * if so, search for the first available port that does have
+	 * console support.
+	 */
+	if (co->index >= SERIAL98_NR)
+		co->index = 0;
+	port = &serial98_ports[co->index].port;
+
+	/*
+	 * Temporary fix.
+	 */
+	spin_lock_init(&port->lock);
+
+	if (options)
+		uart_parse_options(options, &baud, &parity, &bits, &flow);
+
+	return uart_set_options(port, co, baud, parity, bits, flow);
+}
+
+void __init serial98_console_init(void)
+{
+	register_console(&serial98_console);
+}
+
+#endif /* CONFIG_SERIAL98_CONSOLE */
+
+
+static int __init serial98_init(void)
+{
+	int ret;
+	unsigned char iir1, iir2;
+
+	if (PC9800_8MHz_P()) {
+		serial98_clk = 8;
+		serial98_ports[0].port.uartclk = 374400 * 16;
+	} else {
+		serial98_clk = 5;
+		serial98_ports[0].port.uartclk = 460800 * 16;
+	}
+
+	printk(KERN_INFO "serial98: PC-9801 standard serial port driver Version 0.1alpha\n");
+	serial98_ports[0].type = PORT_8251_PC98;
+	/* Check FIFO exist */
+	iir1 = inb(IIR_8251F);
+	iir2 = inb(IIR_8251F);
+	if ((iir1 & 0x40) != (iir2 & 0x40) && (iir1 & 0x20) == (iir2 & 0x20)) {
+		serial98_ports[0].port.iobase = 0x130;
+		serial98_ports[0].port.fifosize = 16;
+		serial98_ports[0].rxchk = STAT_8251F_DSR;
+		serial98_ports[0].txemp = STAT_8251F_TXEMP;
+		serial98_ports[0].txrdy = STAT_8251F_TXRDY;
+		serial98_ports[0].rxrdy = STAT_8251F_RXRDY;
+		serial98_ports[0].brk = STAT_8251F_BRK;
+		serial98_ports[0].fe = STAT_8251F_FER;
+		serial98_ports[0].oe = STAT_8251F_OER;
+		serial98_ports[0].pe = STAT_8251F_PER;
+		serial98_ports[0].dr = STAT_8251F_DSR;
+
+		if (*(unsigned char*)__va(PC9821SCA_RSFLAGS) & 0x10)
+			serial98_ports[0].type = PORT_VFAST_PC98;
+		else {
+			outb(serial98_ports[0].ext | 0x40, SERIAL98_EXT);
+			serial98_ports[0].port.uartclk *= 4;
+			serial98_ports[0].type = PORT_FIFO_PC98;
+		}
+	} else if ((serial98_ports[0].ext = inb(SERIAL98_EXT)) != 0xff) {
+		outb(serial98_ports[0].ext | 0x40, SERIAL98_EXT);
+		if (inb(SERIAL98_EXT) == (serial98_ports[0].ext | 0x40)) {
+			serial98_ports[0].port.uartclk *= 4;
+			serial98_ports[0].type = PORT_19K_PC98;
+		} else {
+			serial98_ops.enable_ms = NULL;
+			outb(serial98_ports[0].ext, SERIAL98_EXT);
+		}
+	}
+
+	if (serial98_request_region(serial98_ports[0].type))
+		return -EBUSY;
+
+	ret = uart_register_driver(&serial98_reg);
+	if (ret == 0) {
+		int i;
+
+		for (i = 0; i < SERIAL98_NR; i++) {
+			uart_add_one_port(&serial98_reg,
+					(struct uart_port *)&serial98_ports[i]);
+		}
+	}
+
+	return ret;
+}
+
+static void __exit serial98_exit(void)
+{
+	int i;
+
+	if (serial98_ports[0].type == PORT_19K_PC98
+			|| serial98_ports[0].type == PORT_FIFO_PC98)
+		outb(serial98_ports[0].ext, SERIAL98_EXT);
+
+	for (i = 0; i < SERIAL98_NR; i++) {
+		uart_remove_one_port(&serial98_reg,
+					(struct uart_port *)&serial98_ports[i]);
+	}
+
+	uart_unregister_driver(&serial98_reg);
+}
+
+module_init(serial98_init);
+module_exit(serial98_exit);
+
+EXPORT_NO_SYMBOLS;
+
+MODULE_AUTHOR("Osamu Tomita <tomita@cinet.co.jp>");
+MODULE_DESCRIPTION("PC-9801 standard serial port driver Version 0.1alpha");
+MODULE_LICENSE("GPL");
diff -Nru linux-2.5.61-ac1/include/linux/serial_core.h linux98-2.5.61-ac1/include/linux/serial_core.h
--- linux-2.5.61-ac1/include/linux/serial_core.h	2003-02-18 08:58:30.000000000 +0900
+++ linux98-2.5.61-ac1/include/linux/serial_core.h	2003-02-18 15:17:31.000000000 +0900
@@ -59,6 +59,14 @@
 /* NEC v850.  */
 #define PORT_NB85E_UART	40
 
+/* NEC PC-9800 */
+#define PORT_8251_PC98	41
+#define PORT_19K_PC98	42
+#define PORT_FIFO_PC98	43
+#define PORT_VFAST_PC98	44
+#define PORT_PC9861	45
+#define PORT_PC9801_101	46
+
 
 #ifdef __KERNEL__
 

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH] PC-9800 additional for 2.5.61-ac1 (18/21) setup
  2003-02-20 12:16 [PATCH] PC-9800 additional for 2.5.61-ac1 (0/21) summary Osamu Tomita
                   ` (15 preceding siblings ...)
  2003-02-20 12:36 ` [PATCH] PC-9800 additional for 2.5.61-ac1 (17/21) serial Osamu Tomita
@ 2003-02-20 12:37 ` Osamu Tomita
  2003-02-20 12:38 ` [PATCH] PC-9800 additional for 2.5.61-ac1 (19/21) SMP Osamu Tomita
                   ` (2 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Osamu Tomita @ 2003-02-20 12:37 UTC (permalink / raw)
  To: Linux Kernel Mailing List; +Cc: Alan Cox

This is additional patch to support NEC PC-9800 subarchitecture
against 2.5.61-ac1. (18/21)

Support difference of IO port/memory address, using mach-* scheme.

diff -Nru linux-2.5.61-ac1/arch/i386/kernel/setup.c linux98-2.5.61/arch/i386/kernel/setup.c
--- linux-2.5.61-ac1/arch/i386/kernel/setup.c	2003-02-18 08:58:20.000000000 +0900
+++ linux98-2.5.61/arch/i386/kernel/setup.c	2003-02-18 12:58:14.000000000 +0900
@@ -23,6 +23,7 @@
  * This file handles the architecture-dependent parts of initialization
  */
 
+#include <linux/config.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/tty.h>
@@ -43,6 +44,7 @@
 #include <asm/setup.h>
 #include <asm/arch_hooks.h>
 #include "setup_arch_pre.h"
+#include "mach_resources.h"
 
 int disable_pse __initdata = 0;
 
@@ -104,98 +106,8 @@
 static char command_line[COMMAND_LINE_SIZE];
        char saved_command_line[COMMAND_LINE_SIZE];
 
-struct resource standard_io_resources[] = {
-	{ "dma1", 0x00, 0x1f, IORESOURCE_BUSY },
-	{ "pic1", 0x20, 0x3f, IORESOURCE_BUSY },
-	{ "timer", 0x40, 0x5f, IORESOURCE_BUSY },
-	{ "keyboard", 0x60, 0x6f, IORESOURCE_BUSY },
-	{ "dma page reg", 0x80, 0x8f, IORESOURCE_BUSY },
-	{ "pic2", 0xa0, 0xbf, IORESOURCE_BUSY },
-	{ "dma2", 0xc0, 0xdf, IORESOURCE_BUSY },
-	{ "fpu", 0xf0, 0xff, IORESOURCE_BUSY }
-};
-#ifdef CONFIG_MELAN
-standard_io_resources[1] = { "pic1", 0x20, 0x21, IORESOURCE_BUSY };
-standard_io_resources[5] = { "pic2", 0xa0, 0xa1, IORESOURCE_BUSY };
-#endif
-
-#define STANDARD_IO_RESOURCES (sizeof(standard_io_resources)/sizeof(struct resource))
-
 static struct resource code_resource = { "Kernel code", 0x100000, 0 };
 static struct resource data_resource = { "Kernel data", 0, 0 };
-static struct resource vram_resource = { "Video RAM area", 0xa0000, 0xbffff, IORESOURCE_BUSY };
-
-/* System ROM resources */
-#define MAXROMS 6
-static struct resource rom_resources[MAXROMS] = {
-	{ "System ROM", 0xF0000, 0xFFFFF, IORESOURCE_BUSY },
-	{ "Video ROM", 0xc0000, 0xc7fff, IORESOURCE_BUSY }
-};
-
-#define romsignature(x) (*(unsigned short *)(x) == 0xaa55)
-
-static void __init probe_roms(void)
-{
-	int roms = 1;
-	unsigned long base;
-	unsigned char *romstart;
-
-	request_resource(&iomem_resource, rom_resources+0);
-
-	/* Video ROM is standard at C000:0000 - C7FF:0000, check signature */
-	for (base = 0xC0000; base < 0xE0000; base += 2048) {
-		romstart = isa_bus_to_virt(base);
-		if (!romsignature(romstart))
-			continue;
-		request_resource(&iomem_resource, rom_resources + roms);
-		roms++;
-		break;
-	}
-
-	/* Extension roms at C800:0000 - DFFF:0000 */
-	for (base = 0xC8000; base < 0xE0000; base += 2048) {
-		unsigned long length;
-
-		romstart = isa_bus_to_virt(base);
-		if (!romsignature(romstart))
-			continue;
-		length = romstart[2] * 512;
-		if (length) {
-			unsigned int i;
-			unsigned char chksum;
-
-			chksum = 0;
-			for (i = 0; i < length; i++)
-				chksum += romstart[i];
-
-			/* Good checksum? */
-			if (!chksum) {
-				rom_resources[roms].start = base;
-				rom_resources[roms].end = base + length - 1;
-				rom_resources[roms].name = "Extension ROM";
-				rom_resources[roms].flags = IORESOURCE_BUSY;
-
-				request_resource(&iomem_resource, rom_resources + roms);
-				roms++;
-				if (roms >= MAXROMS)
-					return;
-			}
-		}
-	}
-
-	/* Final check for motherboard extension rom at E000:0000 */
-	base = 0xE0000;
-	romstart = isa_bus_to_virt(base);
-
-	if (romsignature(romstart)) {
-		rom_resources[roms].start = base;
-		rom_resources[roms].end = base + 65535;
-		rom_resources[roms].name = "Extension ROM";
-		rom_resources[roms].flags = IORESOURCE_BUSY;
-
-		request_resource(&iomem_resource, rom_resources + roms);
-	}
-}
 
 static void __init limit_regions (unsigned long long size)
 {
@@ -832,11 +744,8 @@
 			request_resource(res, &data_resource);
 		}
 	}
-	request_resource(&iomem_resource, &vram_resource);
 
-	/* request I/O space for devices used on all i[345]86 PCs */
-	for (i = 0; i < STANDARD_IO_RESOURCES; i++)
-		request_resource(&ioport_resource, standard_io_resources+i);
+	mach_request_resource( );
 
 	/* Tell the PCI layer not to allocate too close to the RAM area.. */
 	low_mem_size = ((max_low_pfn << PAGE_SHIFT) + 0xfffff) & ~0xfffff;
@@ -917,6 +826,8 @@
 #ifdef CONFIG_VT
 #if defined(CONFIG_VGA_CONSOLE)
 	conswitchp = &vga_con;
+#elif defined(CONFIG_GDC_CONSOLE)
+	conswitchp = &gdc_con;
 #elif defined(CONFIG_DUMMY_CONSOLE)
 	conswitchp = &dummy_con;
 #endif
diff -Nru linux/include/asm-i386/mach-default/mach_resources.h linux98/include/asm-i386/mach-default/mach_resources.h
--- linux/include/asm-i386/mach-default/mach_resources.h	1970-01-01 09:00:00.000000000 +0900
+++ linux98/include/asm-i386/mach-default/mach_resources.h	2002-10-21 09:59:22.000000000 +0900
@@ -0,0 +1,113 @@
+/*
+ *  include/asm-i386/mach-default/mach_resources.h
+ *
+ *  Machine specific resource allocation for generic.
+ *  Split out from setup.c by Osamu Tomita <tomita@cinet.co.jp>
+ */
+#ifndef _MACH_RESOURCES_H
+#define _MACH_RESOURCES_H
+
+struct resource standard_io_resources[] = {
+	{ "dma1", 0x00, 0x1f, IORESOURCE_BUSY },
+	{ "pic1", 0x20, 0x3f, IORESOURCE_BUSY },
+	{ "timer", 0x40, 0x5f, IORESOURCE_BUSY },
+	{ "keyboard", 0x60, 0x6f, IORESOURCE_BUSY },
+	{ "dma page reg", 0x80, 0x8f, IORESOURCE_BUSY },
+	{ "pic2", 0xa0, 0xbf, IORESOURCE_BUSY },
+	{ "dma2", 0xc0, 0xdf, IORESOURCE_BUSY },
+	{ "fpu", 0xf0, 0xff, IORESOURCE_BUSY }
+};
+#ifdef CONFIG_MELAN
+standard_io_resources[1] = { "pic1", 0x20, 0x21, IORESOURCE_BUSY };
+standard_io_resources[5] = { "pic2", 0xa0, 0xa1, IORESOURCE_BUSY };
+#endif
+
+#define STANDARD_IO_RESOURCES (sizeof(standard_io_resources)/sizeof(struct resource))
+
+static struct resource vram_resource = { "Video RAM area", 0xa0000, 0xbffff, IORESOURCE_BUSY };
+
+/* System ROM resources */
+#define MAXROMS 6
+static struct resource rom_resources[MAXROMS] = {
+	{ "System ROM", 0xF0000, 0xFFFFF, IORESOURCE_BUSY },
+	{ "Video ROM", 0xc0000, 0xc7fff, IORESOURCE_BUSY }
+};
+
+#define romsignature(x) (*(unsigned short *)(x) == 0xaa55)
+
+static inline void probe_roms(void)
+{
+	int roms = 1;
+	unsigned long base;
+	unsigned char *romstart;
+
+	request_resource(&iomem_resource, rom_resources+0);
+
+	/* Video ROM is standard at C000:0000 - C7FF:0000, check signature */
+	for (base = 0xC0000; base < 0xE0000; base += 2048) {
+		romstart = isa_bus_to_virt(base);
+		if (!romsignature(romstart))
+			continue;
+		request_resource(&iomem_resource, rom_resources + roms);
+		roms++;
+		break;
+	}
+
+	/* Extension roms at C800:0000 - DFFF:0000 */
+	for (base = 0xC8000; base < 0xE0000; base += 2048) {
+		unsigned long length;
+
+		romstart = isa_bus_to_virt(base);
+		if (!romsignature(romstart))
+			continue;
+		length = romstart[2] * 512;
+		if (length) {
+			unsigned int i;
+			unsigned char chksum;
+
+			chksum = 0;
+			for (i = 0; i < length; i++)
+				chksum += romstart[i];
+
+			/* Good checksum? */
+			if (!chksum) {
+				rom_resources[roms].start = base;
+				rom_resources[roms].end = base + length - 1;
+				rom_resources[roms].name = "Extension ROM";
+				rom_resources[roms].flags = IORESOURCE_BUSY;
+
+				request_resource(&iomem_resource, rom_resources + roms);
+				roms++;
+				if (roms >= MAXROMS)
+					return;
+			}
+		}
+	}
+
+	/* Final check for motherboard extension rom at E000:0000 */
+	base = 0xE0000;
+	romstart = isa_bus_to_virt(base);
+
+	if (romsignature(romstart)) {
+		rom_resources[roms].start = base;
+		rom_resources[roms].end = base + 65535;
+		rom_resources[roms].name = "Extension ROM";
+		rom_resources[roms].flags = IORESOURCE_BUSY;
+
+		request_resource(&iomem_resource, rom_resources + roms);
+	}
+}
+
+static inline void mach_request_resource(void)
+{
+	int i;
+
+	request_resource(&iomem_resource, &vram_resource);
+
+	/* request I/O space for devices used on all i[345]86 PCs */
+	for (i = 0; i < STANDARD_IO_RESOURCES; i++)
+		request_resource(&ioport_resource, standard_io_resources+i);
+
+}
+
+#endif /* !_MACH_RESOURCES_H */
diff -Nru linux/include/asm-i386/mach-pc9800/mach_resources.h linux98/include/asm-i386/mach-pc9800/mach_resources.h
--- linux/include/asm-i386/mach-pc9800/mach_resources.h	1970-01-01 09:00:00.000000000 +0900
+++ linux98/include/asm-i386/mach-pc9800/mach_resources.h	2002-10-26 17:35:19.000000000 +0900
@@ -0,0 +1,192 @@
+/*
+ *  include/asm-i386/mach-pc9800/mach_resources.h
+ *
+ *  Machine specific resource allocation for PC-9800.
+ *  Written by Osamu Tomita <tomita@cinet.co.jp>
+ */
+#ifndef _MACH_RESOURCES_H
+#define _MACH_RESOURCES_H
+
+static char str_pic1[] = "pic1";
+static char str_dma[] = "dma";
+static char str_pic2[] = "pic2";
+static char str_calender_clock[] = "calender clock";
+static char str_system[] = "system";
+static char str_nmi_control[] = "nmi control";
+static char str_kanji_rom[] = "kanji rom";
+static char str_keyboard[] = "keyboard";
+static char str_text_gdc[] = "text gdc";
+static char str_crtc[] = "crtc";
+static char str_timer[] = "timer";
+static char str_graphic_gdc[] = "graphic gdc";
+static char str_dma_ex_bank[] = "dma ex. bank";
+static char str_beep_freq[] = "beep freq.";
+static char str_mouse_pio[] = "mouse pio";
+struct resource standard_io_resources[] = {
+	{ str_pic1, 0x00, 0x00, IORESOURCE_BUSY },
+	{ str_dma, 0x01, 0x01, IORESOURCE_BUSY },
+	{ str_pic1, 0x02, 0x02, IORESOURCE_BUSY },
+	{ str_dma, 0x03, 0x03, IORESOURCE_BUSY },
+	{ str_dma, 0x05, 0x05, IORESOURCE_BUSY },
+	{ str_dma, 0x07, 0x07, IORESOURCE_BUSY },
+	{ str_pic2, 0x08, 0x08, IORESOURCE_BUSY },
+	{ str_dma, 0x09, 0x09, IORESOURCE_BUSY },
+	{ str_pic2, 0x0a, 0x0a, IORESOURCE_BUSY },
+	{ str_dma, 0x0b, 0x0b, IORESOURCE_BUSY },
+	{ str_dma, 0x0d, 0x0d, IORESOURCE_BUSY },
+	{ str_dma, 0x0f, 0x0f, IORESOURCE_BUSY },
+	{ str_dma, 0x11, 0x11, IORESOURCE_BUSY },
+	{ str_dma, 0x13, 0x13, IORESOURCE_BUSY },
+	{ str_dma, 0x15, 0x15, IORESOURCE_BUSY },
+	{ str_dma, 0x17, 0x17, IORESOURCE_BUSY },
+	{ str_dma, 0x19, 0x19, IORESOURCE_BUSY },
+	{ str_dma, 0x1b, 0x1b, IORESOURCE_BUSY },
+	{ str_dma, 0x1d, 0x1d, IORESOURCE_BUSY },
+	{ str_dma, 0x1f, 0x1f, IORESOURCE_BUSY },
+	{ str_calender_clock, 0x20, 0x20, 0 },
+	{ str_dma, 0x21, 0x21, IORESOURCE_BUSY },
+	{ str_calender_clock, 0x22, 0x22, 0 },
+	{ str_dma, 0x23, 0x23, IORESOURCE_BUSY },
+	{ str_dma, 0x25, 0x25, IORESOURCE_BUSY },
+	{ str_dma, 0x27, 0x27, IORESOURCE_BUSY },
+	{ str_dma, 0x29, 0x29, IORESOURCE_BUSY },
+	{ str_dma, 0x2b, 0x2b, IORESOURCE_BUSY },
+	{ str_dma, 0x2d, 0x2d, IORESOURCE_BUSY },
+	{ str_system, 0x31, 0x31, IORESOURCE_BUSY },
+	{ str_system, 0x33, 0x33, IORESOURCE_BUSY },
+	{ str_system, 0x35, 0x35, IORESOURCE_BUSY },
+	{ str_system, 0x37, 0x37, IORESOURCE_BUSY },
+	{ str_nmi_control, 0x50, 0x50, IORESOURCE_BUSY },
+	{ str_nmi_control, 0x52, 0x52, IORESOURCE_BUSY },
+	{ "time stamp", 0x5c, 0x5f, IORESOURCE_BUSY },
+	{ str_kanji_rom, 0xa1, 0xa1, IORESOURCE_BUSY },
+	{ str_kanji_rom, 0xa3, 0xa3, IORESOURCE_BUSY },
+	{ str_kanji_rom, 0xa5, 0xa5, IORESOURCE_BUSY },
+	{ str_kanji_rom, 0xa7, 0xa7, IORESOURCE_BUSY },
+	{ str_kanji_rom, 0xa9, 0xa9, IORESOURCE_BUSY },
+	{ str_keyboard, 0x41, 0x41, IORESOURCE_BUSY },
+	{ str_keyboard, 0x43, 0x43, IORESOURCE_BUSY },
+	{ str_text_gdc, 0x60, 0x60, IORESOURCE_BUSY },
+	{ str_text_gdc, 0x62, 0x62, IORESOURCE_BUSY },
+	{ str_text_gdc, 0x64, 0x64, IORESOURCE_BUSY },
+	{ str_text_gdc, 0x66, 0x66, IORESOURCE_BUSY },
+	{ str_text_gdc, 0x68, 0x68, IORESOURCE_BUSY },
+	{ str_text_gdc, 0x6a, 0x6a, IORESOURCE_BUSY },
+	{ str_text_gdc, 0x6c, 0x6c, IORESOURCE_BUSY },
+	{ str_text_gdc, 0x6e, 0x6e, IORESOURCE_BUSY },
+	{ str_crtc, 0x70, 0x70, IORESOURCE_BUSY },
+	{ str_crtc, 0x72, 0x72, IORESOURCE_BUSY },
+	{ str_crtc, 0x74, 0x74, IORESOURCE_BUSY },
+	{ str_crtc, 0x74, 0x74, IORESOURCE_BUSY },
+	{ str_crtc, 0x76, 0x76, IORESOURCE_BUSY },
+	{ str_crtc, 0x78, 0x78, IORESOURCE_BUSY },
+	{ str_crtc, 0x7a, 0x7a, IORESOURCE_BUSY },
+	{ str_timer, 0x71, 0x71, IORESOURCE_BUSY },
+	{ str_timer, 0x73, 0x73, IORESOURCE_BUSY },
+	{ str_timer, 0x75, 0x75, IORESOURCE_BUSY },
+	{ str_timer, 0x77, 0x77, IORESOURCE_BUSY },
+	{ str_graphic_gdc, 0xa0, 0xa0, IORESOURCE_BUSY },
+	{ str_graphic_gdc, 0xa2, 0xa2, IORESOURCE_BUSY },
+	{ str_graphic_gdc, 0xa4, 0xa4, IORESOURCE_BUSY },
+	{ str_graphic_gdc, 0xa6, 0xa6, IORESOURCE_BUSY },
+	{ "cpu", 0xf0, 0xf7, IORESOURCE_BUSY },
+	{ "fpu", 0xf8, 0xff, IORESOURCE_BUSY },
+	{ str_dma_ex_bank, 0x0e05, 0x0e05, 0 },
+	{ str_dma_ex_bank, 0x0e07, 0x0e07, 0 },
+	{ str_dma_ex_bank, 0x0e09, 0x0e09, 0 },
+	{ str_dma_ex_bank, 0x0e0b, 0x0e0b, 0 },
+	{ str_beep_freq, 0x3fd9, 0x3fd9, IORESOURCE_BUSY },
+	{ str_beep_freq, 0x3fdb, 0x3fdb, IORESOURCE_BUSY },
+	{ str_beep_freq, 0x3fdd, 0x3fdd, IORESOURCE_BUSY },
+	{ str_beep_freq, 0x3fdf, 0x3fdf, IORESOURCE_BUSY },
+	/* All PC-9800 have (exactly) one mouse interface.  */
+	{ str_mouse_pio, 0x7fd9, 0x7fd9, 0 },
+	{ str_mouse_pio, 0x7fdb, 0x7fdb, 0 },
+	{ str_mouse_pio, 0x7fdd, 0x7fdd, 0 },
+	{ str_mouse_pio, 0x7fdf, 0x7fdf, 0 },
+	{ "mouse timer", 0xbfdb, 0xbfdb, 0 },
+	{ "mouse irq", 0x98d7, 0x98d7, 0 },
+};
+
+#define STANDARD_IO_RESOURCES (sizeof(standard_io_resources)/sizeof(struct resource))
+
+static struct resource tvram_resource = { "Text VRAM/CG window", 0xa0000, 0xa4fff, IORESOURCE_BUSY };
+static struct resource gvram_brg_resource = { "Graphic VRAM (B/R/G)", 0xa8000, 0xbffff, IORESOURCE_BUSY };
+static struct resource gvram_e_resource = { "Graphic VRAM (E)", 0xe0000, 0xe7fff, IORESOURCE_BUSY };
+
+/* System ROM resources */
+#define MAXROMS 6
+static struct resource rom_resources[MAXROMS] = {
+	{ "System ROM", 0xe8000, 0xfffff, IORESOURCE_BUSY }
+};
+
+static inline void probe_roms(void)
+{
+	int roms = 1;
+	int i;
+	__u8 *xrom_id;
+
+	request_resource(&iomem_resource, rom_resources+0);
+
+	xrom_id = (__u8 *) isa_bus_to_virt(PC9800SCA_XROM_ID + 0x10);
+
+	for (i = 0; i < 16; i++) {
+		if (xrom_id[i] & 0x80) {
+			int j;
+
+			for (j = i + 1; j < 16 && (xrom_id[j] & 0x80); j++)
+				;
+			rom_resources[roms].start = 0x0d0000 + i * 0x001000;
+			rom_resources[roms].end = 0x0d0000 + j * 0x001000 - 1;
+			rom_resources[roms].name = "Extension ROM";
+			rom_resources[roms].flags = IORESOURCE_BUSY;
+
+			request_resource(&iomem_resource,
+					  rom_resources + roms);
+			if (++roms >= MAXROMS)
+				return;
+		}
+	}
+}
+
+static inline void mach_request_resource(void)
+{
+	int i;
+
+	if (PC9800_HIGHRESO_P()) {
+		tvram_resource.start = 0xe0000;
+		tvram_resource.end   = 0xe4fff;
+		gvram_brg_resource.name  = "Graphic VRAM";
+		gvram_brg_resource.start = 0xc0000;
+		gvram_brg_resource.end   = 0xdffff;
+	}
+
+	request_resource(&iomem_resource, &tvram_resource);
+	request_resource(&iomem_resource, &gvram_brg_resource);
+	if (!PC9800_HIGHRESO_P())
+		request_resource(&iomem_resource, &gvram_e_resource);
+
+	for (i = 0; i < STANDARD_IO_RESOURCES; i++)
+		request_resource(&ioport_resource, standard_io_resources + i);
+
+	if (PC9800_HIGHRESO_P() || PC9800_9821_P()) {
+		static char graphics[] = "graphics";
+		static struct resource graphics_resources[] = {
+			{ graphics, 0x9a0, 0x9a0, 0 },
+			{ graphics, 0x9a2, 0x9a2, 0 },
+			{ graphics, 0x9a4, 0x9a4, 0 },
+			{ graphics, 0x9a6, 0x9a6, 0 },
+			{ graphics, 0x9a8, 0x9a8, 0 },
+			{ graphics, 0x9aa, 0x9aa, 0 },
+			{ graphics, 0x9ac, 0x9ac, 0 },
+			{ graphics, 0x9ae, 0x9ae, 0 },
+		};
+
+#define GRAPHICS_RESOURCES (sizeof(graphics_resources)/sizeof(struct resource))
+
+		for (i = 0; i < GRAPHICS_RESOURCES; i++)
+			request_resource(&ioport_resource, graphics_resources + i);
+	}
+}
+
+#endif /* !_MACH_RESOURCES_H */

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH] PC-9800 additional for 2.5.61-ac1 (19/21) SMP
  2003-02-20 12:16 [PATCH] PC-9800 additional for 2.5.61-ac1 (0/21) summary Osamu Tomita
                   ` (16 preceding siblings ...)
  2003-02-20 12:37 ` [PATCH] PC-9800 additional for 2.5.61-ac1 (18/21) setup Osamu Tomita
@ 2003-02-20 12:38 ` Osamu Tomita
  2003-02-20 12:38 ` [PATCH] PC-9800 additional for 2.5.61-ac1 (20/21) timer Osamu Tomita
  2003-02-20 12:39 ` [PATCH] PC-9800 additional for 2.5.61-ac1 (21/21) traps Osamu Tomita
  19 siblings, 0 replies; 21+ messages in thread
From: Osamu Tomita @ 2003-02-20 12:38 UTC (permalink / raw)
  To: Linux Kernel Mailing List; +Cc: Alan Cox

This is additional patch to support NEC PC-9800 subarchitecture
against 2.5.61-ac1. (19/21)

SMP support for PC98.

diff -Nru linux-2.5.61-ac1/arch/i386/kernel/mpparse.c linux98-2.5.61-ac1/arch/i386/kernel/mpparse.c
--- linux-2.5.61-ac1/arch/i386/kernel/mpparse.c	2003-02-18 08:58:20.000000000 +0900
+++ linux98-2.5.61-ac1/arch/i386/kernel/mpparse.c	2003-02-18 15:52:44.000000000 +0900
@@ -33,6 +33,7 @@
 
 #include <mach_apic.h>
 #include <mach_mpparse.h>
+#include <bios_ebda.h>
 
 /* Have we found an MP table */
 int smp_found_config;
@@ -654,7 +655,8 @@
 		 * Read the physical hardware table.  Anything here will
 		 * override the defaults.
 		 */
-		if (!smp_read_mpc((void *)mpf->mpf_physptr)) {
+		if (!smp_read_mpc(pc98 ? phys_to_virt(mpf->mpf_physptr)
+					: (void *)mpf->mpf_physptr)) {
 			smp_found_config = 0;
 			printk(KERN_ERR "BIOS bug, MP table errors detected!...\n");
 			printk(KERN_ERR "... disabling SMP support. (tell your hw vendor)\n");
@@ -708,8 +710,23 @@
 			printk(KERN_INFO "found SMP MP-table at %08lx\n",
 						virt_to_phys(mpf));
 			reserve_bootmem(virt_to_phys(mpf), PAGE_SIZE);
-			if (mpf->mpf_physptr)
-				reserve_bootmem(mpf->mpf_physptr, PAGE_SIZE);
+			if (mpf->mpf_physptr) {
+				/*
+				 * We cannot access to MPC table to compute
+				 * table size yet, as only few megabytes from
+				 * the bottom is mapped now.
+				 * PC-9800's MPC table places on the very last
+				 * of physical memory; so that simply reserving
+				 * PAGE_SIZE from mpg->mpf_physptr yields BUG()
+				 * in reserve_bootmem.
+				 */
+				unsigned long size = PAGE_SIZE;
+				unsigned long end = max_low_pfn * PAGE_SIZE;
+				if (mpf->mpf_physptr + size > end)
+					size = end - mpf->mpf_physptr;
+				reserve_bootmem(mpf->mpf_physptr, size);
+			}
+
 			mpf_found = mpf;
 			return 1;
 		}
@@ -752,9 +769,9 @@
 	 * MP1.4 SPEC states to only scan first 1K of 4K EBDA.
 	 */
 
-	address = *(unsigned short *)phys_to_virt(0x40E);
-	address <<= 4;
-	smp_scan_config(address, 0x400);
+	address = get_bios_ebda();
+	if (address)
+		smp_scan_config(address, 0x400);
 }
 
 
diff -Nru linux-2.5.61/arch/i386/kernel/smpboot.c linux98-2.5.61/arch/i386/kernel/smpboot.c
--- linux-2.5.61/arch/i386/kernel/smpboot.c	2003-02-15 08:51:44.000000000 +0900
+++ linux98-2.5.61/arch/i386/kernel/smpboot.c	2003-02-15 15:04:28.000000000 +0900
@@ -823,13 +823,27 @@
 
 	store_NMI_vector(&nmi_high, &nmi_low);
 
+#ifndef CONFIG_X86_PC9800
 	CMOS_WRITE(0xa, 0xf);
+#else
+	/* reset code is stored in 8255 on PC-9800. */
+	outb(0x0e, 0x37);	/* SHUT0 = 0 */
+#endif
 	local_flush_tlb();
 	Dprintk("1.\n");
 	*((volatile unsigned short *) TRAMPOLINE_HIGH) = start_eip >> 4;
 	Dprintk("2.\n");
 	*((volatile unsigned short *) TRAMPOLINE_LOW) = start_eip & 0xf;
 	Dprintk("3.\n");
+#ifdef CONFIG_X86_PC9800
+	/*
+	 * On PC-9800, continuation on warm reset is done by loading
+	 * %ss:%sp from 0x0000:0404 and executing 'lret', so:
+	 */
+	/* 0x3f0 is on unused interrupt vector and should be safe... */
+	*((volatile unsigned long *) phys_to_virt(0x404)) = 0x000003f0;
+	Dprintk("4.\n");
+#endif
 
 	/*
 	 * Starting actual IPI sequence...
diff -Nru linux/include/asm-i386/mach-default/bios_ebda.h linux98/include/asm-i386/mach-default/bios_ebda.h
--- linux/include/asm-i386/mach-default/bios_ebda.h	1970-01-01 09:00:00.000000000 +0900
+++ linux98/include/asm-i386/mach-default/bios_ebda.h	2002-12-18 22:40:38.000000000 +0900
@@ -0,0 +1,15 @@
+#ifndef _MACH_BIOS_EBDA_H
+#define _MACH_BIOS_EBDA_H
+
+/*
+ * there is a real-mode segmented pointer pointing to the
+ * 4K EBDA area at 0x40E.
+ */
+static inline unsigned int get_bios_ebda(void)
+{
+	unsigned int address = *(unsigned short *)phys_to_virt(0x40E);
+	address <<= 4;
+	return address;	/* 0 means none */
+}
+
+#endif /* _MACH_BIOS_EBDA_H */
diff -Nru linux/include/asm-i386/mach-pc9800/bios_ebda.h linux98/include/asm-i386/mach-pc9800/bios_ebda.h
--- linux/include/asm-i386/mach-pc9800/bios_ebda.h	1970-01-01 09:00:00.000000000 +0900
+++ linux98/include/asm-i386/mach-pc9800/bios_ebda.h	2002-12-18 22:49:59.000000000 +0900
@@ -0,0 +1,14 @@
+#ifndef _MACH_BIOS_EBDA_H
+#define _MACH_BIOS_EBDA_H
+
+/*
+ * PC-9800 has no EBDA.
+ * Its BIOS uses 0x40E for other purpose,
+ * Not pointer to 4K EBDA area.
+ */
+static inline unsigned int get_bios_ebda(void)
+{
+	return 0;	/* 0 means none */
+}
+
+#endif /* _MACH_BIOS_EBDA_H */
diff -Nru linux/include/asm-i386/mach-pc9800/mach_wakecpu.h linux98/include/asm-i386/mach-pc9800/mach_wakecpu.h
--- linux/include/asm-i386/mach-pc9800/mach_wakecpu.h	1970-01-01 09:00:00.000000000 +0900
+++ linux98/include/asm-i386/mach-pc9800/mach_wakecpu.h	2003-01-10 11:40:16.000000000 +0900
@@ -0,0 +1,45 @@
+#ifndef __ASM_MACH_WAKECPU_H
+#define __ASM_MACH_WAKECPU_H
+
+/* 
+ * This file copes with machines that wakeup secondary CPUs by the
+ * INIT, INIT, STARTUP sequence.
+ */
+
+#define WAKE_SECONDARY_VIA_INIT
+
+/*
+ * On PC-9800, continuation on warm reset is done by loading
+ * %ss:%sp from 0x0000:0404 and executing 'lret', so:
+ */
+#define TRAMPOLINE_LOW phys_to_virt(0x4fa)
+#define TRAMPOLINE_HIGH phys_to_virt(0x4fc)
+
+#define boot_cpu_apicid boot_cpu_physical_apicid
+
+static inline void wait_for_init_deassert(atomic_t *deassert)
+{
+	while (!atomic_read(deassert));
+	return;
+}
+
+/* Nothing to do for most platforms, since cleared by the INIT cycle */
+static inline void smp_callin_clear_local_apic(void)
+{
+}
+
+static inline void store_NMI_vector(unsigned short *high, unsigned short *low)
+{
+}
+
+static inline void restore_NMI_vector(unsigned short *high, unsigned short *low)
+{
+}
+
+#if APIC_DEBUG
+ #define inquire_remote_apic(apicid) __inquire_remote_apic(apicid)
+#else
+ #define inquire_remote_apic(apicid) {}
+#endif
+
+#endif /* __ASM_MACH_WAKECPU_H */
diff -Nru linux/include/asm-i386/mach-pc9800/smpboot_hooks.h linux98/include/asm-i386/mach-pc9800/smpboot_hooks.h
--- linux/include/asm-i386/mach-pc9800/smpboot_hooks.h	1970-01-01 09:00:00.000000000 +0900
+++ linux98/include/asm-i386/mach-pc9800/smpboot_hooks.h	2002-09-22 06:56:46.000000000 +0900
@@ -0,0 +1,33 @@
+/* two abstractions specific to kernel/smpboot.c, mainly to cater to visws
+ * which needs to alter them. */
+
+static inline void smpboot_clear_io_apic_irqs(void)
+{
+	io_apic_irqs = 0;
+}
+
+static inline void smpboot_setup_warm_reset_vector(void)
+{
+	/*
+	 * Install writable page 0 entry to set BIOS data area.
+	 */
+	local_flush_tlb();
+
+	/*
+	 * Paranoid:  Set warm reset code and vector here back
+	 * to default values.
+	 */
+	outb(0x0f, 0x37);	/* SHUT0 = 1 */
+
+	*((volatile long *) phys_to_virt(0x404)) = 0;
+}
+
+static inline void smpboot_setup_io_apic(void)
+{
+	/*
+	 * Here we can be sure that there is an IO-APIC in the system. Let's
+	 * go and set it up:
+	 */
+	if (!skip_ioapic_setup && nr_ioapics)
+		setup_IO_APIC();
+}

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH] PC-9800 additional for 2.5.61-ac1 (20/21) timer
  2003-02-20 12:16 [PATCH] PC-9800 additional for 2.5.61-ac1 (0/21) summary Osamu Tomita
                   ` (17 preceding siblings ...)
  2003-02-20 12:38 ` [PATCH] PC-9800 additional for 2.5.61-ac1 (19/21) SMP Osamu Tomita
@ 2003-02-20 12:38 ` Osamu Tomita
  2003-02-20 12:39 ` [PATCH] PC-9800 additional for 2.5.61-ac1 (21/21) traps Osamu Tomita
  19 siblings, 0 replies; 21+ messages in thread
From: Osamu Tomita @ 2003-02-20 12:38 UTC (permalink / raw)
  To: Linux Kernel Mailing List; +Cc: Alan Cox

This is additional patch to support NEC PC-9800 subarchitecture
against 2.5.61-ac1. (20/21)

Support difference of timer, using mach-* scheme.

diff -Nru linux-2.5.60/arch/i386/kernel/timers/timer_pit.c linux98-2.5.60/arch/i386/kernel/timers/timer_pit.c
--- linux-2.5.60/arch/i386/kernel/timers/timer_pit.c	2003-02-11 03:38:51.000000000 +0900
+++ linux98-2.5.60/arch/i386/kernel/timers/timer_pit.c	2003-02-11 11:15:22.000000000 +0900
@@ -16,6 +16,7 @@
 extern spinlock_t i8259A_lock;
 extern spinlock_t i8253_lock;
 #include "do_timer.h"
+#include "io_ports.h"
 
 static int init_pit(void)
 {
@@ -77,7 +78,8 @@
 {
 	int count;
 	unsigned long flags;
-	static int count_p = LATCH;    /* for the first call after boot */
+	static int count_p;
+	static int is_1st_boot = 1;    /* for the first call after boot */
 	static unsigned long jiffies_p = 0;
 
 	/*
@@ -85,11 +87,17 @@
 	 */
 	unsigned long jiffies_t;
 
+	/* for support LATCH is not constant */
+	if (is_1st_boot) {
+		is_1st_boot = 0;
+		count_p = LATCH;
+	}
+
 	spin_lock_irqsave(&i8253_lock, flags);
 	/* timer count may underflow right here */
-	outb_p(0x00, 0x43);	/* latch the count ASAP */
+	outb_p(0x00, PIT_MODE);	/* latch the count ASAP */
 
-	count = inb_p(0x40);	/* read the latched count */
+	count = inb_p(PIT_CH0);	/* read the latched count */
 
 	/*
 	 * We do this guaranteed double memory access instead of a _p 
@@ -97,13 +105,13 @@
 	 */
  	jiffies_t = jiffies;
 
-	count |= inb_p(0x40) << 8;
+	count |= inb_p(PIT_CH0) << 8;
 	
         /* VIA686a test code... reset the latch if count > max + 1 */
         if (count > LATCH) {
-                outb_p(0x34, 0x43);
-                outb_p(LATCH & 0xff, 0x40);
-                outb(LATCH >> 8, 0x40);
+                outb_p(0x34, PIT_MODE);
+                outb_p(LATCH & 0xff, PIT_CH0);
+                outb(LATCH >> 8, PIT_CH0);
                 count = LATCH - 1;
         }
 	
diff -Nru linux-2.5.61/arch/i386/kernel/timers/timer_tsc.c linux98-2.5.61/arch/i386/kernel/timers/timer_tsc.c
--- linux-2.5.61/arch/i386/kernel/timers/timer_tsc.c	2003-02-15 08:52:04.000000000 +0900
+++ linux98-2.5.61/arch/i386/kernel/timers/timer_tsc.c	2003-02-15 14:13:41.000000000 +0900
@@ -14,6 +14,9 @@
 /* processor.h for distable_tsc flag */
 #include <asm/processor.h>
 
+#include "io_ports.h"
+#include "calibrate_tsc.h"
+
 int tsc_disable __initdata = 0;
 
 extern spinlock_t i8253_lock;
@@ -22,8 +25,6 @@
 /* Number of usecs that the last interrupt was delayed */
 static int delay_at_last_interrupt;
 
-static unsigned long last_tsc_low; /* lsb 32 bits of Time Stamp Counter */
-
 /* Cached *multiplier* to convert TSC counts to microseconds.
  * (see the equation below).
  * Equal to 2^32 * (1 / (clocks per usec) ).
@@ -64,7 +65,12 @@
 {
 	int count;
 	int countmp;
-	static int count1=0, count2=LATCH;
+	static int count1=0, count2, initialize = 1;
+
+	if (initialize) {
+		count2 = LATCH;
+		initialize = 0;
+	}
 	/*
 	 * It is important that these two operations happen almost at
 	 * the same time. We do the RDTSC stuff first, since it's
@@ -82,10 +88,10 @@
 	rdtscl(last_tsc_low);
 
 	spin_lock(&i8253_lock);
-	outb_p(0x00, 0x43);     /* latch the count ASAP */
+	outb_p(0x00, PIT_MODE);     /* latch the count ASAP */
 
-	count = inb_p(0x40);    /* read the latched count */
-	count |= inb(0x40) << 8;
+	count = inb_p(PIT_CH0);    /* read the latched count */
+	count |= inb(PIT_CH0) << 8;
 	spin_unlock(&i8253_lock);
 
 	if (pit_latch_buggy) {
@@ -118,83 +124,9 @@
 	} while ((now-bclock) < loops);
 }
 
-/* ------ Calibrate the TSC ------- 
- * Return 2^32 * (1 / (TSC clocks per usec)) for do_fast_gettimeoffset().
- * Too much 64-bit arithmetic here to do this cleanly in C, and for
- * accuracy's sake we want to keep the overhead on the CTC speaker (channel 2)
- * output busy loop as low as possible. We avoid reading the CTC registers
- * directly because of the awkward 8-bit access mechanism of the 82C54
- * device.
- */
-
-#define CALIBRATE_LATCH	(5 * LATCH)
-#define CALIBRATE_TIME	(5 * 1000020/HZ)
-
 unsigned long __init calibrate_tsc(void)
 {
-       /* Set the Gate high, disable speaker */
-	outb((inb(0x61) & ~0x02) | 0x01, 0x61);
-
-	/*
-	 * Now let's take care of CTC channel 2
-	 *
-	 * Set the Gate high, program CTC channel 2 for mode 0,
-	 * (interrupt on terminal count mode), binary count,
-	 * load 5 * LATCH count, (LSB and MSB) to begin countdown.
-	 *
-	 * Some devices need a delay here.
-	 */
-	outb(0xb0, 0x43);			/* binary, mode 0, LSB/MSB, Ch 2 */
-	outb_p(CALIBRATE_LATCH & 0xff, 0x42);	/* LSB of count */
-	outb_p(CALIBRATE_LATCH >> 8, 0x42);       /* MSB of count */
-
-	{
-		unsigned long startlow, starthigh;
-		unsigned long endlow, endhigh;
-		unsigned long count;
-
-		rdtsc(startlow,starthigh);
-		count = 0;
-		do {
-			count++;
-		} while ((inb(0x61) & 0x20) == 0);
-		rdtsc(endlow,endhigh);
-
-		last_tsc_low = endlow;
-
-		/* Error: ECTCNEVERSET */
-		if (count <= 1)
-			goto bad_ctc;
-
-		/* 64-bit subtract - gcc just messes up with long longs */
-		__asm__("subl %2,%0\n\t"
-			"sbbl %3,%1"
-			:"=a" (endlow), "=d" (endhigh)
-			:"g" (startlow), "g" (starthigh),
-			 "0" (endlow), "1" (endhigh));
-
-		/* Error: ECPUTOOFAST */
-		if (endhigh)
-			goto bad_ctc;
-
-		/* Error: ECPUTOOSLOW */
-		if (endlow <= CALIBRATE_TIME)
-			goto bad_ctc;
-
-		__asm__("divl %2"
-			:"=a" (endlow), "=d" (endhigh)
-			:"r" (endlow), "0" (0), "1" (CALIBRATE_TIME));
-
-		return endlow;
-	}
-
-	/*
-	 * The CTC wasn't reliable: we got a hit on the very first read,
-	 * or the CPU was so fast/slow that the quotient wouldn't fit in
-	 * 32 bits..
-	 */
-bad_ctc:
-	return 0;
+	return mach_calibrate_tsc();
 }
 
 
diff -Nru linux/include/asm-i386/mach-default/calibrate_tsc.h linux98/include/asm-i386/mach-default/calibrate_tsc.h
--- linux/include/asm-i386/mach-default/calibrate_tsc.h	1970-01-01 09:00:00.000000000 +0900
+++ linux98/include/asm-i386/mach-default/calibrate_tsc.h	2002-11-05 22:15:11.000000000 +0900
@@ -0,0 +1,90 @@
+/*
+ *  include/asm-i386/mach-default/calibrate_tsc.h
+ *
+ *  Machine specific calibrate_tsc() for generic.
+ *  Split out from timer_tsc.c by Osamu Tomita <tomita@cinet.co.jp>
+ */
+/* ------ Calibrate the TSC ------- 
+ * Return 2^32 * (1 / (TSC clocks per usec)) for do_fast_gettimeoffset().
+ * Too much 64-bit arithmetic here to do this cleanly in C, and for
+ * accuracy's sake we want to keep the overhead on the CTC speaker (channel 2)
+ * output busy loop as low as possible. We avoid reading the CTC registers
+ * directly because of the awkward 8-bit access mechanism of the 82C54
+ * device.
+ */
+#ifndef _MACH_CALIBRATE_TSC_H
+#define _MACH_CALIBRATE_TSC_H
+
+#define CALIBRATE_LATCH	(5 * LATCH)
+#define CALIBRATE_TIME	(5 * 1000020/HZ)
+
+static unsigned long last_tsc_low; /* lsb 32 bits of Time Stamp Counter */
+
+static inline unsigned long mach_calibrate_tsc(void)
+{
+       /* Set the Gate high, disable speaker */
+	outb((inb(0x61) & ~0x02) | 0x01, 0x61);
+
+	/*
+	 * Now let's take care of CTC channel 2
+	 *
+	 * Set the Gate high, program CTC channel 2 for mode 0,
+	 * (interrupt on terminal count mode), binary count,
+	 * load 5 * LATCH count, (LSB and MSB) to begin countdown.
+	 *
+	 * Some devices need a delay here.
+	 */
+	outb(0xb0, PIT_MODE);			/* binary, mode 0, LSB/MSB, Ch 2 */
+	outb(CALIBRATE_LATCH & 0xff, PIT_CH2);	/* LSB of count */
+	outb(CALIBRATE_LATCH >> 8, PIT_CH2);	/* MSB of count */
+
+	{
+		unsigned long startlow, starthigh;
+		unsigned long endlow, endhigh;
+		unsigned long count;
+
+		rdtsc(startlow,starthigh);
+		count = 0;
+		do {
+			count++;
+		} while ((inb(0x61) & 0x20) == 0);
+		rdtsc(endlow,endhigh);
+
+		last_tsc_low = endlow;
+
+		/* Error: ECTCNEVERSET */
+		if (count <= 1)
+			goto bad_ctc;
+
+		/* 64-bit subtract - gcc just messes up with long longs */
+		__asm__("subl %2,%0\n\t"
+			"sbbl %3,%1"
+			:"=a" (endlow), "=d" (endhigh)
+			:"g" (startlow), "g" (starthigh),
+			 "0" (endlow), "1" (endhigh));
+
+		/* Error: ECPUTOOFAST */
+		if (endhigh)
+			goto bad_ctc;
+
+		/* Error: ECPUTOOSLOW */
+		if (endlow <= CALIBRATE_TIME)
+			goto bad_ctc;
+
+		__asm__("divl %2"
+			:"=a" (endlow), "=d" (endhigh)
+			:"r" (endlow), "0" (0), "1" (CALIBRATE_TIME));
+
+		return endlow;
+	}
+
+	/*
+	 * The CTC wasn't reliable: we got a hit on the very first read,
+	 * or the CPU was so fast/slow that the quotient wouldn't fit in
+	 * 32 bits..
+	 */
+bad_ctc:
+	return 0;
+}
+
+#endif /* !_MACH_CALIBRATE_TSC_H */
diff -Nru linux/include/asm-i386/mach-pc9800/do_timer.h linux98/include/asm-i386/mach-pc9800/do_timer.h
--- linux/include/asm-i386/mach-pc9800/do_timer.h	1970-01-01 09:00:00.000000000 +0900
+++ linux98/include/asm-i386/mach-pc9800/do_timer.h	2002-10-16 13:20:29.000000000 +0900
@@ -0,0 +1,80 @@
+/* defines for inline arch setup functions */
+
+/**
+ * do_timer_interrupt_hook - hook into timer tick
+ * @regs:	standard registers from interrupt
+ *
+ * Description:
+ *	This hook is called immediately after the timer interrupt is ack'd.
+ *	It's primary purpose is to allow architectures that don't possess
+ *	individual per CPU clocks (like the CPU APICs supply) to broadcast the
+ *	timer interrupt as a means of triggering reschedules etc.
+ **/
+
+static inline void do_timer_interrupt_hook(struct pt_regs *regs)
+{
+	do_timer(regs);
+/*
+ * In the SMP case we use the local APIC timer interrupt to do the
+ * profiling, except when we simulate SMP mode on a uniprocessor
+ * system, in that case we have to call the local interrupt handler.
+ */
+#ifndef CONFIG_X86_LOCAL_APIC
+	x86_do_profile(regs);
+#else
+	if (!using_apic_timer)
+		smp_local_timer_interrupt(regs);
+#endif
+}
+
+
+/* you can safely undefine this if you don't have the Neptune chipset */
+
+#define BUGGY_NEPTUN_TIMER
+
+/**
+ * do_timer_overflow - process a detected timer overflow condition
+ * @count:	hardware timer interrupt count on overflow
+ *
+ * Description:
+ *	This call is invoked when the jiffies count has not incremented but
+ *	the hardware timer interrupt has.  It means that a timer tick interrupt
+ *	came along while the previous one was pending, thus a tick was missed
+ **/
+static inline int do_timer_overflow(int count)
+{
+	int i;
+
+	spin_lock(&i8259A_lock);
+	/*
+	 * This is tricky when I/O APICs are used;
+	 * see do_timer_interrupt().
+	 */
+	i = inb(0x00);
+	spin_unlock(&i8259A_lock);
+	
+	/* assumption about timer being IRQ0 */
+	if (i & 0x01) {
+		/*
+		 * We cannot detect lost timer interrupts ... 
+		 * well, that's why we call them lost, don't we? :)
+		 * [hmm, on the Pentium and Alpha we can ... sort of]
+		 */
+		count -= LATCH;
+	} else {
+#ifdef BUGGY_NEPTUN_TIMER
+		/*
+		 * for the Neptun bug we know that the 'latch'
+		 * command doesnt latch the high and low value
+		 * of the counter atomically. Thus we have to 
+		 * substract 256 from the counter 
+		 * ... funny, isnt it? :)
+		 */
+		
+		count -= 256;
+#else
+		printk("do_slow_gettimeoffset(): hardware timer problem?\n");
+#endif
+	}
+	return count;
+}
diff -Nru linux/include/asm-i386/mach-pc9800/calibrate_tsc.h linux98/include/asm-i386/mach-pc9800/calibrate_tsc.h
--- linux/include/asm-i386/mach-pc9800/calibrate_tsc.h	1970-01-01 09:00:00.000000000 +0900
+++ linux98/include/asm-i386/mach-pc9800/calibrate_tsc.h	2002-11-05 22:19:50.000000000 +0900
@@ -0,0 +1,71 @@
+/*
+ *  include/asm-i386/mach-pc9800/calibrate_tsc.h
+ *
+ *  Machine specific calibrate_tsc() for PC-9800.
+ *  Written by Osamu Tomita <tomita@cinet.co.jp>
+ */
+
+/* ------ Calibrate the TSC ------- 
+ * Return 2^32 * (1 / (TSC clocks per usec)) for do_fast_gettimeoffset().
+ * Too much 64-bit arithmetic here to do this cleanly in C.
+ * PC-9800:
+ *  CTC cannot be used because some models (especially
+ *  note-machines) may disable clock to speaker channel (#1)
+ *  unless speaker is enabled.  We use ARTIC instead.
+ */
+#ifndef _MACH_CALIBRATE_TSC_H
+#define _MACH_CALIBRATE_TSC_H
+
+#define CALIBRATE_LATCH	(5 * 307200/HZ) /* 0.050sec * 307200Hz = 15360 */
+#define CALIBRATE_TIME	(5 * 1000020/HZ)
+
+static unsigned long last_tsc_low; /* lsb 32 bits of Time Stamp Counter */
+
+static inline unsigned long mach_calibrate_tsc(void)
+{
+
+	unsigned long startlow, starthigh;
+	unsigned long endlow, endhigh;
+	unsigned short count;
+
+	for (count = inw(0x5c); inw(0x5c) == count; )
+		;
+	rdtsc(startlow,starthigh);
+	count = inw(0x5c);
+	while ((unsigned short)(inw(0x5c) - count) < CALIBRATE_LATCH)
+		;
+	rdtsc(endlow,endhigh);
+
+	last_tsc_low = endlow;
+
+	/* 64-bit subtract - gcc just messes up with long longs */
+	__asm__("subl %2,%0\n\t"
+		"sbbl %3,%1"
+		:"=a" (endlow), "=d" (endhigh)
+		:"g" (startlow), "g" (starthigh),
+		 "0" (endlow), "1" (endhigh));
+
+	/* Error: ECPUTOOFAST */
+	if (endhigh)
+		goto bad_ctc;
+
+	/* Error: ECPUTOOSLOW */
+	if (endlow <= CALIBRATE_TIME)
+		goto bad_ctc;
+
+	__asm__("divl %2"
+		:"=a" (endlow), "=d" (endhigh)
+		:"r" (endlow), "0" (0), "1" (CALIBRATE_TIME));
+
+	return endlow;
+
+	/*
+ 	* The CTC wasn't reliable: we got a hit on the very first read,
+ 	* or the CPU was so fast/slow that the quotient wouldn't fit in
+ 	* 32 bits..
+ 	*/
+bad_ctc:
+	return 0;
+}
+
+#endif /* !_MACH_CALIBRATE_TSC_H */
diff -Nru linux/include/asm-i386/timex.h linux98/include/asm-i386/timex.h
--- linux/include/asm-i386/timex.h	2002-02-14 18:09:15.000000000 +0900
+++ linux98/include/asm-i386/timex.h	2002-02-14 23:58:57.000000000 +0900
@@ -9,11 +9,15 @@
 #include <linux/config.h>
 #include <asm/msr.h>
 
+#ifdef CONFIG_X86_PC9800
+   extern int CLOCK_TICK_RATE;
+#else
 #ifdef CONFIG_MELAN
 #  define CLOCK_TICK_RATE 1189200 /* AMD Elan has different frequency! */
 #else
 #  define CLOCK_TICK_RATE 1193180 /* Underlying HZ */
 #endif
+#endif
 
 #define CLOCK_TICK_FACTOR	20	/* Factor of both 1000000 and CLOCK_TICK_RATE */
 #define FINETUNE ((((((long)LATCH * HZ - CLOCK_TICK_RATE) << SHIFT_HZ) * \
This is patchset to support NEC PC-9800 subarchitecture
against 2.5.60 (22/34).

Misc files for support PC98.

diff -Nru linux-2.5.60/kernel/timer.c linux98-2.5.60/kernel/timer.c
--- linux-2.5.60/kernel/timer.c	2003-02-11 03:38:50.000000000 +0900
+++ linux98-2.5.60/kernel/timer.c	2003-02-11 13:04:49.000000000 +0900
@@ -437,8 +437,13 @@
 /*
  * Timekeeping variables
  */
+#ifdef CONFIG_X86_PC9800
+extern unsigned long tick_usec; 		/* ACTHZ   period (usec) */
+extern unsigned long tick_nsec;			/* USER_HZ period (nsec) */
+#else
 unsigned long tick_usec = TICK_USEC; 		/* ACTHZ   period (usec) */
 unsigned long tick_nsec = TICK_NSEC(TICK_USEC);	/* USER_HZ period (nsec) */
+#endif
 
 /* The current time */
 struct timespec xtime __attribute__ ((aligned (16)));

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH] PC-9800 additional for 2.5.61-ac1 (21/21) traps
  2003-02-20 12:16 [PATCH] PC-9800 additional for 2.5.61-ac1 (0/21) summary Osamu Tomita
                   ` (18 preceding siblings ...)
  2003-02-20 12:38 ` [PATCH] PC-9800 additional for 2.5.61-ac1 (20/21) timer Osamu Tomita
@ 2003-02-20 12:39 ` Osamu Tomita
  19 siblings, 0 replies; 21+ messages in thread
From: Osamu Tomita @ 2003-02-20 12:39 UTC (permalink / raw)
  To: Linux Kernel Mailing List; +Cc: Alan Cox

This is additional patch to support NEC PC-9800 subarchitecture
against 2.5.61-ac1. (21/21)

Support difference of NMI handling, using mach-* scheme.

diff -Nru linux-2.5.61-ac1/arch/i386/kernel/traps.c linux98-2.5.61/arch/i386/kernel/traps.c
--- linux-2.5.61-ac1/arch/i386/kernel/traps.c	2003-02-18 08:58:20.000000000 +0900
+++ linux98-2.5.61/arch/i386/kernel/traps.c	2003-02-18 13:50:05.000000000 +0900
@@ -50,6 +50,8 @@
 #include <linux/irq.h>
 #include <linux/module.h>
 
+#include "mach_traps.h"
+
 asmlinkage int system_call(void);
 asmlinkage void lcall7(void);
 asmlinkage void lcall27(void);
@@ -387,8 +389,7 @@
 	printk("You probably have a hardware problem with your RAM chips\n");
 
 	/* Clear and disable the memory parity error line. */
-	reason = (reason & 0xf) | 4;
-	outb(reason, 0x61);
+	clear_mem_error(reason);
 }
 
 static void io_check_error(unsigned char reason, struct pt_regs * regs)
@@ -425,7 +426,7 @@
 
 static void default_do_nmi(struct pt_regs * regs)
 {
-	unsigned char reason = inb(0x61);
+	unsigned char reason = get_nmi_reason();
  
 	if (!(reason & 0xc0)) {
 #if CONFIG_X86_LOCAL_APIC
@@ -449,10 +450,7 @@
 	 * Reassert NMI in case it became active meanwhile
 	 * as it's edge-triggered.
 	 */
-	outb(0x8f, 0x70);
-	inb(0x71);		/* dummy */
-	outb(0x0f, 0x70);
-	inb(0x71);		/* dummy */
+	reassert_nmi();
 }
 
 static int dummy_nmi_callback(struct pt_regs * regs, int cpu)
diff -Nru linux/include/asm-i386/mach-default/mach_traps.h linux98/include/asm-i386/mach-default/mach_traps.h
--- linux/include/asm-i386/mach-default/mach_traps.h	1970-01-01 09:00:00.000000000 +0900
+++ linux98/include/asm-i386/mach-default/mach_traps.h	2002-11-05 22:42:05.000000000 +0900
@@ -0,0 +1,29 @@
+/*
+ *  include/asm-i386/mach-default/mach_traps.h
+ *
+ *  Machine specific NMI handling for generic.
+ *  Split out from traps.c by Osamu Tomita <tomita@cinet.co.jp>
+ */
+#ifndef _MACH_TRAPS_H
+#define _MACH_TRAPS_H
+
+static inline void clear_mem_error(unsigned char reason)
+{
+	reason = (reason & 0xf) | 4;
+	outb(reason, 0x61);
+}
+
+static inline unsigned char get_nmi_reason(void)
+{
+	return inb(0x61);
+}
+
+static inline void reassert_nmi(void)
+{
+	outb(0x8f, 0x70);
+	inb(0x71);		/* dummy */
+	outb(0x0f, 0x70);
+	inb(0x71);		/* dummy */
+}
+
+#endif /* !_MACH_TRAPS_H */
diff -Nru linux/include/asm-i386/mach-pc9800/mach_traps.h linux98/include/asm-i386/mach-pc9800/mach_traps.h
--- linux/include/asm-i386/mach-pc9800/mach_traps.h	1970-01-01 09:00:00.000000000 +0900
+++ linux98/include/asm-i386/mach-pc9800/mach_traps.h	2002-11-05 22:46:55.000000000 +0900
@@ -0,0 +1,27 @@
+/*
+ *  include/asm-i386/mach-pc9800/mach_traps.h
+ *
+ *  Machine specific NMI handling for PC-9800.
+ *  Written by Osamu Tomita <tomita@cinet.co.jp>
+ */
+#ifndef _MACH_TRAPS_H
+#define _MACH_TRAPS_H
+
+static inline void clear_mem_error(unsigned char reason)
+{
+	outb(0x08, 0x37);
+	outb(0x09, 0x37);
+}
+
+static inline unsigned char get_nmi_reason(void)
+{
+	return (inb(0x33) & 6) ? 0x80 : 0;
+}
+
+static inline void reassert_nmi(void)
+{
+	outb(0x09, 0x50);	/* disable NMI once */
+	outb(0x09, 0x52);	/* re-enable it */
+}
+
+#endif /* !_MACH_TRAPS_H */

^ permalink raw reply	[flat|nested] 21+ messages in thread

end of thread, other threads:[~2003-02-20 12:41 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-02-20 12:16 [PATCH] PC-9800 additional for 2.5.61-ac1 (0/21) summary Osamu Tomita
2003-02-20 12:22 ` [PATCH] PC-9800 additional for 2.5.61-ac1 (1/21) ALSA Osamu Tomita
2003-02-20 12:22 ` [PATCH] PC-9800 additional for 2.5.61-ac1 (2/21) APM Osamu Tomita
2003-02-20 12:23 ` [PATCH] PC-9800 additional for 2.5.61-ac1 (3/21) console Osamu Tomita
2003-02-20 12:24 ` [PATCH] PC-9800 additional for 2.5.61-ac1 (4/21) misc core Osamu Tomita
2003-02-20 12:25 ` [PATCH] PC-9800 additional for 2.5.61-ac1 (5/21) Osamu Tomita
2003-02-20 12:26 ` [PATCH] PC-9800 additional for 2.5.61-ac1 (6/21) fs/patition Osamu Tomita
2003-02-20 12:28 ` [PATCH] PC-9800 additional for 2.5.61-ac1 (7/21) IDE Osamu Tomita
2003-02-20 12:29 ` [PATCH] PC-9800 additional for 2.5.61-ac1 (8/21) kanji Osamu Tomita
2003-02-20 12:30 ` [PATCH] PC-9800 additional for 2.5.61-ac1 (9/21) kconfig Osamu Tomita
2003-02-20 12:31 ` [PATCH] PC-9800 additional for 2.5.61-ac1 (10/21) network card Osamu Tomita
2003-02-20 12:32 ` [PATCH] PC-9800 additional for 2.5.61-ac1 (11/21) parport Osamu Tomita
2003-02-20 12:33 ` [PATCH] PC-9800 additional for 2.5.61-ac1 (12/21) PCI Osamu Tomita
2003-02-20 12:34 ` [PATCH] PC-9800 additional for 2.5.61-ac1 (13/21) PCMCIA Osamu Tomita
2003-02-20 12:34 ` [PATCH] PC-9800 additional for 2.5.61-ac1 (14/21) PNP Osamu Tomita
2003-02-20 12:35 ` [PATCH] PC-9800 additional for 2.5.61-ac1 (15/21) RTC Osamu Tomita
2003-02-20 12:36 ` [PATCH] PC-9800 additional for 2.5.61-ac1 (17/21) serial Osamu Tomita
2003-02-20 12:37 ` [PATCH] PC-9800 additional for 2.5.61-ac1 (18/21) setup Osamu Tomita
2003-02-20 12:38 ` [PATCH] PC-9800 additional for 2.5.61-ac1 (19/21) SMP Osamu Tomita
2003-02-20 12:38 ` [PATCH] PC-9800 additional for 2.5.61-ac1 (20/21) timer Osamu Tomita
2003-02-20 12:39 ` [PATCH] PC-9800 additional for 2.5.61-ac1 (21/21) traps Osamu Tomita

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®