2003-01-19 05:02:05

by Osamu Tomita

[permalink] [raw]
Subject: [PATCHSET] PC-9800 sub-arch (0/29) summary

This is patchset to support NEC PC-9800 subarchitecture
against 2.5.59.

Please download recent patch from following URL.
http://downloads.sourceforge.jp/linux98/2110/linux98-2.5.59.patch.tar.bz2

Comments and test reports are wellcome.


Changes:
- Add new driver for standard serial port.

Description:
- 2.5.50-ac1-merged.patch
PC98 support patch in 2.5.50-ac1 with minimum changes
to apply 2.5.59.

arch/i386/boot98/Makefile | 90
arch/i386/boot98/bootsect.S | 397 ++
arch/i386/boot98/compressed/Makefile | 26
arch/i386/boot98/compressed/head.S | 128
arch/i386/boot98/compressed/misc.c | 379 ++
arch/i386/boot98/compressed/vmlinux.scr | 9
arch/i386/boot98/install.sh | 40
arch/i386/boot98/setup.S | 961 +++++
arch/i386/boot98/tools/build.c | 188 +
arch/i386/boot98/video.S | 262 +
arch/i386/kernel/cpu/proc.c | 2
arch/i386/mach-pc9800/Makefile | 15
arch/i386/mach-pc9800/setup.c | 117
arch/i386/pci/pcbios.c | 15
drivers/block/Makefile | 4
drivers/block/floppy98.c | 4650 +++++++++++++++++++++++++
drivers/char/lp_old98.c | 577 +++
drivers/char/upd4990a.c | 438 ++
drivers/input/keyboard/98kbd.c | 379 ++
drivers/input/keyboard/Kconfig | 12
drivers/input/mouse/98busmouse.c | 201 +
drivers/input/mouse/Kconfig | 12
drivers/input/serio/98kbd-io.c | 181
include/asm-i386/gdc.h | 217 +
include/asm-i386/pc9800_sca.h | 25
include/asm-i386/serial.h | 7
include/asm-i386/setup.h | 1
include/asm-i386/upd4990a.h | 58
include/linux/upd4990a.h | 140
drivers/video/console/gdccon.c | 834 ++++
drivers/input/keyboard/Makefile | 1
drivers/input/mouse/Makefile | 1
drivers/input/serio/Makefile | 1
arch/i386/kernel/i8259.c | 96
arch/i386/kernel/io_apic.c | 24
arch/i386/kernel/mpparse.c | 2
arch/i386/kernel/reboot.c | 18
arch/i386/kernel/setup.c | 1
include/asm-i386/mach-default/io_ports.h | 30
include/asm-i386/mach-default/irq_vectors.h | 7
include/asm-i386/mach-default/mach_reboot.h | 30
include/asm-i386/mach-default/pci-functions.h | 19
include/asm-i386/mach-pc9800/io_ports.h | 30
include/asm-i386/mach-pc9800/irq_vectors.h | 93
include/asm-i386/mach-pc9800/mach_reboot.h | 21
include/asm-i386/mach-pc9800/pci-functions.h | 20
include/asm-i386/mach-pc9800/setup_arch_post.h | 29
include/asm-i386/mach-pc9800/setup_arch_pre.h | 36
include/asm-i386/mach-visws/irq_vectors.h | 6
include/asm-i386/mach-voyager/irq_vectors.h | 6
arch/i386/kernel/apic.c | 7
drivers/video/console/Makefile | 1
include/asm-i386/processor.h | 2
arch/i386/kernel/vm86.c | 8
arch/i386/kernel/traps.c | 7
drivers/input/serio/Kconfig | 12
drivers/char/Kconfig | 22
arch/i386/Makefile | 1
58 files changed, 10806 insertions(+), 90 deletions(-)


- alsa-pc98.patch
ALSA sound drivers for PC98
Fix bug 2.5.59 and additional driver.

sound/isa/cs423x/pc9801_118_magic.h | 411 +++++++++++++++++++++++++++++++
sound/isa/cs423x/sound_pc9800.h | 23 +
sound/drivers/mpu401/Makefile | 1
sound/isa/cs423x/Makefile | 2
sound/core/Makefile | 1
sound/drivers/mpu401/mpu401.c | 9
sound/drivers/opl3/Makefile | 1
sound/isa/Kconfig | 6
sound/isa/cs423x/pc98.c | 466 ++++++++++++++++++++++++++++++++++++
9 files changed, 917 insertions(+), 3 deletions(-)


- apm.patch
APM support for PC98. Including PC98's BIOS bug fix.

arch/i386/kernel/apm.c | 16 ++++++++++++----
include/linux/apm_bios.h | 24 ++++++++++++++++++++++++
2 files changed, 36 insertions(+), 4 deletions(-)


- arch-i386.patch
Core patches for PC98 under arch/i386 and include/asm-i386/mach-* directory.

arch/i386/Kconfig | 10 +
arch/i386/Makefile | 14 +
arch/i386/kernel/setup.c | 99 ------------
arch/i386/kernel/time.c | 115 ++------------
arch/i386/kernel/timers/timer_pit.c | 22 +-
arch/i386/kernel/timers/timer_tsc.c | 94 +-----------
arch/i386/kernel/traps.c | 12 -
include/asm-i386/mach-default/calibrate_tsc.h | 90 +++++++++++
include/asm-i386/mach-default/mach_resources.h | 113 ++++++++++++++
include/asm-i386/mach-default/mach_time.h | 122 +++++++++++++++
include/asm-i386/mach-default/mach_traps.h | 29 +++
include/asm-i386/mach-pc9800/calibrate_tsc.h | 71 +++++++++
include/asm-i386/mach-pc9800/do_timer.h | 80 ++++++++++
include/asm-i386/mach-pc9800/mach_resources.h | 192 +++++++++++++++++++++++++
include/asm-i386/mach-pc9800/mach_time.h | 136 +++++++++++++++++
include/asm-i386/mach-pc9800/mach_traps.h | 27 +++
include/asm-i386/mach-pc9800/smpboot_hooks.h | 33 ++++
17 files changed, 967 insertions(+), 292 deletions(-)


- console.patch
Support for PC98 Standard console.

drivers/video/console/Kconfig | 14 +
drivers/char/Makefile | 9
drivers/char/console_macros.h | 14 +
drivers/char/console_pc9800.h | 14 +
drivers/char/consolemap.c | 58 ++++-
drivers/char/pc9800.uni | 260 +++++++++++++++++++++++
drivers/char/vt.c | 459 +++++++++++++++++++++++++++++++++++------
drivers/char/vt_ioctl.c | 19 +
include/linux/console.h | 11
include/linux/console_struct.h | 25 ++
include/linux/consolemap.h | 1
include/linux/tty.h | 4
include/linux/vt.h | 1
include/linux/vt_buffer.h | 4
14 files changed, 822 insertions(+), 71 deletions(-)


- drivers-net.patch
C-bus(PC98's legacy bus like ISA) network cards support.

drivers/net/8390.h | 3
drivers/net/Kconfig | 55 +++++
drivers/net/Makefile | 1
drivers/net/Makefile.lib | 1
drivers/net/ne2k_cbus.h | 481 +++++++++++++++++++++++++++++++++++++++++++++++
drivers/net/at1700.c | 115 +++++++++--
drivers/net/ne.c | 356 +++++++++++++++++++++++++++++++++-
drivers/net/3c509.c | 35 +++
drivers/net/Space.c | 2
9 files changed, 1017 insertions(+), 32 deletions(-)


- fs.patch
FAT fs and partition table support.

fs/fat/inode.c | 4
fs/partitions/Kconfig | 7 +
fs/partitions/Makefile | 1
fs/partitions/check.c | 4
fs/partitions/msdos.c | 2
fs/partitions/nec98.c | 272 +++++++++++++++++++++++++++++++++++++++++++++++++
fs/partitions/nec98.h | 10 +
7 files changed, 298 insertions(+), 2 deletions(-)


- ide.patch
Support standard IDE I/F of PC98.

drivers/ide/Kconfig | 5
drivers/ide/ide-disk.c | 67 +++
drivers/ide/ide-probe.c | 16
drivers/ide/ide-proc.c | 3
drivers/ide/ide.c | 9
drivers/ide/legacy/Makefile | 5
drivers/ide/legacy/hd98.c | 904 ++++++++++++++++++++++++++++++++++++++++++++
drivers/ide/legacy/pc9800.c | 82 +++
include/asm-i386/ide.h | 18
include/linux/hdreg.h | 19
include/linux/ide.h | 2
11 files changed, 1125 insertions(+), 5 deletions(-)


- include-asm.patch
Core patches for PC98 under include/asm-i386/ directory.

include/asm-i386/dma.h | 7 +
include/asm-i386/io.h | 6 +
include/asm-i386/irq.h | 4
include/asm-i386/pc9800.h | 27 ++++
include/asm-i386/pc9800_dma.h | 238 +++++++++++++++++++++++++++++++++++++++++
include/asm-i386/pgtable.h | 4
include/asm-i386/scatterlist.h | 6 +
include/asm-i386/timex.h | 4
8 files changed, 296 insertions(+)


- input.patch
Beep driver and keyboard support files.

drivers/char/keyboard.c | 4 +
drivers/input/misc/98spkr.c | 95 ++++++++++++++++++++++++++++++++++++++++++++
drivers/input/misc/Kconfig | 4 +
drivers/input/misc/Makefile | 1
include/linux/kbd_kern.h | 5 +-
include/linux/keyboard.h | 1
6 files changed, 108 insertions(+), 2 deletions(-)


- kernel.patch
Misc files for support PC98.

include/linux/kernel.h | 6 ++++++
kernel/dma.c | 3 +++
kernel/timer.c | 5 +++++
3 files changed, 14 insertions(+)


- parport.patch
Parallel port support.

drivers/parport/parport_pc.c | 66 +++++++++++++++++++++++++++++++++++++++----
include/linux/parport_pc.h | 10 ++++++
2 files changed, 71 insertions(+), 5 deletions(-)


- pci.patch
PCI support.

arch/i386/pci/irq.c | 27 +++++++++++++++++++++++++++
drivers/pcmcia/yenta.c | 6 ++++++
include/asm-i386/pci.h | 4 ++++
3 files changed, 37 insertions(+)


- pcmcia.patch
PCMCIA (16bits) support.

drivers/pcmcia/i82365.c | 4 ++++
1 files changed, 4 insertions(+)


- pnp.patch
Legacy bus PNP support.

drivers/pnp/isapnp/core.c | 5 +++++
1 files changed, 5 insertions(+)


- scsi.patch
SCSI host adapter support.

drivers/scsi/Kconfig | 7 +
drivers/scsi/Makefile | 10 +
drivers/scsi/pc980155.c | 263 ++++++++++++++++++++++++++++++++++++++++++++
drivers/scsi/pc980155.h | 47 +++++++
drivers/scsi/pc980155regs.h | 89 ++++++++++++++
drivers/scsi/scsi_scan.c | 1
drivers/scsi/scsi_syms.c | 4
drivers/scsi/scsicam98.c | 192 ++++++++++++++++++++++++++++++++
drivers/scsi/sd.c | 23 +++
drivers/scsi/wd33c93.c | 30 ++++-
drivers/scsi/wd33c93.h | 5
11 files changed, 664 insertions(+), 7 deletions(-)


- serial.patch
Serial port driver.

drivers/serial/8250_pnp.c | 5
drivers/serial/Kconfig | 17
drivers/serial/Makefile | 1
drivers/serial/serial98.c | 1125 ++++++++++++++++++++++++++++++++++++++++++++
include/linux/serial_core.h | 8
5 files changed, 1153 insertions(+), 3 deletions(-)


- smp.patch
SMP support.

arch/i386/kernel/mpparse.c | 34 ++++++++++++++++-----
arch/i386/kernel/smpboot.c | 14 ++++++++
include/asm-i386/mach-default/bios_ebda.h | 15 +++++++++
include/asm-i386/mach-pc9800/bios_ebda.h | 14 ++++++++
include/asm-i386/mach-pc9800/mach_wakecpu.h | 45 ++++++++++++++++++++++++++++
5 files changed, 114 insertions(+), 8 deletions(-)


-- *-update.patch are updates for files in 2.5.50-ac1.

- Kconfig-update.patch

drivers/char/Kconfig | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)


- boot98-update.patch

arch/i386/boot98/compressed/Makefile | 3 +--
arch/i386/boot98/Makefile | 20 +++-----------------
2 files changed, 4 insertions(+), 19 deletions(-)


- floppy98-update.patch

drivers/block/floppy98.c | 84 +++++++++++++++++++++++++++--------------------
drivers/block/Makefile | 2 -
2 files changed, 50 insertions(+), 36 deletions(-)


- gdc-update.patch

include/asm-i386/gdc.h | 144 ++++++++++++++++++++++-------------------
drivers/video/console/gdccon.c | 1
2 files changed, 79 insertions(+), 66 deletions(-)


- i8259.c-update.patch

arch/i386/kernel/i8259.c | 2 +-
1 files changed, 1 insertion(+), 1 deletion(-)


- input-update.patch

drivers/input/mouse/98busmouse.c | 7 ++++---
drivers/input/serio/98kbd-io.c | 7 ++++---
drivers/input/keyboard/Kconfig | 2 +-
drivers/input/mouse/Kconfig | 2 +-
drivers/input/serio/Kconfig | 2 +-
5 files changed, 11 insertions(+), 9 deletions(-)

- lp_old98-update.patch

drivers/char/lp_old98.c | 147 ++++++++++++++++++++++--------------------------
1 files changed, 69 insertions(+), 78 deletions(-)


- mach-pc9800-update.patch
arch/i386/mach-pc9800/Makefile | 10 -----
arch/i386/mach-pc9800/setup.c | 8 ++--
arch/i386/mach-pc9800/topology.c | 68 +++++++++++++++++++++++++++++++++++++++
3 files changed, 73 insertions(+), 13 deletions(-)


- pci-quirks-update.patch

drivers/pci/quirks.c | 2 ++
1 files changed, 2 insertions(+)


- serial.h-update.patch

include/asm-i386/serial.h | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)


- upd4990a.h-update.patch

include/asm-i386/upd4990a.h | 6 ------
1 files changed, 6 deletions(-)


Thanks,
Osamu Tomita <[email protected]>


2003-01-19 06:29:16

by Osamu Tomita

[permalink] [raw]
Subject: [PATCHSET] PC-9800 sub-arch (6/29) ac-update

This is patchset to support NEC PC-9800 subarchitecture
against 2.5.59 (6/29).

Updates files under arch/i386/boot98 in 2.5.50-ac1.

diff -Nru linux-2.5.50-ac1/arch/i386/boot98/Makefile linux-2.5.54/arch/i386/boot98/Makefile
--- linux-2.5.50-ac1/arch/i386/boot98/Makefile 2002-12-16 09:15:54.000000000 +0900
+++ linux-2.5.54/arch/i386/boot98/Makefile 2003-01-02 12:21:49.000000000 +0900
@@ -32,12 +32,6 @@

host-progs := tools/build

-# Default
-
-boot: bzImage
-
-include $(TOPDIR)/Rules.make
-
# ---------------------------------------------------------------------------

$(obj)/zImage: IMAGE_OFFSET := 0x1000
@@ -53,6 +47,7 @@
$(obj)/zImage $(obj)/bzImage: $(obj)/bootsect $(obj)/setup \
$(obj)/vmlinux.bin $(obj)/tools/build FORCE
$(call if_changed,image)
+ @echo 'Kernel: $@ is ready'

$(obj)/vmlinux.bin: $(obj)/compressed/vmlinux FORCE
$(call if_changed,objcopy)
@@ -64,9 +59,8 @@
$(call if_changed,ld)

$(obj)/compressed/vmlinux: FORCE
- +@$(call descend,$(obj)/compressed,IMAGE_OFFSET=$(IMAGE_OFFSET) \
- $(obj)/compressed/vmlinux)
-
+ $(Q)$(MAKE) -f scripts/Makefile.build obj=$(obj)/compressed \
+ IMAGE_OFFSET=$(IMAGE_OFFSET) $@

zdisk: $(BOOTIMAGE)
dd bs=8192 if=$(BOOTIMAGE) of=/dev/fd0
@@ -80,11 +74,3 @@

install: $(BOOTIMAGE)
sh $(src)/install.sh $(KERNELRELEASE) $(BOOTIMAGE) System.map "$(INSTALL_PATH)"
-
-archhelp:
- @echo '* bzImage - Compressed kernel image (arch/$(ARCH)/boot/bzImage)'
- @echo ' install - Install kernel using'
- @echo ' (your) ~/bin/installkernel or'
- @echo ' (distribution) /sbin/installkernel or'
- @echo ' install to $$(INSTALL_PATH) and run lilo'
-
diff -Nru linux-2.5.50-ac1/arch/i386/boot98/compressed/Makefile linux-2.5.52/arch/i386/boot98/compressed/Makefile
--- linux-2.5.50-ac1/arch/i386/boot98/compressed/Makefile 2002-12-16 09:15:54.000000000 +0900
+++ linux-2.5.52/arch/i386/boot98/compressed/Makefile 2002-12-16 11:08:13.000000000 +0900
@@ -7,12 +7,11 @@
EXTRA_TARGETS := vmlinux vmlinux.bin vmlinux.bin.gz head.o misc.o piggy.o
EXTRA_AFLAGS := -traditional

-include $(TOPDIR)/Rules.make
-
LDFLAGS_vmlinux := -Ttext $(IMAGE_OFFSET) -e startup_32

$(obj)/vmlinux: $(obj)/head.o $(obj)/misc.o $(obj)/piggy.o FORCE
$(call if_changed,ld)
+ @:

$(obj)/vmlinux.bin: vmlinux FORCE
$(call if_changed,objcopy)

2003-01-19 06:26:06

by Osamu Tomita

[permalink] [raw]
Subject: [PATCHSET] PC-9800 sub-arch (3/29) alsa

This is patchset to support NEC PC-9800 subarchitecture
against 2.5.59 (3/29).

ALSA sound drivers for PC98
Fix bug in 2.5.59 and additional driver.

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.52/sound/isa/cs423x/Makefile linux98-2.5.52/sound/isa/cs423x/Makefile
--- linux-2.5.52/sound/isa/cs423x/Makefile 2002-12-16 11:08:16.000000000 +0900
+++ linux98-2.5.52/sound/isa/cs423x/Makefile 2002-12-16 21:38:54.000000000 +0900
@@ -10,6 +10,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
@@ -22,5 +23,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 <[email protected]>
+ * Osamu Tomita <[email protected]>
+ * Takashi Iwai <[email protected]>
+ *
+ *
+ * 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 <[email protected]>");
+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/sound/core/Makefile linux98/sound/core/Makefile
--- linux/sound/core/Makefile 2002-10-19 13:01:14.000000000 +0900
+++ linux98/sound/core/Makefile 2002-10-30 13:52:52.000000000 +0900
@@ -96,6 +96,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.52/sound/drivers/mpu401/Makefile linux98-2.5.52/sound/drivers/mpu401/Makefile
--- linux-2.5.52/sound/drivers/mpu401/Makefile 2002-12-16 11:08:24.000000000 +0900
+++ linux98-2.5.52/sound/drivers/mpu401/Makefile 2002-12-16 21:38:54.000000000 +0900
@@ -39,5 +39,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/sound/drivers/opl3/Makefile linux98/sound/drivers/opl3/Makefile
--- linux/sound/drivers/opl3/Makefile 2002-12-24 14:19:25.000000000 +0900
+++ linux98/sound/drivers/opl3/Makefile 2002-12-26 15:25:50.000000000 +0900
@@ -26,6 +26,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)
diff -Nru linux/sound/drivers/mpu401/mpu401.c linux98/sound/drivers/mpu401/mpu401.c
--- linux/sound/drivers/mpu401/mpu401.c 2002-12-24 14:20:59.000000000 +0900
+++ linux98/sound/drivers/mpu401/mpu401.c 2003-01-04 14:05:38.000000000 +0900
@@ -40,7 +40,7 @@
static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */
static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* MPU-401 port number */
static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* MPU-401 IRQ */
-#ifdef CONFIG_PC9800
+#ifdef CONFIG_X86_PC9800
static int pc98ii[SNDRV_CARDS]; /* PC98-II dauther board */
#endif

@@ -59,7 +59,7 @@
MODULE_PARM(irq, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
MODULE_PARM_DESC(irq, "IRQ # for MPU-401 device.");
MODULE_PARM_SYNTAX(irq, SNDRV_IRQ_DESC);
-#ifdef CONFIG_PC9800
+#ifdef CONFIG_X86_PC9800
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);
@@ -85,7 +85,7 @@
if (card == NULL)
return -ENOMEM;
if (snd_mpu401_uart_new(card, 0,
-#ifdef CONFIG_PC9800
+#ifdef CONFIG_X86_PC9800
pc98ii[dev] ? MPU401_HW_PC98II :
#endif
MPU401_HW_MPU401,
@@ -154,6 +154,9 @@
(void)(get_option(&str,&enable[nr_dev]) == 2 &&
get_option(&str,&index[nr_dev]) == 2 &&
get_id(&str,&id[nr_dev]) == 2 &&
+#ifdef CONFIG_X86_PC9800
+ get_option(&str,&pc98ii[nr_dev]) == 2 &&
+#endif
get_option(&str,(int *)&port[nr_dev]) == 2 &&
get_option(&str,&irq[nr_dev]) == 2);
nr_dev++;

2003-01-19 06:29:11

by Osamu Tomita

[permalink] [raw]
Subject: [PATCHSET] PC-9800 sub-arch (5/29) core#1

This is patchset to support NEC PC-9800 subarchitecture
against 2.5.59 (5/29).

Core patches for PC98 under arch/i386 and include/asm-i386/mach-* directory.

diff -Nru linux-2.5.50-ac1/arch/i386/Kconfig linux98-2.5.59/arch/i386/Kconfig
--- linux-2.5.50-ac1/arch/i386/Kconfig 2003-01-17 13:22:06.000000000 +0900
+++ linux98-2.5.59/arch/i386/Kconfig 2003-01-17 13:33:54.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
@@ -1167,7 +1173,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.
@@ -1185,7 +1191,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
diff -Nru linux-2.5.50-ac1/arch/i386/Makefile linux98-2.5.59/arch/i386/Makefile
--- linux-2.5.50-ac1/arch/i386/Makefile 2003-01-17 13:24:14.000000000 +0900
+++ linux98-2.5.59/arch/i386/Makefile 2003-01-17 13:33:54.000000000 +0900
@@ -65,6 +65,10 @@
mflags-$(CONFIG_X86_NUMAQ) := -Iinclude/asm-i386/mach-numaq
mcore-$(CONFIG_X86_NUMAQ) := mach-default

+# PC-9800 subarch support
+mflags-$(CONFIG_X86_PC9800) := -Iinclude/asm-i386/mach-pc9800
+mcore-$(CONFIG_X86_PC9800) := mach-pc9800
+
# BIGSMP subarch support
mflags-$(CONFIG_X86_BIGSMP) := -Iinclude/asm-i386/mach-bigsmp
mcore-$(CONFIG_X86_BIGSMP) := mach-default
@@ -90,15 +94,19 @@
CFLAGS += $(mflags-y)
AFLAGS += $(mflags-y)

+ifeq ($(CONFIG_X86_PC9800),y)
+boot := arch/i386/boot98
+else
boot := arch/i386/boot
+endif

.PHONY: zImage bzImage compressed zlilo bzlilo zdisk bzdisk install \
clean archclean archmrproper

all: bzImage

-BOOTIMAGE=arch/i386/boot/bzImage
-zImage zlilo zdisk: BOOTIMAGE=arch/i386/boot/zImage
+BOOTIMAGE=$(boot)/bzImage
+zImage zlilo zdisk: BOOTIMAGE=$(boot)/zImage

zImage bzImage: vmlinux
$(Q)$(MAKE) $(build)=$(boot) $(BOOTIMAGE)
@@ -119,7 +127,7 @@
$(Q)$(MAKE) $(clean)=arch/i386/boot98

define archhelp
- echo '* bzImage - Compressed kernel image (arch/$(ARCH)/boot/bzImage)'
+ echo '* bzImage - Compressed kernel image ($(boot)/bzImage)'
echo ' install - Install kernel using'
echo ' (your) ~/bin/installkernel or'
echo ' (distribution) /sbin/installkernel or'
diff -Nru linux/arch/i386/kernel/setup.c linux98/arch/i386/kernel/setup.c
--- linux/arch/i386/kernel/setup.c 2002-12-26 13:40:40.000000000 +0900
+++ linux98/arch/i386/kernel/setup.c 2002-12-26 14:01:32.000000000 +0900
@@ -20,6 +20,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>
@@ -40,6 +41,7 @@
#include <asm/setup.h>
#include <asm/arch_hooks.h>
#include "setup_arch_pre.h"
+#include "mach_resources.h"

int disable_pse __initdata = 0;

@@ -102,98 +104,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)
{
@@ -826,11 +738,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;
@@ -911,6 +820,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/arch/i386/kernel/time.c linux98/arch/i386/kernel/time.c
--- linux/arch/i386/kernel/time.c 2003-01-14 14:58:41.000000000 +0900
+++ linux98/arch/i386/kernel/time.c 2003-01-14 22:42:14.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 */

@@ -136,69 +139,13 @@
write_unlock_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;
@@ -224,9 +171,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
@@ -240,14 +187,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
@@ -292,43 +239,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/arch/i386/kernel/timers/timer_pit.c linux98/arch/i386/kernel/timers/timer_pit.c
--- linux/arch/i386/kernel/timers/timer_pit.c 2003-01-14 14:59:12.000000000 +0900
+++ linux98/arch/i386/kernel/timers/timer_pit.c 2003-01-14 22:42:14.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;

- 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,12 +87,18 @@
*/
unsigned long jiffies_t;

+ /* for support LATCH is not constant */
+ if (is_1st_boot) {
+ is_1st_boot = 0;
+ count_p = LATCH;
+ }
+
/* gets recalled with irq locally disabled */
spin_lock(&i8253_lock);
/* 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
@@ -98,13 +106,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/arch/i386/kernel/timers/timer_tsc.c linux98/arch/i386/kernel/timers/timer_tsc.c
--- linux/arch/i386/kernel/timers/timer_tsc.c 2003-01-14 14:59:01.000000000 +0900
+++ linux98/arch/i386/kernel/timers/timer_tsc.c 2003-01-14 22:42:14.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)
-
static 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/arch/i386/kernel/traps.c linux98/arch/i386/kernel/traps.c
--- linux/arch/i386/kernel/traps.c 2003-01-14 09:33:33.000000000 +0900
+++ linux98/arch/i386/kernel/traps.c 2003-01-14 09:52:36.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/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 <[email protected]>
+ */
+/* ------ 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-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 <[email protected]>
+ */
+#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-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 <[email protected]>
+ */
+#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-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 <[email protected]>
+ */
+#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/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 <[email protected]>
+ */
+
+/* ------ 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/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/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 <[email protected]>
+ */
+#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 */
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 <[email protected]>
+ */
+#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 */
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 <[email protected]>
+ */
+#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 */
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();
+}

2003-01-19 06:23:34

by Osamu Tomita

[permalink] [raw]
Subject: [PATCHSET] PC-9800 sub-arch (2/29) ac-update

This is patchset to support NEC PC-9800 subarchitecture
against 2.5.59 (2/29).

Updates drivers/char/Kconfig in 2.5.50-ac1.

diff -Nru linux-2.5.50-ac1/drivers/char/Kconfig linux98-2.5.58/drivers/char/Kconfig
--- linux-2.5.50-ac1/drivers/char/Kconfig 2003-01-14 22:18:18.000000000 +0900
+++ linux98-2.5.58/drivers/char/Kconfig 2003-01-14 22:35:34.000000000 +0900
@@ -577,7 +577,7 @@

config PC9800_OLDLP
tristate "NEC PC-9800 old-style printer port support"
- depends on PC9800 && !PARPORT
+ depends on X86_PC9800 && !PARPORT
---help---
If you intend to attach a printer to the parallel port of NEC PC-9801
/PC-9821 with OLD compatibility mode, Say Y.
@@ -785,7 +785,7 @@

config RTC
tristate "Enhanced Real Time Clock Support"
- depends on !PPC32 && !PARISC && !IA64 && !PC9800
+ depends on !PPC32 && !PARISC && !IA64 && !X86_PC9800
---help---
If you say Y here and create a character special file /dev/rtc with
major number 10 and minor number 135 using mknod ("man mknod"), you
@@ -846,7 +846,7 @@

config RTC98
tristate "NEC PC-9800 Real Time Clock Support"
- depends on PC9800
+ depends on X86_PC9800
default y
---help---
If you say Y here and create a character special file /dev/rtc with

2003-01-19 06:27:15

by Osamu Tomita

[permalink] [raw]
Subject: [PATCHSET] PC-9800 sub-arch (4/29) apm

This is patchset to support NEC PC-9800 subarchitecture
against 2.5.59 (4/29).

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

diff -Nru linux/arch/i386/kernel/apm.c linux98/arch/i386/kernel/apm.c
--- linux/arch/i386/kernel/apm.c 2003-01-09 13:03:50.000000000 +0900
+++ linux98/arch/i386/kernel/apm.c 2003-01-10 10:06:15.000000000 +0900
@@ -227,6 +227,8 @@

#include <linux/sysrq.h>

+#include "io_ports.h"
+
extern rwlock_t xtime_lock;
extern spinlock_t i8253_lock;
extern unsigned long get_cmos_time(void);
@@ -623,6 +625,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"
@@ -684,6 +689,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"
@@ -724,7 +732,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;
}

@@ -1237,11 +1245,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/include/linux/apm_bios.h linux98/include/linux/apm_bios.h
--- linux/include/linux/apm_bios.h 2003-01-02 12:22:18.000000000 +0900
+++ linux98/include/linux/apm_bios.h 2003-01-04 13:20:28.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,7 @@
/*
* The APM function codes
*/
+#ifndef CONFIG_X86_PC9800
#define APM_FUNC_INST_CHECK 0x5300
#define APM_FUNC_REAL_CONN 0x5301
#define APM_FUNC_16BIT_CONN 0x5302
@@ -80,6 +82,28 @@
#define APM_FUNC_RESUME_TIMER 0x5311
#define APM_FUNC_RESUME_ON_RING 0x5312
#define APM_FUNC_TIMER 0x5313
+#else
+#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
+#endif

/*
* Function code for APM_FUNC_RESUME_TIMER

2003-01-19 06:31:46

by Osamu Tomita

[permalink] [raw]
Subject: [PATCHSET] PC-9800 sub-arch (7/29) console

This is patchset to support NEC PC-9800 subarchitecture
against 2.5.59 (7/29).

Support for PC98 Standard console.

diff -Nru linux/drivers/char/Makefile linux98/drivers/char/Makefile
--- linux/drivers/char/Makefile 2002-12-10 11:46:24.000000000 +0900
+++ linux98/drivers/char/Makefile 2002-12-16 11:27:23.000000000 +0900
@@ -5,7 +5,11 @@
#
# This file contains the font map for the default (hardware) font
#
+ifneq ($(CONFIG_X86_PC9800),y)
FONTMAPFILE = cp437.uni
+else
+FONTMAPFILE = pc9800.uni
+endif

obj-y += mem.o tty_io.o n_tty.o tty_ioctl.o pty.o misc.o random.o

@@ -14,7 +18,8 @@

export-objs := busmouse.o vt.o generic_serial.o ip2main.o consolemap.o\
ite_gpio.o keyboard.o misc.o nvram.o random.o rtc.o \
- selection.o sonypi.o sysrq.o tty_io.o tty_ioctl.o
+ selection.o sonypi.o sysrq.o tty_io.o tty_ioctl.o \
+ upd4990a.o

obj-$(CONFIG_VT) += vt_ioctl.o vc_screen.o consolemap.o consolemap_deftbl.o selection.o keyboard.o
obj-$(CONFIG_HW_CONSOLE) += vt.o defkeymap.o
@@ -51,6 +56,7 @@

obj-$(CONFIG_PRINTER) += lp.o
obj-$(CONFIG_TIPAR) += tipar.o
+obj-$(CONFIG_PC9800_OLDLP) += lp_old98.o

obj-$(CONFIG_BUSMOUSE) += busmouse.o
obj-$(CONFIG_DTLK) += dtlk.o
@@ -58,6 +64,7 @@
obj-$(CONFIG_APPLICOM) += applicom.o
obj-$(CONFIG_SONYPI) += sonypi.o
obj-$(CONFIG_RTC) += rtc.o
+obj-$(CONFIG_RTC98) += upd4990a.o
obj-$(CONFIG_GEN_RTC) += genrtc.o
obj-$(CONFIG_EFI_RTC) += efirtc.o
ifeq ($(CONFIG_PPC),)
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)
@@ -64,6 +68,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/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/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
@@ -75,6 +75,9 @@
*/

#include <linux/module.h>
+#ifdef CONFIG_X86_PC9800
+#define CONFIG_KANJI
+#endif
#include <linux/sched.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
@@ -107,6 +110,10 @@

#include "console_macros.h"

+#ifdef CONFIG_X86_PC9800
+#include "console_pc9800.h"
+extern unsigned short translations[][256];
+#endif

const struct consw *conswitchp;

@@ -151,6 +158,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);
@@ -301,7 +312,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 +398,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 +416,7 @@
else {
u16 *q = p;
int cnt = count;
- u16 a;
+ vram_char_t a;

if (!can_do_color) {
while (cnt--) {
@@ -433,11 +446,30 @@
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)
{
static unsigned short *p;
- static unsigned short old;
+ static vram_char_t old;
static unsigned short oldx, oldy;

if (p) {
@@ -448,10 +480,15 @@
if (offset == -1)
p = NULL;
else {
- unsigned short new;
+ vram_char_t new;
p = screenpos(currcons, offset, 1);
old = scr_readw(p);
+#ifndef CONFIG_FB_EGC
new = old ^ complement_mask;
+#else
+ new = (old & 0xff0000ff) | ((old & 0xf000) >> 4)
+ | ((old & 0xf00) << 4);
+#endif
scr_writew(new, p);
if (DO_UPDATE) {
oldx = (offset >> 1) % video_num_columns;
@@ -510,7 +547,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 +683,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 +720,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 +773,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;

@@ -1085,6 +1126,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 +1137,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 +1148,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;
@@ -1261,6 +1311,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) {
@@ -1310,6 +1364,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 +1457,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 +1486,18 @@
bottom = video_num_lines;
vc_state = ESnormal;
ques = 0;
+#ifndef CONFIG_KANJI
translate = set_translate(LAT1_MAP,currcons);
G0_charset = LAT1_MAP;
G1_charset = GRAF_MAP;
+#else
+ 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;
+#endif
charset = 0;
need_wrap = 0;
report_mouse = 0;
@@ -1442,6 +1539,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 +1587,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 +1654,11 @@
case ')':
vc_state = ESsetG1;
return;
+#ifdef CONFIG_KANJI
+ case '$':
+ vc_state = ESsetJIS;
+ return;
+#endif
case '#':
vc_state = EShash;
return;
@@ -1794,8 +1908,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 +1938,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 +2014,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 +2071,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 */
+#ifndef CONFIG_KANJI
+ tc = translate[toggle_meta ? (c|0x80) : c];
+#else
+ tc = translate[(toggle_meta || translate_ex) ? (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 +2232,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 +2304,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
@@ -2427,9 +2740,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 +2791,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);
@@ -2972,9 +3298,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;
@@ -3036,8 +3365,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 2002-12-10 11:45:55.000000000 +0900
+++ linux98/include/linux/console.h 2002-12-16 11:27:23.000000000 +0900
@@ -17,6 +17,13 @@
#include <linux/types.h>
#include <linux/kdev_t.h>
#include <linux/spinlock.h>
+#include <linux/config.h>
+
+#ifndef CONFIG_X86_PC9800
+typedef __u16 vram_char_t;
+#else
+typedef __u32 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 */
@@ -83,6 +90,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 */
};

@@ -106,6 +125,10 @@
#define CUR_HWMASK 0x0f
#define CUR_SWMASK 0xfff0

+#ifndef CONFIG_X86_PC9800
#define CUR_DEFAULT CUR_UNDERLINE
+#else
+#define CUR_DEFAULT CUR_BLOCK
+#endif

#define CON_IS_VISIBLE(conp) (*conp->vc_display_fg == conp)
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;

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))

2003-01-19 06:34:08

by Osamu Tomita

[permalink] [raw]
Subject: [PATCHSET] PC-9800 sub-arch (9/29) ac-update

This is patchset to support NEC PC-9800 subarchitecture
against 2.5.59 (9/29).

Updates floppy driver for PC98 in 2.5.50-ac1.

diff -Nru linux-2.5.50-ac1/drivers/block/Makefile linux-2.5.54/drivers/block/Makefile
--- linux-2.5.50-ac1/drivers/block/Makefile 2003-01-04 10:47:57.000000000 +0900
+++ linux-2.5.54/drivers/block/Makefile 2003-01-04 13:35:45.000000000 +0900
@@ -14,7 +14,7 @@
obj-y := elevator.o ll_rw_blk.o ioctl.o genhd.o scsi_ioctl.o deadline-iosched.o

obj-$(CONFIG_MAC_FLOPPY) += swim3.o
-ifneq ($(CONFIG_PC9800),y)
+ifneq ($(CONFIG_X86_PC9800),y)
obj-$(CONFIG_BLK_DEV_FD) += floppy.o
else
obj-$(CONFIG_BLK_DEV_FD) += floppy98.o
diff -Nru linux-2.5.50-ac1/drivers/block/floppy98.c linux-2.5.52/drivers/block/floppy98.c
--- linux-2.5.50-ac1/drivers/block/floppy98.c 2002-12-16 09:15:54.000000000 +0900
+++ linux-2.5.52/drivers/block/floppy98.c 2002-12-16 14:42:13.000000000 +0900
@@ -167,6 +167,7 @@
#include <linux/kernel.h>
#include <linux/timer.h>
#include <linux/workqueue.h>
+#include <linux/version.h>
#define FDPATCHES
#include <linux/fdreg.h>

@@ -254,7 +255,6 @@
void floppy_interrupt(int irq, void *dev_id, struct pt_regs * regs);
static int set_mode(char mask, char data);
static void register_devfs_entries (int drive) __init;
-static devfs_handle_t devfs_handle;

#define K_64 0x10000 /* 64KB */

@@ -275,9 +275,8 @@
static int irqdma_allocated;

#define LOCAL_END_REQUEST
-#define MAJOR_NR FLOPPY_MAJOR
#define DEVICE_NAME "floppy"
-#define DEVICE_NR(device) ( (minor(device) & 3) | ((minor(device) & 0x80 ) >> 5 ))
+
#include <linux/blk.h>
#include <linux/blkpg.h>
#include <linux/cdrom.h> /* for the compatibility eject ioctl */
@@ -3354,7 +3353,7 @@
static int invalidate_drive(struct block_device *bdev)
{
/* invalidate the buffer track to force a reread */
- set_bit(DRIVE(to_kdev_t(bdev->bd_dev)), &fake_change);
+ set_bit((int)bdev->bd_disk->private_data, &fake_change);
process_fd_request();
check_disk_change(bdev);
return 0;
@@ -4058,27 +4057,28 @@
.revalidate_disk= floppy_revalidate,
};

-static void __init register_devfs_entries (int drive)
-{
- int base_minor, i;
- static char *table[] =
- {"",
+static char *table[] =
+{"",
#if 0
- "d360",
+"d360",
#else
- "h1232",
+"h1232",
#endif
- "h1200", "u360", "u720", "h360", "h720",
- "u1440", "u2880", "CompaQ", "h1440", "u1680", "h410",
- "u820", "h1476", "u1722", "h420", "u830", "h1494", "u1743",
- "h880", "u1040", "u1120", "h1600", "u1760", "u1920",
- "u3200", "u3520", "u3840", "u1840", "u800", "u1600",
- NULL
- };
- static int t360[] = {1,0}, t1200[] = {2,5,6,10,12,14,16,18,20,23,0},
- t3in[] = {8,9,26,27,28, 7,11,15,19,24,25,29,31, 3,4,13,17,21,22,30,0};
- static int *table_sup[] =
- {NULL, t360, t1200, t3in+5+8, t3in+5, t3in, t3in};
+"h1200", "u360", "u720", "h360", "h720",
+"u1440", "u2880", "CompaQ", "h1440", "u1680", "h410",
+"u820", "h1476", "u1722", "h420", "u830", "h1494", "u1743",
+"h880", "u1040", "u1120", "h1600", "u1760", "u1920",
+"u3200", "u3520", "u3840", "u1840", "u800", "u1600",
+NULL
+};
+static int t360[] = {1,0}, t1200[] = {2,5,6,10,12,14,16,18,20,23,0},
+t3in[] = {8,9,26,27,28, 7,11,15,19,24,25,29,31, 3,4,13,17,21,22,30,0};
+static int *table_sup[] =
+{NULL, t360, t1200, t3in+5+8, t3in+5, t3in, t3in};
+
+static void __init register_devfs_entries (int drive)
+{
+ int base_minor, i;

base_minor = (drive < 4) ? drive : (124 + drive);
if (UDP->cmos < NUMBER(default_drive_params)) {
@@ -4086,8 +4086,8 @@
do {
char name[16];

- sprintf (name, "%d%s", drive, table[table_sup[UDP->cmos][i]]);
- devfs_register (devfs_handle, name, DEVFS_FL_DEFAULT, MAJOR_NR,
+ sprintf(name, "floppy/%d%s", drive, table[table_sup[UDP->cmos][i]]);
+ devfs_register(NULL, name, DEVFS_FL_DEFAULT, FLOPPY_MAJOR,
base_minor + (table_sup[UDP->cmos][i] << 2),
S_IFBLK | S_IRUSR | S_IWUSR | S_IRGRP |S_IWGRP,
&floppy_fops, NULL);
@@ -4268,21 +4268,21 @@
goto Enomem;
}

- devfs_handle = devfs_mk_dir (NULL, "floppy", NULL);
- if (register_blkdev(MAJOR_NR,"fd",&floppy_fops)) {
- printk("Unable to get major %d for floppy\n",MAJOR_NR);
+ devfs_mk_dir (NULL, "floppy", NULL);
+ if (register_blkdev(FLOPPY_MAJOR,"fd",&floppy_fops)) {
+ printk("Unable to get major %d for floppy\n",FLOPPY_MAJOR);
err = -EBUSY;
goto out;
}

for (i=0; i<N_DRIVE; i++) {
- disks[i]->major = MAJOR_NR;
+ disks[i]->major = FLOPPY_MAJOR;
disks[i]->first_minor = TOMINOR(i);
disks[i]->fops = &floppy_fops;
sprintf(disks[i]->disk_name, "fd%d", i);
}

- blk_register_region(MKDEV(MAJOR_NR, 0), 256, THIS_MODULE,
+ blk_register_region(MKDEV(FLOPPY_MAJOR, 0), 256, THIS_MODULE,
floppy_find, NULL, NULL);

for (i=0; i<256; i++)
@@ -4401,8 +4401,8 @@
out1:
del_timer(&fd_timeout);
out2:
- blk_unregister_region(MKDEV(MAJOR_NR, 0), 256);
- unregister_blkdev(MAJOR_NR,"fd");
+ blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256);
+ unregister_blkdev(FLOPPY_MAJOR,"fd");
blk_cleanup_queue(&floppy_queue);
out:
for (i=0; i<N_DRIVE; i++)
@@ -4592,6 +4592,18 @@

char *floppy;

+static void unregister_devfs_entries (int drive)
+{
+ int i;
+
+ if (UDP->cmos < NUMBER(default_drive_params)) {
+ i = 0;
+ do {
+ devfs_remove("floppy/%d%s", drive, table[table_sup[UDP->cmos][i]]);
+ } while (table_sup[UDP->cmos][i++]);
+ }
+}
+
static void __init parse_floppy_cfg_string(char *cfg)
{
char *ptr;
@@ -4621,15 +4633,17 @@
int drive;

platform_device_unregister(&floppy_device);
- devfs_unregister (devfs_handle);
- blk_unregister_region(MKDEV(MAJOR_NR, 0), 256);
- unregister_blkdev(MAJOR_NR, "fd");
+ blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256);
+ unregister_blkdev(FLOPPY_MAJOR, "fd");
for (drive = 0; drive < N_DRIVE; drive++) {
if ((allowed_drive_mask & (1 << drive)) &&
- fdc_state[FDC(drive)].version != FDC_NONE)
+ fdc_state[FDC(drive)].version != FDC_NONE) {
del_gendisk(disks[drive]);
+ unregister_devfs_entries(drive);
+ }
put_disk(disks[drive]);
}
+ devfs_remove("floppy");

blk_cleanup_queue(&floppy_queue);
/* eject disk, if any */

2003-01-19 06:45:15

by Osamu Tomita

[permalink] [raw]
Subject: [PATCHSET] PC-9800 sub-arch (19/29) ac-update

This is patchset to support NEC PC-9800 subarchitecture
against 2.5.59 (19/29).

Updates files under arch/i386/mach-pc9800 in 2.5.50-ac1.

diff -Nru linux-2.5.50-ac1/arch/i386/mach-pc9800/Makefile linux98-2.5.52/arch/i386/mach-pc9800/Makefile
--- linux-2.5.50-ac1/arch/i386/mach-pc9800/Makefile 2002-12-17 09:07:10.000000000 +0900
+++ linux98-2.5.52/arch/i386/mach-pc9800/Makefile 2002-12-16 11:07:52.000000000 +0900
@@ -1,15 +1,7 @@
#
# Makefile for the linux kernel.
#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
-# Note 2! The CFLAGS definitions are now in the main makefile...

EXTRA_CFLAGS += -I../kernel
-export-objs :=
-
-obj-y := setup.o

-include $(TOPDIR)/Rules.make
+obj-y := setup.o topology.o
diff -Nru linux-2.5.50-ac1/arch/i386/mach-pc9800/setup.c linux98-2.5.52/arch/i386/mach-pc9800/setup.c
--- linux-2.5.50-ac1/arch/i386/mach-pc9800/setup.c 2002-12-11 13:09:57.000000000 +0900
+++ linux98-2.5.52/arch/i386/mach-pc9800/setup.c 2002-12-20 15:08:00.000000000 +0900
@@ -8,6 +8,7 @@
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
+#include <linux/apm_bios.h>
#include <asm/setup.h>
#include <asm/arch_hooks.h>

@@ -16,9 +17,6 @@
unsigned char table[0];
};

-/* Indicates PC-9800 architecture No:0 Yes:1 */
-extern int pc98;
-
/**
* pre_intr_init_hook - initialisation prior to setting up interrupt vectors
*
@@ -68,7 +66,9 @@
{
SYS_DESC_TABLE.length = 0;
MCA_bus = 0;
- pc98 = 1;
+ /* In PC-9800, APM BIOS version is written in BCD...?? */
+ APM_BIOS_INFO.version = (APM_BIOS_INFO.version & 0xff00)
+ | ((APM_BIOS_INFO.version & 0x00f0) >> 4);
}

/**
diff -Nru linux-2.5.52/arch/i386/mach-pc9800/topology.c linux98-2.5.52/arch/i386/mach-pc9800/topology.c
--- linux-2.5.52/arch/i386/mach-pc9800/topology.c 1970-01-01 09:00:00.000000000 +0900
+++ linux98-2.5.52/arch/i386/mach-pc9800/topology.c 2002-12-16 11:08:16.000000000 +0900
@@ -0,0 +1,68 @@
+/*
+ * arch/i386/mach-generic/topology.c - Populate driverfs with topology information
+ *
+ * Written by: Matthew Dobson, IBM Corporation
+ * Original Code: Paul Dorwin, IBM Corporation, Patrick Mochel, OSDL
+ *
+ * Copyright (C) 2002, IBM Corp.
+ *
+ * All rights reserved.
+ *
+ * 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, GOOD TITLE or
+ * NON INFRINGEMENT. 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send feedback to <[email protected]>
+ */
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <asm/cpu.h>
+
+struct i386_cpu cpu_devices[NR_CPUS];
+
+#ifdef CONFIG_NUMA
+#include <linux/mmzone.h>
+#include <asm/node.h>
+#include <asm/memblk.h>
+
+struct i386_node node_devices[MAX_NUMNODES];
+struct i386_memblk memblk_devices[MAX_NR_MEMBLKS];
+
+static int __init topology_init(void)
+{
+ int i;
+
+ for (i = 0; i < num_online_nodes(); i++)
+ arch_register_node(i);
+ for (i = 0; i < NR_CPUS; i++)
+ if (cpu_possible(i)) arch_register_cpu(i);
+ for (i = 0; i < num_online_memblks(); i++)
+ arch_register_memblk(i);
+ return 0;
+}
+
+#else /* !CONFIG_NUMA */
+
+static int __init topology_init(void)
+{
+ int i;
+
+ for (i = 0; i < NR_CPUS; i++)
+ if (cpu_possible(i)) arch_register_cpu(i);
+ return 0;
+}
+
+#endif /* CONFIG_NUMA */
+
+subsys_initcall(topology_init);

2003-01-19 06:42:13

by Osamu Tomita

[permalink] [raw]
Subject: [PATCHSET] PC-9800 sub-arch (15/29) ac-update

This is patchset to support NEC PC-9800 subarchitecture
against 2.5.59 (15/29).

Updates input driver for PC98 in 2.5.50-ac1.

diff -Nru linux-2.5.50-ac1/drivers/input/keyboard/Kconfig linux98-2.5.54/drivers/input/keyboard/Kconfig
--- linux-2.5.50-ac1/drivers/input/keyboard/Kconfig 2003-01-04 10:47:57.000000000 +0900
+++ linux98-2.5.54/drivers/input/keyboard/Kconfig 2003-01-04 15:28:14.000000000 +0900
@@ -92,7 +92,7 @@

config KEYBOARD_98KBD
tristate "NEC PC-9800 Keyboard support"
- depends on PC9800 && INPUT && INPUT_KEYBOARD && SERIO
+ depends on X86_PC9800 && INPUT && INPUT_KEYBOARD && SERIO
help
Say Y here if you want to use the NEC PC-9801/PC-9821 keyboard (or
compatible) on your system.
diff -Nru linux-2.5.50-ac1/drivers/input/mouse/98busmouse.c linux98-2.5.52/drivers/input/mouse/98busmouse.c
--- linux-2.5.50-ac1/drivers/input/mouse/98busmouse.c 2002-12-17 09:07:10.000000000 +0900
+++ linux98-2.5.52/drivers/input/mouse/98busmouse.c 2002-12-17 13:58:53.000000000 +0900
@@ -31,15 +31,16 @@
*
*/

-#include <asm/io.h>
-#include <asm/irq.h>
-
#include <linux/config.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/input.h>
+#include <linux/interrupt.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>

MODULE_AUTHOR("Osamu Tomita <[email protected]>");
MODULE_DESCRIPTION("PC-9801 busmouse driver");
diff -Nru linux-2.5.50-ac1/drivers/input/mouse/Kconfig linux98-2.5.54/drivers/input/mouse/Kconfig
--- linux-2.5.50-ac1/drivers/input/mouse/Kconfig 2003-01-04 10:47:57.000000000 +0900
+++ linux98-2.5.54/drivers/input/mouse/Kconfig 2003-01-04 15:31:55.000000000 +0900
@@ -123,7 +123,7 @@

config MOUSE_PC9800
tristate "NEC PC-9800 busmouse"
- depends on PC9800 && INPUT && INPUT_MOUSE && ISA
+ depends on X86_PC9800 && INPUT && INPUT_MOUSE && ISA
help
Say Y here if you have NEC PC-9801/PC-9821 computer and want its
native mouse supported.
diff -Nru linux-2.5.50-ac1/drivers/input/serio/98kbd-io.c linux98-2.5.52/drivers/input/serio/98kbd-io.c
--- linux-2.5.50-ac1/drivers/input/serio/98kbd-io.c 2002-12-17 09:07:10.000000000 +0900
+++ linux98-2.5.52/drivers/input/serio/98kbd-io.c 2002-12-17 14:01:05.000000000 +0900
@@ -11,16 +11,17 @@
* the Free Software Foundation.
*/

-#include <asm/io.h>
-
+#include <linux/config.h>
#include <linux/delay.h>
#include <linux/module.h>
+#include <linux/interrupt.h>
#include <linux/ioport.h>
-#include <linux/config.h>
#include <linux/init.h>
#include <linux/serio.h>
#include <linux/sched.h>

+#include <asm/io.h>
+
MODULE_AUTHOR("Osamu Tomita <[email protected]>");
MODULE_DESCRIPTION("NEC PC-9801 keyboard controller driver");
MODULE_LICENSE("GPL");
diff -Nru linux-2.5.50-ac1/drivers/input/serio/Kconfig linux98-2.5.57/drivers/input/serio/Kconfig
--- linux-2.5.50-ac1/drivers/input/serio/Kconfig 2003-01-14 09:33:34.000000000 +0900
+++ linux98-2.5.57/drivers/input/serio/Kconfig 2003-01-14 10:19:27.000000000 +0900
@@ -109,7 +109,7 @@

config SERIO_98KBD
tristate "NEC PC-9800 keyboard controller"
- depends on PC9800 && SERIO
+ depends on X86_PC9800 && SERIO
help
Say Y here if you have the NEC PC-9801/PC-9821 and want to use its
standard keyboard connected to its keyboard controller.

2003-01-19 06:53:23

by Osamu Tomita

[permalink] [raw]
Subject: [PATCHSET] PC-9800 sub-arch (28/29) SMP

This is patchset to support NEC PC-9800 subarchitecture
against 2.5.59 (28/29).

SMP support.

diff -Nru linux-2.5.50-ac1/arch/i386/kernel/mpparse.c linux98-2.5.54/arch/i386/kernel/mpparse.c
--- linux-2.5.50-ac1/arch/i386/kernel/mpparse.c 2003-01-04 20:02:50.000000000 +0900
+++ linux98-2.5.54/arch/i386/kernel/mpparse.c 2003-01-04 20:02:53.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;
@@ -653,7 +654,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");
@@ -707,8 +709,23 @@
printk("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;
}
@@ -751,11 +768,12 @@
* 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);
- if (smp_found_config)
- printk(KERN_WARNING "WARNING: MP table in the EBDA can be UNSAFE, contact [email protected] if you experience SMP problems!\n");
+ address = get_bios_ebda();
+ if (address) {
+ smp_scan_config(address, 0x400);
+ if (smp_found_config)
+ printk(KERN_WARNING "WARNING: MP table in the EBDA can be UNSAFE, contact [email protected] if you experience SMP problems!\n");
+ }
}


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/arch/i386/kernel/smpboot.c linux98/arch/i386/kernel/smpboot.c
--- linux/arch/i386/kernel/smpboot.c 2003-01-09 13:04:14.000000000 +0900
+++ linux98/arch/i386/kernel/smpboot.c 2003-01-10 11:29:24.000000000 +0900
@@ -825,13 +825,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-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 */

2003-01-19 06:47:17

by Osamu Tomita

[permalink] [raw]
Subject: [PATCHSET] PC-9800 sub-arch (18/29) ac-update

This is patchset to support NEC PC-9800 subarchitecture
against 2.5.59 (18/29).

Updates bakward comptible printer driver for PC98 in 2.5.50-ac1.

diff -Nru linux-2.5.50-ac1/drivers/char/lp_old98.c linux98-2.5.54/drivers/char/lp_old98.c
--- linux-2.5.50-ac1/drivers/char/lp_old98.c 2002-12-17 22:33:32.000000000 +0900
+++ linux98-2.5.54/drivers/char/lp_old98.c 2003-01-04 13:31:13.000000000 +0900
@@ -10,45 +10,35 @@
* generic PC printer port driver.
*/

-#include <linux/init.h>
#include <linux/module.h>
+#include <linux/init.h>
#include <linux/config.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/sched.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
#include <linux/ioport.h>
#include <linux/fcntl.h>
#include <linux/delay.h>
#include <linux/console.h>
#include <linux/version.h>
+#include <linux/fs.h>

#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/system.h>

-#if !defined(CONFIG_PC9800) && !defined(CONFIG_PC98)
-#error This driver works only for NEC PC-9800 series
-#endif
-
-#if LINUX_VERSION_CODE < 0x20200
-# define LP_STATS
-#endif
-
-#if LINUX_VERSION_CODE >= 0x2030b
-# define CONFIG_RESOURCE98
-#endif
-
#include <linux/lp.h>

/*
* I/O port numbers
*/
#define LP_PORT_DATA 0x40
-#define LP_PORT_STATUS (LP_PORT_DATA+2)
-#define LP_PORT_STROBE (LP_PORT_DATA+4)
-#define LP_PORT_CONTROL (LP_PORT_DATA+6)
+#define LP_PORT_STATUS (LP_PORT_DATA + 2)
+#define LP_PORT_STROBE (LP_PORT_DATA + 4)
+#define LP_PORT_CONTROL (LP_PORT_DATA + 6)

#define LP_PORT_H98MODE 0x0448
#define LP_PORT_EXTMODE 0x0149
@@ -73,27 +63,27 @@
/* PC-9800s have at least and at most one old-style printer port. */
static struct lp_struct lp = {
/* Following `TAG: INITIALIZER' notations are GNU CC extension. */
- flags: LP_EXIST | LP_ABORTOPEN,
- chars: LP_INIT_CHAR,
- time: LP_INIT_TIME,
- wait: LP_INIT_WAIT,
+ .flags = LP_EXIST | LP_ABORTOPEN,
+ .chars = LP_INIT_CHAR,
+ .time = LP_INIT_TIME,
+ .wait = LP_INIT_WAIT,
};

static int dc1_check = 1000;
+static spinlock_t lp_old98_lock = SPIN_LOCK_UNLOCKED;

-#undef LP_OLD98_DEBUG

-#ifndef __udelay_val
-# define __udelay_val current_cpu_data.loops_per_sec
-#endif
+#undef LP_OLD98_DEBUG

static inline void nanodelay(unsigned long nanosecs) /* Evil ? */
{
- if( nanosecs ) {
- nanosecs *= (unsigned long)((1ULL << 40) / 1000000000ULL);
- __asm__("mul%L2 %2"
- : "=d"(nanosecs) : "a"(nanosecs), "g"(__udelay_val));
- __delay(nanosecs >> 8);
+ if (nanosecs) {
+ int d0;
+ nanosecs = (nanosecs * 512UL) / 119UL;
+ __asm__("mull %0"
+ :"=d" (nanosecs), "=&a" (d0)
+ :"1" (nanosecs),"0" (current_cpu_data.loops_per_jiffy));
+ __delay(nanosecs * HZ);
}
}

@@ -118,15 +108,14 @@
}
}

-static inline int
-lp_old98_wait_ready(void)
+static inline int lp_old98_wait_ready(void)
{
struct timer_list timer;

init_timer(&timer);
timer.function = lp_old98_timer_function;
timer.expires = jiffies + 1;
- timer.data = (unsigned long) &timer;
+ timer.data = (unsigned long)&timer;
add_timer(&timer);
interruptible_sleep_on(&lp_old98_waitq);
del_timer(&timer);
@@ -140,7 +129,7 @@
int tmp;
#endif

- while( !(inb(LP_PORT_STATUS) & LP_MASK_nBUSY) ) {
+ while (!(inb(LP_PORT_STATUS) & LP_MASK_nBUSY)) {
count++;
if (count >= lp.chars)
return 0;
@@ -153,7 +142,7 @@
* Update lp statsistics here (and between next two outb()'s).
* Time to compute it is part of storobe delay.
*/
- if( count > lp.stats.maxwait ) {
+ if (count > lp.stats.maxwait) {
#ifdef LP_OLD98_DEBUG
printk(KERN_DEBUG "lp_old98: success after %d counts.\n",
count);
@@ -162,7 +151,7 @@
}
count *= 256;
tmp = count - lp.stats.meanwait;
- if( tmp < 0 )
+ if (tmp < 0)
tmp = -tmp;
#endif
nanodelay(lp.wait);
@@ -173,7 +162,7 @@
#ifdef LP_STATS
lp.stats.meanwait = (255 * lp.stats.meanwait + count + 128) / 256;
lp.stats.mdev = (127 * lp.stats.mdev + tmp + 64) / 128;
- lp.stats.chars++;
+ lp.stats.chars ++;
#endif

nanodelay(lp.wait);
@@ -199,7 +188,7 @@
return -EFAULT;

#ifdef LP_STATS
- if( jiffies - lp.lastcall > lp.time )
+ if (jiffies - lp.lastcall > lp.time)
lp.runchars = 0;
lp.lastcall = jiffies;
#endif
@@ -212,17 +201,17 @@
if (__copy_from_user(lp.lp_buffer, buf, copy_size))
return -EFAULT;

- while( bytes_written < copy_size ) {
- if( lp_old98_char(lp.lp_buffer[bytes_written]) )
- bytes_written++;
+ while (bytes_written < copy_size) {
+ if (lp_old98_char(lp.lp_buffer[bytes_written]))
+ bytes_written ++;
else {
#ifdef LP_STATS
int rc = lp.runchars + bytes_written;

- if( rc > lp.stats.maxrun )
+ if (rc > lp.stats.maxrun)
lp.stats.maxrun = rc;

- lp.stats.sleeps++;
+ lp.stats.sleeps ++;
#endif
#ifdef LP_OLD98_DEBUG
printk(KERN_DEBUG
@@ -243,7 +232,7 @@
lp.runchars += bytes_written;
#endif
count -= bytes_written;
- } while( count > 0 );
+ } while (count > 0);

return total_bytes_written;
}
@@ -256,16 +245,16 @@

static int lp_old98_open(struct inode * inode, struct file * file)
{
- if( MINOR(inode->i_rdev) != 0 )
+ if (minor(inode->i_rdev) != 0)
return -ENXIO;
- if( lp.flags & LP_BUSY )
+ if (lp.flags & LP_BUSY)
return -EBUSY;

if ((lp.lp_buffer = kmalloc(LP_BUFFER_SIZE, GFP_KERNEL)) == NULL)
return -ENOMEM;

if (dc1_check && (lp.flags & LP_ABORTOPEN)
- && !(file->f_flags & O_NONBLOCK) ) {
+ && !(file->f_flags & O_NONBLOCK)) {
/*
* Check whether printer is on-line.
* PC-9800's old style port have only BUSY# as status input,
@@ -284,22 +273,22 @@
* `PC-9801 Super Technique', Ascii, 1992.
*/
int count;
- unsigned long eflags;
+ unsigned long flags;

- save_flags(eflags);
- cli(); /* interrupts while check is fairly bad */
+ /* interrupts while check is fairly bad */
+ spin_lock_irqsave(&lp_old98_lock, flags);

if (!lp_old98_char(DC1)) {
- restore_flags(eflags);
+ spin_unlock_irqrestore(&lp_old98_lock, flags);
return -EBUSY;
}
count = (unsigned int)dc1_check > 10000 ? 10000 : dc1_check;
- while( inb(LP_PORT_STATUS) & LP_MASK_nBUSY )
- if( --count == 0 ) {
- restore_flags(eflags);
+ while (inb(LP_PORT_STATUS) & LP_MASK_nBUSY)
+ if (--count == 0) {
+ spin_unlock_irqrestore(&lp_old98_lock, flags);
return -ENODEV;
}
- restore_flags(eflags);
+ spin_unlock_irqrestore(&lp_old98_lock, flags);
}

lp.flags |= LP_BUSY;
@@ -329,14 +318,14 @@
{
unsigned char data;

- if( (data = inb(LP_PORT_EXTMODE)) != 0xFF && (data & 0x10) ) {
+ if ((data = inb(LP_PORT_EXTMODE)) != 0xFF && (data & 0x10)) {
printk(KERN_INFO
"lp_old98: shutting down extended parallel port mode...\n");
outb(data & ~0x10, LP_PORT_EXTMODE);
}
#ifdef PC98_HW_H98
- if( (pc98_hw_flags & PC98_HW_H98)
- && ((data = inb(LP_PORT_H98MODE)) & 0x01) ) {
+ if ((pc98_hw_flags & PC98_HW_H98)
+ && ((data = inb(LP_PORT_H98MODE)) & 0x01)) {
printk(KERN_INFO
"lp_old98: shutting down H98 full centronics mode...\n");
outb(data & ~0x01, LP_PORT_H98MODE);
@@ -358,7 +347,7 @@
{
int retval = 0;

- switch ( command ) {
+ switch (command) {
case LPTIME:
lp.time = arg * HZ/100;
break;
@@ -366,13 +355,13 @@
lp.chars = arg;
break;
case LPABORT:
- if( arg )
+ if (arg)
lp.flags |= LP_ABORT;
else
lp.flags &= ~LP_ABORT;
break;
case LPABORTOPEN:
- if( arg )
+ if (arg)
lp.flags |= LP_ABORTOPEN;
else
lp.flags &= ~LP_ABORTOPEN;
@@ -402,8 +391,8 @@
break;
#ifdef LP_STATS
case LPGETSTATS:
- if( copy_to_user((struct lp_stats *)arg, &lp.stats,
- sizeof(struct lp_stats)) )
+ if (copy_to_user((struct lp_stats *)arg, &lp.stats,
+ sizeof(struct lp_stats)))
retval = -EFAULT;
else if (suser())
memset(&lp.stats, 0, sizeof(struct lp_stats));
@@ -420,13 +409,13 @@
}

static struct file_operations lp_old98_fops = {
- owner: THIS_MODULE,
- llseek: lp_old98_llseek,
- read: NULL,
- write: lp_old98_write,
- ioctl: lp_old98_ioctl,
- open: lp_old98_open,
- release:lp_old98_release,
+ .owner = THIS_MODULE,
+ .llseek = lp_old98_llseek,
+ .read = NULL,
+ .write = lp_old98_write,
+ .ioctl = lp_old98_ioctl,
+ .open = lp_old98_open,
+ .release = lp_old98_release,
};

/*
@@ -494,15 +483,15 @@

static kdev_t lp_old98_console_device(struct console *console)
{
- return MKDEV(LP_MAJOR, 0);
+ return mk_kdev(LP_MAJOR, 0);
}

static struct console lp_old98_console = {
- name: "lp_old98",
- write: lp_old98_console_write,
- device: lp_old98_console_device,
- flags: CON_PRINTBUFFER,
- index: -1,
+ .name = "lp_old98",
+ .write = lp_old98_console_write,
+ .device = lp_old98_console_device,
+ .flags = CON_PRINTBUFFER,
+ .index = -1,
};

#endif /* console on lp_old98 */
@@ -544,7 +533,7 @@
* but for locking out other printer drivers...
*/
#ifdef PC98_HW_H98
- if( pc98_hw_flags & PC98_HW_H98 )
+ if (pc98_hw_flags & PC98_HW_H98)
request_region(LP_PORT_H98MODE, 1, "lp_old98");
#endif
request_region(LP_PORT_EXTMODE, 1, "lp_old98");
@@ -565,7 +554,7 @@
release_region(LP_PORT_STATUS, 1);
release_region(LP_PORT_STROBE, 1);
#ifdef PC98_HW_H98
- if( pc98_hw_flags & PC98_HW_H98 )
+ if (pc98_hw_flags & PC98_HW_H98)
release_region(LP_PORT_H98MODE, 1);
#endif
release_region(LP_PORT_EXTMODE, 1);
@@ -573,5 +562,7 @@

MODULE_PARM(dc1_check, "1i");
MODULE_AUTHOR("Kousuke Takai <[email protected]>");
+MODULE_DESCRIPTION("PC-9800 old printer port driver");
+MODULE_LICENSE("GPL");

#endif

2003-01-19 06:33:19

by Osamu Tomita

[permalink] [raw]
Subject: [PATCHSET] PC-9800 sub-arch (8/29) network cards

This is patchset to support NEC PC-9800 subarchitecture
against 2.5.59 (8/29).

C-bus(PC98's legacy bus like ISA) network cards support.

diff -Nru linux-2.5.59/drivers/net/3c509.c linux98-2.5.59/drivers/net/3c509.c
--- linux-2.5.59/drivers/net/3c509.c 2003-01-17 13:22:13.000000000 +0900
+++ linux98-2.5.59/drivers/net/3c509.c 2003-01-17 13:45:53.000000000 +0900
@@ -56,6 +56,10 @@
v1.19b 08Nov2002 Marc Zyngier <[email protected]>
- 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"
@@ -178,7 +182,11 @@
struct eisa_device *edev;
#endif
};
+#ifdef CONFIG_X86_PC9800
+static int id_port __initdata = 0x71d0;
+#else
static int id_port __initdata = 0x110; /* Start with 0x110 to avoid new sound cards.*/
+#endif
static struct net_device *el3_root_dev;

static ushort id_read_eeprom(int index);
@@ -433,6 +441,7 @@
}
#endif /* CONFIG_MCA */

+#ifndef CONFIG_X86_PC9800
#ifdef __ISAPNP__
if (nopnp == 1)
goto no_pnp;
@@ -488,6 +497,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
@@ -518,6 +528,7 @@
phys_addr[i] = htons(id_read_eeprom(i));
}

+#ifndef CONFIG_X86_PC9800
#ifdef __ISAPNP__
if (nopnp == 0) {
/* The ISA PnP 3c509 cards respond to the ID sequence.
@@ -539,11 +550,16 @@
}
}
#endif /* __ISAPNP__ */
+#endif /* !CONFIG_X86_PC9800 */

{
unsigned int iobase = id_read_eeprom(8);
if_port = iobase >> 14;
+#ifndef CONFIG_X86_PC9800
ioaddr = 0x200 + ((iobase & 0x1f) << 4);
+#else
+ ioaddr = 0x40d0 + ((iobase & 0x1f) << 8);
+#endif
}
irq = id_read_eeprom(9) >> 12;

@@ -570,7 +586,15 @@
outb(0xd0 + ++current_tag, id_port);

/* Activate the adaptor at the EEPROM location. */
+#ifndef CONFIG_X86_PC9800
outb((ioaddr >> 4) | 0xe0, id_port);
+#else
+ outb((ioaddr >> 8) | 0xe0, id_port);
+ if (irq == 7)
+ irq = 6;
+ else if (irq == 15)
+ irq = 13;
+#endif

EL3WINDOW(0);
if (inw(ioaddr) != 0x6d50) {
@@ -1358,7 +1382,18 @@
outw(0x0001, ioaddr + 4);

/* Set the IRQ line. */
+#ifndef CONFIG_X86_PC9800
outw((dev->irq << 12) | 0x0f00, ioaddr + WN0_IRQ);
+#else
+ {
+ int irq = dev->irq;
+ if (irq == 6)
+ irq = 7;
+ else if (irq == 13)
+ irq = 15;
+ outw((irq << 12) | 0x0f00, ioaddr + WN0_IRQ);
+ }
+#endif

/* Set the station address in window 2 each time opened. */
EL3WINDOW(2);
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.42/drivers/net/Kconfig linux98-2.5.42/drivers/net/Kconfig
--- linux-2.5.50/drivers/net/Kconfig 2003-01-09 13:04:24.000000000 +0900
+++ linux98-2.5.50/drivers/net/Kconfig 2003-01-10 10:15:57.000000000 +0900
@@ -654,7 +654,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
@@ -903,7 +903,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
@@ -949,7 +949,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
@@ -1147,6 +1147,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.42/drivers/net/Makefile linux98-2.5.42/drivers/net/Makefile
--- linux-2.5.42/drivers/net/Makefile 2002-11-28 07:35:54.000000000 +0900
+++ linux98-2.5.42/drivers/net/Makefile 2002-12-12 11:06:46.000000000 +0900
@@ -90,6 +90,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.59/drivers/net/Space.c linux98-2.5.59/drivers/net/Space.c
--- linux-2.5.59/drivers/net/Space.c 2003-01-17 13:22:13.000000000 +0900
+++ linux98-2.5.59/drivers/net/Space.c 2003-01-17 13:45:53.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.58/drivers/net/ne.c linux98-2.5.58/drivers/net/ne.c
--- linux-2.5.58/drivers/net/ne.c 2003-01-14 14:58:39.000000000 +0900
+++ linux98-2.5.58/drivers/net/ne.c 2003-01-14 23:04:58.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,63 @@
int wordlength = 2;
const char *name = NULL;
int start_page, stop_page;
+#ifndef CONFIG_NET_CBUS
int neX000, ctron, copam, bad_card;
+#else
+ int neX000, bad_card;
+#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 +446,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 +469,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 +564,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 +613,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 +664,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 +706,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 +736,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 +776,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 +810,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 +855,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 +868,15 @@
return;
}
ei_status.dmaing |= 0x01;
+
+#ifdef CONFIG_NET_CBUS
+ /* derived from ICM-patch */
+ /* round up count to a word */
+ if (count & 1) {
+ count++;
+ }
+#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 +934,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?
@@ -735,16 +1037,25 @@
#ifdef MODULE
#define MAX_NE_CARDS 4 /* Max number of NE cards per module */
static struct net_device dev_ne[MAX_NE_CARDS];
-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 */
+static int __initdata io[MAX_NE_CARDS];
+static int __initdata irq[MAX_NE_CARDS];
+static int __initdata bad[MAX_NE_CARDS]; /* 0xbad = bad sig or no reset ack */
+#ifdef CONFIG_NET_CBUS
+static int __initdata 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 +1073,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 +1105,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 */

2003-01-19 06:49:53

by Osamu Tomita

[permalink] [raw]
Subject: [PATCHSET] PC-9800 sub-arch (23/29) PCMCIA

This is patchset to support NEC PC-9800 subarchitecture
against 2.5.59 (23/29).

PCMCIA (16bits) support.

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;

2003-01-19 06:42:53

by Osamu Tomita

[permalink] [raw]
Subject: [PATCHSET] PC-9800 sub-arch (16/29) input

This is patchset to support NEC PC-9800 subarchitecture
against 2.5.59 (16/29).

Beep driver and keyboard support files.

diff -Nru linux/drivers/input/misc/98spkr.c linux98/drivers/input/misc/98spkr.c
--- linux/drivers/input/misc/98spkr.c 1970-01-01 09:00:00.000000000 +0900
+++ linux98/drivers/input/misc/98spkr.c 2002-11-16 13:05:59.000000000 +0900
@@ -0,0 +1,95 @@
+/*
+ * PC-9800 Speaker beeper driver for Linux
+ *
+ * Copyright (c) 2002 Osamu Tomita
+ * Copyright (c) 2002 Vojtech Pavlik
+ * Copyright (c) 1992 Orest Zborowski
+ *
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <asm/io.h>
+
+MODULE_AUTHOR("Osamu Tomita <[email protected]>");
+MODULE_DESCRIPTION("PC-9800 Speaker beeper driver");
+MODULE_LICENSE("GPL");
+
+static char spkr98_name[] = "PC-9801 Speaker";
+static char spkr98_phys[] = "isa3fdb/input0";
+static struct input_dev spkr98_dev;
+
+spinlock_t i8253_beep_lock = SPIN_LOCK_UNLOCKED;
+
+static int spkr98_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
+{
+ unsigned int count = 0;
+ unsigned long flags;
+
+ if (type != EV_SND)
+ return -1;
+
+ switch (code) {
+ case SND_BELL: if (value) value = 1000;
+ case SND_TONE: break;
+ default: return -1;
+ }
+
+ if (value > 20 && value < 32767)
+ count = CLOCK_TICK_RATE / value;
+
+ spin_lock_irqsave(&i8253_beep_lock, flags);
+
+ if (count) {
+ outb(0x76, 0x3fdf);
+ outb(0, 0x5f);
+ outb(count & 0xff, 0x3fdb);
+ outb(0, 0x5f);
+ outb((count >> 8) & 0xff, 0x3fdb);
+ /* beep on */
+ outb(6, 0x37);
+ } else {
+ /* beep off */
+ outb(7, 0x37);
+ }
+
+ spin_unlock_irqrestore(&i8253_beep_lock, flags);
+
+ return 0;
+}
+
+static int __init spkr98_init(void)
+{
+ spkr98_dev.evbit[0] = BIT(EV_SND);
+ spkr98_dev.sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
+ spkr98_dev.event = spkr98_event;
+
+ spkr98_dev.name = spkr98_name;
+ spkr98_dev.phys = spkr98_phys;
+ spkr98_dev.id.bustype = BUS_ISA;
+ spkr98_dev.id.vendor = 0x001f;
+ spkr98_dev.id.product = 0x0001;
+ spkr98_dev.id.version = 0x0100;
+
+ input_register_device(&spkr98_dev);
+
+ printk(KERN_INFO "input: %s\n", spkr98_name);
+
+ return 0;
+}
+
+static void __exit spkr98_exit(void)
+{
+ input_unregister_device(&spkr98_dev);
+}
+
+module_init(spkr98_init);
+module_exit(spkr98_exit);
diff -Nru linux/drivers/input/misc/Kconfig linux98/drivers/input/misc/Kconfig
--- linux/drivers/input/misc/Kconfig 2002-11-11 12:28:11.000000000 +0900
+++ linux98/drivers/input/misc/Kconfig 2002-11-16 13:08:21.000000000 +0900
@@ -44,6 +44,10 @@
tristate "M68k Beeper support"
depends on M68K && INPUT && INPUT_MISC

+config INPUT_98SPKR
+ tristate "PC-9800 Speaker support"
+ depends on X86_PC9800 && INPUT && INPUT_MISC
+
config INPUT_UINPUT
tristate "User level driver support"
depends on INPUT && INPUT_MISC
diff -Nru linux/drivers/input/misc/Makefile linux98/drivers/input/misc/Makefile
--- linux/drivers/input/misc/Makefile 2002-12-10 11:46:11.000000000 +0900
+++ linux98/drivers/input/misc/Makefile 2002-12-16 16:00:39.000000000 +0900
@@ -7,5 +7,6 @@
obj-$(CONFIG_INPUT_SPARCSPKR) += sparcspkr.o
obj-$(CONFIG_INPUT_PCSPKR) += pcspkr.o
obj-$(CONFIG_INPUT_M68K_BEEP) += m68kspkr.o
+obj-$(CONFIG_INPUT_98SPKR) += 98spkr.o
obj-$(CONFIG_INPUT_UINPUT) += uinput.o
obj-$(CONFIG_INPUT_GSC) += gsc_ps2.o
diff -Nru linux/drivers/char/keyboard.c linux98/drivers/char/keyboard.c
--- linux/drivers/char/keyboard.c 2002-12-10 11:45:54.000000000 +0900
+++ linux98/drivers/char/keyboard.c 2002-12-16 16:00:39.000000000 +0900
@@ -57,7 +57,11 @@
* Some laptops take the 789uiojklm,. keys as number pad when NumLock is on.
* This seems a good reason to start with NumLock off.
*/
+#ifndef CONFIG_X86_PC9800
#define KBD_DEFLEDS 0
+#else
+#define KBD_DEFLEDS (1 << VC_NUMLOCK)
+#endif
#endif

#ifndef KBD_DEFLOCK
diff -Nru linux/include/linux/kbd_kern.h linux98/include/linux/kbd_kern.h
--- linux/include/linux/kbd_kern.h 2002-10-19 13:02:28.000000000 +0900
+++ linux98/include/linux/kbd_kern.h 2002-10-27 10:23:23.000000000 +0900
@@ -43,11 +43,12 @@
#define LED_SHOW_IOCTL 1 /* only change leds upon ioctl */
#define LED_SHOW_MEM 2 /* `heartbeat': peek into memory */

- unsigned char ledflagstate:3; /* flags, not lights */
- unsigned char default_ledflagstate:3;
+ unsigned char ledflagstate:4; /* flags, not lights */
+ unsigned char default_ledflagstate:4;
#define VC_SCROLLOCK 0 /* scroll-lock mode */
#define VC_NUMLOCK 1 /* numeric lock mode */
#define VC_CAPSLOCK 2 /* capslock mode */
+#define VC_KANALOCK 3 /* kanalock mode */

unsigned char kbdmode:2; /* one 2-bit value */
#define VC_XLATE 0 /* translate keycodes using keymap */
diff -Nru linux/include/linux/keyboard.h linux98/include/linux/keyboard.h
--- linux/include/linux/keyboard.h 2002-10-19 13:01:13.000000000 +0900
+++ linux98/include/linux/keyboard.h 2002-10-21 15:59:48.000000000 +0900
@@ -9,6 +9,7 @@
#define KG_ALT 3
#define KG_ALTGR 1
#define KG_SHIFTL 4
+#define KG_KANASHIFT 4
#define KG_SHIFTR 5
#define KG_CTRLL 6
#define KG_CTRLR 7

2003-01-19 06:37:29

by Osamu Tomita

[permalink] [raw]
Subject: [PATCHSET] PC-9800 sub-arch (12/29) ac-update

This is patchset to support NEC PC-9800 subarchitecture
against 2.5.59 (12/29).

Updates arch/i386/kernel/i8259.c in 2.5.50-ac1.

diff -Nru linux-2.5.50-ac1/arch/i386/kernel/i8259.c linux98-2.5.54/arch/i386/kernel/i8259.c
--- linux-2.5.50-ac1/arch/i386/kernel/i8259.c 2003-01-04 10:47:57.000000000 +0900
+++ linux98-2.5.54/arch/i386/kernel/i8259.c 2003-01-04 13:23:33.000000000 +0900
@@ -331,7 +331,7 @@
static void math_error_irq(int cpl, void *dev_id, struct pt_regs *regs)
{
extern void math_error(void *);
-#ifndef CONFIG_PC9800
+#ifndef CONFIG_X86_PC9800
outb(0,0xF0);
#endif
if (ignore_fpu_irq || !boot_cpu_data.hard_math)

2003-01-19 06:48:02

by Osamu Tomita

[permalink] [raw]
Subject: [PATCHSET] PC-9800 sub-arch (22/29) PCI

This is patchset to support NEC PC-9800 subarchitecture
against 2.5.59 (22/29).

PCI support.

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;
+#ifndef CONFIG_X86_PC9800
#define PCIBIOS_MIN_IO 0x1000
+#else
+#define PCIBIOS_MIN_IO 0x4000
+#endif
#define PCIBIOS_MIN_MEM (pci_mem_start)

void pcibios_config_init(void);

2003-01-19 06:36:44

by Osamu Tomita

[permalink] [raw]
Subject: [PATCHSET] PC-9800 sub-arch (11/29) ac-update

This is patchset to support NEC PC-9800 subarchitecture
against 2.5.59 (11/29).

Updates console driver for PC98 in 2.5.50-ac1.

diff -Nru linux-2.5.50-ac1/drivers/video/console/gdccon.c linux98-2.5.52/drivers/video/console/gdccon.c
--- linux-2.5.50-ac1/drivers/video/console/gdccon.c 2002-12-17 09:07:11.000000000 +0900
+++ linux98-2.5.52/drivers/video/console/gdccon.c 2002-12-17 11:01:09.000000000 +0900
@@ -17,7 +17,6 @@
#include <linux/kernel.h>
#include <linux/tty.h>
#include <linux/console.h>
-#include <linux/console_struct.h>
#include <linux/string.h>
#include <linux/kd.h>
#include <linux/slab.h>
diff -Nru linux-2.5.50-ac1/include/asm-i386/gdc.h.old linux-2.5.50-ac1/include/asm-i386/gdc.h
--- linux-2.5.50-ac1/include/asm-i386/gdc.h 2002-12-11 13:10:08.000000000 +0900
+++ linux98-2.5.52/include/asm-i386/gdc.h 2002-12-11 17:26:46.000000000 +0900
@@ -55,26 +55,29 @@
_scr_memsetw(u16 *s, u16 c, unsigned int count)
{
#ifdef CONFIG_GDC_32BITACCESS
- __asm__ __volatile__ ("shr%L1 %1
- jz 2f
-" /* cld kernel code now assumes DF = 0 any time */ "\
- test%L0 %3,%0
- jz 1f
- stos%W2
- dec%L1 %1
-1: shr%L1 %1
- rep
- stos%L2
- jnc 2f
- stos%W2
- rep
- stos%W2
-2:"
+ __asm__ __volatile__ (
+ "shr%L1 %1\n\t"
+ "jz 2f\n\t"
+ /* "cld\n\t" kernel code now assumes DF = 0 any time */
+ "test%L0 %3,%0\n\t"
+ "jz 1f\n\t"
+ "stos%W2\n\t"
+ "dec%L1 %1\n"
+"1: shr%L1 %1\n\t"
+ "rep\n\t"
+ "stos%L2\n\t"
+ "jnc 2f\n\t"
+ "stos%W2\n\t"
+ "rep\n\t"
+ "stos%W2\n"
+"2:"
: "=D"(s), "=c"(count)
: "a"((((u32) c) << 16) | c), "g"(2),
"0"(s), "1"(count));
#else
- __asm__ __volatile__ ("rep\n\tstosw"
+ __asm__ __volatile__ (
+ "rep\n\t"
+ "stosw"
: "=D"(s), "=c"(count)
: "0"(s), "1"(count / 2), "a"(c));
#endif
@@ -92,23 +95,26 @@
_scr_memcpyw(u16 *d, u16 *s, unsigned int count)
{
#if 1 /* def CONFIG_GDC_32BITACCESS */
- __asm__ __volatile__ ("shr%L2 %2
- jz 2f
-" /* cld */ "\
- test%L0 %3,%0
- jz 1f
- movs%W0
- dec%L2 %2
-1: shr%L2 %2
- rep
- movs%L0
- jnc 2f
- movs%W0
-2:"
+ __asm__ __volatile__ (
+ "shr%L2 %2\n\t"
+ "jz 2f\n\t"
+ /* "cld\n\t" */
+ "test%L0 %3,%0\n\t"
+ "jz 1f\n\t"
+ "movs%W0\n\t"
+ "dec%L2 %2\n"
+"1: shr%L2 %2\n\t"
+ "rep\n\t"
+ "movs%L0\n\t"
+ "jnc 2f\n\t"
+ "movs%W0\n"
+"2:"
: "=D"(d), "=S"(s), "=c"(count)
: "g"(2), "0"(d), "1"(s), "2"(count));
#else
- __asm__ __volatile__ ("rep\n\tmovsw"
+ __asm__ __volatile__ (
+ "rep\n\t"
+ "movsw"
: "=D"(d), "=S"(s), "=c"(count)
: "0"(d), "1"(s), "2"(count / 2));
#endif
@@ -126,30 +132,35 @@
#if 1 /* def CONFIG_GDC_32BITACCESS */
u16 tmp;

- __asm__ __volatile__ ("shr%L3 %3
- jz 2f
- std
- lea%L1 -4(%1,%3,2),%1
- lea%L2 -4(%2,%3,2),%2
- test%L1 %4,%1
- jz 1f
- mov%W0 2(%2),%0
- sub%L2 %4,%2
- dec%L3 %3
- mov%W0 %0,2(%1)
- sub%L1 %4,%1
-1: shr%L3 %3
- rep
- movs%L0
- jnc 3f
- mov%W0 2(%2),%0
- mov%W0 %0,2(%1)
-3: cld
-2:"
+ __asm__ __volatile__ (
+ "shr%L3 %3\n\t"
+ "jz 2f\n\t"
+ "std\n\t"
+ "lea%L1 -4(%1,%3,2),%1\n\t"
+ "lea%L2 -4(%2,%3,2),%2\n\t"
+ "test%L1 %4,%1\n\t"
+ "jz 1f\n\t"
+ "mov%W0 2(%2),%0\n\t"
+ "sub%L2 %4,%2\n\t"
+ "dec%L3 %3\n\t"
+ "mov%W0 %0,2(%1)\n\t"
+ "sub%L1 %4,%1\n"
+"1: shr%L3 %3\n\t"
+ "rep\n\t"
+ "movs%L0\n\t"
+ "jnc 3f\n\t"
+ "mov%W0 2(%2),%0\n\t"
+ "mov%W0 %0,2(%1)\n"
+"3: cld\n"
+"2:"
: "=r"(tmp), "=D"(d), "=S"(s), "=c"(count)
: "g"(2), "1"(d), "2"(s), "3"(count));
#else
- __asm__ __volatile__ ("std\n\trep\n\tmovsw\n\tcld"
+ __asm__ __volatile__ (
+ "std\n\t"
+ "rep\n\t"
+ "movsw\n\t"
+ "cld"
: "=D"(d), "=S"(s), "=c"(count)
: "0"((void *) d + count - 2),
"1"((void *) s + count - 2), "2"(count / 2));
@@ -179,23 +190,26 @@
#ifdef CONFIG_GDC_32BITACCESS
/* VRAM is quite slow, so we align source pointer (%esi)
to double-word alignment. */
- __asm__ __volatile__ ("shr%L2 %2
- jz 2f
-" /* cld */ "\
- test%L0 %3,%0
- jz 1f
- movs%W0
- dec%L2 %2
-1: shr%L2 %2
- rep
- movs%L0
- jnc 2f
- movs%W0
-2:"
+ __asm__ __volatile__ (
+ "shr%L2 %2\n\t"
+ "jz 2f\n\t"
+ /* "cld\n\t" */
+ "test%L0 %3,%0\n\t"
+ "jz 1f\n\t"
+ "movs%W0\n\t"
+ "dec%L2 %2\n"
+"1: shr%L2 %2\n\t"
+ "rep\n\t"
+ "movs%L0\n\t"
+ "jnc 2f\n\t"
+ "movs%W0\n"
+"2:"
: "=D"(d), "=S"(s), "=c"(count)
: "g"(2), "0"(d), "1"(s), "2"(count));
#else
- __asm__ __volatile__ ("rep\n\tmovsw"
+ __asm__ __volatile__ (
+ "rep\n\t"
+ "movsw"
: "=D"(d), "=S"(s), "=c"(count)
: "0"(d), "1"(s), "2"(count / 2));
#endif

2003-01-19 06:35:49

by Osamu Tomita

[permalink] [raw]
Subject: [PATCHSET] PC-9800 sub-arch (10/29) fs, patition table

This is patchset to support NEC PC-9800 subarchitecture
against 2.5.59 (10/29).

FAT fs and partition table support.

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/fs/partitions/Makefile linux98/fs/partitions/Makefile
--- linux/fs/partitions/Makefile 2002-12-16 11:07:54.000000000 +0900
+++ linux98/fs/partitions/Makefile 2002-12-17 09:39:48.000000000 +0900
@@ -18,3 +18,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 2002-12-12 14:22:11.000000000 +0900
@@ -0,0 +1,272 @@
+/*
+ * 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)
+
+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
+
+extern struct scsi_device *sd_find_params_by_bdev(struct block_device *, char **, sector_t *);
+
+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 };
+ sector_t capacity;
+
+ (void)sd_find_params_by_bdev(bdev, NULL, &capacity);
+ scsicam_bios_param(bdev, capacity, 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;
+}
+
+/*
+ * 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);

2003-01-19 06:47:17

by Osamu Tomita

[permalink] [raw]
Subject: [PATCHSET] PC-9800 sub-arch (20/29) parport

This is patchset to support NEC PC-9800 subarchitecture
against 2.5.59 (20/29).

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 ([email protected]) 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));
}

2003-01-19 06:42:54

by Osamu Tomita

[permalink] [raw]
Subject: [PATCHSET] PC-9800 sub-arch (17/29) kernel

This is patchset to support NEC PC-9800 subarchitecture
against 2.5.59 (17/29).

Misc files for support PC98.

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
};


diff -Nru linux/kernel/timer.c linux98/kernel/timer.c
--- linux/kernel/timer.c 2002-12-10 11:45:52.000000000 +0900
+++ linux98/kernel/timer.c 2002-12-16 16:14:08.000000000 +0900
@@ -434,8 +434,13 @@
/*
* Timekeeping variables
*/
+#ifndef CONFIG_X86_PC9800
unsigned long tick_usec = TICK_USEC; /* ACTHZ period (usec) */
unsigned long tick_nsec = TICK_NSEC(TICK_USEC); /* USER_HZ period (nsec) */
+#else
+extern unsigned long tick_usec; /* ACTHZ period (usec) */
+extern unsigned long tick_nsec; /* USER_HZ period (nsec) */
+#endif

/* The current time */
struct timespec xtime __attribute__ ((aligned (16)));
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

2003-01-19 06:40:38

by Osamu Tomita

[permalink] [raw]
Subject: [PATCHSET] PC-9800 sub-arch (14/29) core#2

This is patchset to support NEC PC-9800 subarchitecture
against 2.5.59 (14/29).

Core patches for PC98 under include/asm-i386/ directory.

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/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
+#ifndef CONFIG_X86_PC9800
#define __SLOW_DOWN_IO "outb %%al,$0x80;"
+#else
+#define __SLOW_DOWN_IO "outb %%al,$0x5f;"
+#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)
{
+#ifndef CONFIG_X86_PC9800
return ((irq == 2) ? 9 : irq);
+#else
+ return ((irq == 7) ? 11 : 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 <[email protected]>
+ * (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/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/pgtable.h linux98/include/asm-i386/pgtable.h
--- linux/include/asm-i386/pgtable.h 2002-04-15 04:18:55.000000000 +0900
+++ linux98/include/asm-i386/pgtable.h 2002-04-17 10:37:22.000000000 +0900
@@ -58,7 +58,11 @@
#endif
#endif

+#ifndef CONFIG_X86_PC9800
#define __beep() asm("movb $0x3,%al; outb %al,$0x61")
+#else
+#define __beep() asm("movb $0x6,%al; outb %al,$0x37")
+#endif

#define PMD_SIZE (1UL << PMD_SHIFT)
#define PMD_MASK (~(PMD_SIZE-1))
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/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) * \

2003-01-19 06:40:15

by Osamu Tomita

[permalink] [raw]
Subject: [PATCHSET] PC-9800 sub-arch (13/29) IDE

This is patchset to support NEC PC-9800 subarchitecture
against 2.5.59 (13/29).

Support standard IDE I/F of PC98.

diff -Nru linux/drivers/ide/Kconfig linux98/drivers/ide/Kconfig
--- linux/drivers/ide/Kconfig 2003-01-14 09:31:48.000000000 +0900
+++ linux98/drivers/ide/Kconfig 2003-01-14 10:17:08.000000000 +0900
@@ -1015,6 +1015,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, [email protected], 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 ([email protected])
+ */
+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)
{
+#ifndef CONFIG_X86_PC9800
static unsigned long ata_io_base[MAX_HWIFS] = { 0x1f0, 0x170, 0x1e8, 0x168, 0x1e0, 0x160 };
+#else /* CONFIG_X86_PC9800 */
+ static unsigned long ata_io_base[MAX_HWIFS] = { 0x640, 0x640, 0, 0, 0, 0 };
+#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;
+#ifndef CONFIG_X86_PC9800
reg += 1;
+#else
+ reg += increment;
+#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 2002-10-12 13:22:07.000000000 +0900
+++ linux98/include/linux/hdreg.h 2002-10-12 19:38:02.000000000 +0900
@@ -5,11 +5,13 @@
* 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

+#ifndef 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 +27,23 @@

#define HD_CMD 0x3f6 /* used for resets */
#define HD_ALTSTATUS 0x3f6 /* same as HD_STATUS but doesn't clear irq */
+#else /* 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 */
+#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 {

2003-01-19 06:52:48

by Osamu Tomita

[permalink] [raw]
Subject: [PATCHSET] PC-9800 sub-arch (26/29) ac-update

This is patchset to support NEC PC-9800 subarchitecture
against 2.5.59 (26/29).

Updates include/asm-i386/serial.h in 2.5.50-ac1.

diff -Nru linux-2.5.50-ac1/include/asm-i386/serial.h linux98-2.5.54/include/asm-i386/serial.h
--- linux-2.5.50-ac1/include/asm-i386/serial.h 2003-01-04 10:47:57.000000000 +0900
+++ linux98-2.5.54/include/asm-i386/serial.h 2003-01-04 13:41:33.000000000 +0900
@@ -50,7 +50,7 @@

#define C_P(card,port) (((card)<<6|(port)<<3) + 1)

-#ifndef CONFIG_PC9800
+#ifndef CONFIG_X86_PC9800
#define STD_SERIAL_PORT_DEFNS \
/* UART CLK PORT IRQ FLAGS */ \
{ 0, BASE_BAUD, 0x3F8, 4, STD_COM_FLAGS }, /* ttyS0 */ \
@@ -62,7 +62,7 @@
/* UART CLK PORT IRQ FLAGS */ \
{ 0, BASE_BAUD, 0x30, 4, STD_COM_FLAGS }, /* ttyS0 */ \
{ 0, BASE_BAUD, 0x238, 5, STD_COM_FLAGS }, /* ttyS1 */
-#endif /* CONFIG_PC9800 */
+#endif /* CONFIG_X86_PC9800 */


#ifdef CONFIG_SERIAL_MANY_PORTS

2003-01-19 06:52:49

by Osamu Tomita

[permalink] [raw]
Subject: [PATCHSET] PC-9800 sub-arch (25/29) SCSI

This is patchset to support NEC PC-9800 subarchitecture
against 2.5.59 (25/29).

SCSI host adapter support.

diff -Nru linux/drivers/scsi/Kconfig linux98/drivers/scsi/Kconfig
--- linux/drivers/scsi/Kconfig 2003-01-09 13:04:25.000000000 +0900
+++ linux98/drivers/scsi/Kconfig 2003-01-10 10:37:00.000000000 +0900
@@ -1730,6 +1730,13 @@
see the picture at
<http://amiga.multigraph.com/photos/oktagon.html>.

+config SCSI_PC980155
+ tristate "NEC PC-9801-55 SCSI support"
+ depends on X86_PC9800 && SCSI
+ help
+ If you have the NEC PC-9801-55 SCSI interface card or compatibles
+ for NEC PC-9801/PC-9821, say Y.
+
# bool 'Cyberstorm Mk III SCSI support (EXPERIMENTAL)' CONFIG_CYBERSTORMIII_SCSI
# bool 'GVP Turbo 040/060 SCSI support (EXPERIMENTAL)' CONFIG_GVP_TURBO_SCSI
endmenu
diff -Nru linux/drivers/scsi/Makefile linux98/drivers/scsi/Makefile
--- linux/drivers/scsi/Makefile 2003-01-09 13:04:23.000000000 +0900
+++ linux98/drivers/scsi/Makefile 2003-01-10 10:37:00.000000000 +0900
@@ -31,6 +31,7 @@
obj-$(CONFIG_A3000_SCSI) += a3000.o wd33c93.o
obj-$(CONFIG_A2091_SCSI) += a2091.o wd33c93.o
obj-$(CONFIG_GVP11_SCSI) += gvp11.o wd33c93.o
+obj-$(CONFIG_SCSI_PC980155) += pc980155.o wd33c93.o
obj-$(CONFIG_MVME147_SCSI) += mvme147.o wd33c93.o
obj-$(CONFIG_SGIWD93_SCSI) += sgiwd93.o wd33c93.o
obj-$(CONFIG_CYBERSTORM_SCSI) += NCR53C9x.o cyberstorm.o
@@ -124,10 +125,17 @@
obj-$(CONFIG_BLK_DEV_SR) += sr_mod.o
obj-$(CONFIG_CHR_DEV_SG) += sg.o

-scsi_mod-objs := scsi.o hosts.o scsi_ioctl.o constants.o scsicam.o \
+scsi_mod-objs := scsi.o hosts.o scsi_ioctl.o constants.o \
scsi_error.o scsi_lib.o scsi_scan.o scsi_syms.o \
scsi_sysfs.o

+ifneq ($(CONFIG_X86_PC9800),y)
+scsi_mod-objs += scsicam.o
+else
+export-objs += wd33c93.o
+scsi_mod-objs += scsicam98.o
+endif
+
ifdef CONFIG_PROC_FS
scsi_mod-objs += scsi_proc.o
endif
diff -Nru linux/drivers/scsi/pc980155.c linux98/drivers/scsi/pc980155.c
--- linux/drivers/scsi/pc980155.c 1970-01-01 09:00:00.000000000 +0900
+++ linux98/drivers/scsi/pc980155.c 2002-12-15 12:09:04.000000000 +0900
@@ -0,0 +1,263 @@
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/blk.h>
+#include <linux/sched.h>
+#include <linux/version.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/irq.h>
+#include <asm/dma.h>
+#include <linux/module.h>
+
+#include "scsi.h"
+#include "hosts.h"
+#include "wd33c93.h"
+#include "pc980155.h"
+#include "pc980155regs.h"
+
+#define DEBUG
+
+#include<linux/stat.h>
+
+static inline void __print_debug_info(unsigned int);
+static inline void __print_debug_info(unsigned int a){}
+#define print_debug_info() __print_debug_info(base_io);
+
+#define NR_BASE_IOS 4
+static int nr_base_ios = NR_BASE_IOS;
+static unsigned int base_ios[NR_BASE_IOS] = {0xcc0, 0xcd0, 0xce0, 0xcf0};
+static unsigned int SASR;
+static unsigned int SCMD;
+static wd33c93_regs regs = {&SASR, &SCMD};
+
+static struct Scsi_Host *pc980155_host = NULL;
+
+static void pc980155_intr_handle(int irq, void *dev_id, struct pt_regs *regp);
+
+inline void pc980155_dma_enable(unsigned int base_io){
+ outb(0x01, REG_CWRITE);
+ WAIT();
+}
+inline void pc980155_dma_disable(unsigned int base_io){
+ outb(0x02, REG_CWRITE);
+ WAIT();
+}
+
+
+static void pc980155_intr_handle(int irq, void *dev_id, struct pt_regs *regp)
+{
+ wd33c93_intr(pc980155_host);
+}
+
+static int dma_setup(Scsi_Cmnd *sc, int dir_in){
+ /*
+ * sc->SCp.this_residual : transfer count
+ * sc->SCp.ptr : distination address (virtual address)
+ * dir_in : data direction (DATA_OUT_DIR:0 or DATA_IN_DIR:1)
+ *
+ * if success return 0
+ */
+
+ /*
+ * DMA WRITE MODE
+ * bit 7,6 01b single mode (this mode only)
+ * bit 5 inc/dec (default:0 = inc)
+ * bit 4 auto initialize (normaly:0 = off)
+ * bit 3,2 01b memory -> io
+ * 10b io -> memory
+ * 00b verify
+ * bit 1,0 channel
+ */
+ disable_dma(sc->host->dma_channel);
+ set_dma_mode(sc->host->dma_channel, 0x40 | (dir_in ? 0x04 : 0x08));
+ clear_dma_ff(sc->host->dma_channel);
+ set_dma_addr(sc->host->dma_channel, virt_to_phys(sc->SCp.ptr));
+ set_dma_count(sc->host->dma_channel, sc->SCp.this_residual);
+#if 0
+#ifdef DEBUG
+ printk("D%d(%x)D", sc->SCp.this_residual);
+#endif
+#endif
+ enable_dma(sc->host->dma_channel);
+
+ pc980155_dma_enable(sc->host->io_port);
+
+ return 0;
+}
+
+static void dma_stop(struct Scsi_Host *instance, Scsi_Cmnd *sc, int status){
+ /*
+ * instance: Hostadapter's instance
+ * sc: scsi command
+ * status: True if success
+ */
+
+ pc980155_dma_disable(sc->host->io_port);
+
+ disable_dma(sc->host->dma_channel);
+}
+
+/* return non-zero on detection */
+static inline int pc980155_test_port(wd33c93_regs regs)
+{
+ /* Quick and dirty test for presence of the card. */
+ if (READ_AUX_STAT() == 0xff)
+ return 0;
+ return 1;
+}
+
+static inline int
+pc980155_getconfig(unsigned int base_io, wd33c93_regs regs,
+ unsigned char* irq, unsigned char* dma,
+ unsigned char* scsi_id)
+{
+ static unsigned char irqs[] = { 3, 5, 6, 9, 12, 13 };
+ unsigned char result;
+
+ printk(KERN_DEBUG "PC-9801-55: base_io=%x SASR=%x SCMD=%x\n",
+ base_io, *regs.SASR, *regs.SCMD);
+ result = read_wd33c93(regs, WD_RESETINT);
+ printk(KERN_DEBUG "PC-9801-55: getting config (%x)\n", result);
+ *scsi_id = result & 0x07;
+ *irq = (result >> 3) & 0x07;
+ if (*irq > 5) {
+ printk(KERN_ERR "PC-9801-55 (base %#x): impossible IRQ (%d)"
+ " - other device here?\n", base_io, *irq);
+ return 0;
+ }
+
+ *irq = irqs[*irq];
+ result = inb(REG_STATRD);
+ WAIT();
+ *dma = result & 0x03;
+ if (*dma == 1) {
+ printk(KERN_ERR
+ "PC-9801-55 (base %#x): impossible DMA channl (%d)"
+ " - other device here?\n", base_io, *dma);
+ return 0;
+ }
+#ifdef DEBUG
+ printk("PC-9801-55: end of getconfig\n");
+#endif
+ return 1;
+}
+
+/* return non-zero on detection */
+int scsi_pc980155_detect(Scsi_Host_Template* tpnt)
+{
+ unsigned int base_io;
+ unsigned char irq, dma, scsi_id;
+ int i;
+#ifdef DEBUG
+ unsigned char debug;
+#endif
+
+ for (i = 0; i < nr_base_ios; i++) {
+ base_io = base_ios[i];
+ SASR = REG_ADDRST;
+ SCMD = REG_CONTRL;
+
+ /* printk("PC-9801-55: SASR(%x = %x)\n", SASR, REG_ADDRST); */
+ if (check_region(base_io, 6))
+ continue;
+ if (! pc980155_test_port(regs))
+ continue;
+
+ if (!pc980155_getconfig(base_io, regs, &irq, &dma, &scsi_id))
+ continue;
+#ifdef DEBUG
+ printk("PC-9801-55: config: base io = %x, irq = %d, dma channel = %d, scsi id = %d\n",
+ base_io, irq, dma, scsi_id);
+#endif
+ if (request_irq(irq, pc980155_intr_handle, 0, "PC-9801-55",
+ NULL)) {
+ printk(KERN_ERR
+ "PC-9801-55: unable to allocate IRQ %d\n",
+ irq);
+ continue;
+ }
+ if (request_dma(dma, "PC-9801-55")) {
+ printk(KERN_ERR "PC-9801-55: "
+ "unable to allocate DMA channel %d\n", dma);
+ free_irq(irq, NULL);
+ continue;
+ }
+
+ request_region(base_io, 6, "PC-9801-55");
+ pc980155_host = scsi_register(tpnt, sizeof(struct WD33C93_hostdata));
+ pc980155_host->this_id = scsi_id;
+ pc980155_host->io_port = base_io;
+ pc980155_host->n_io_port = 6;
+ pc980155_host->irq = irq;
+ pc980155_host->dma_channel = dma;
+
+#ifdef DEBUG
+ printk("PC-9801-55: scsi host found at %x irq = %d, use dma channel %d.\n", base_io, irq, dma);
+ debug = read_aux_stat(regs);
+ printk("PC-9801-55: aux: %x ", debug);
+ debug = read_wd33c93(regs, 0x17);
+ printk("status: %x\n", debug);
+#endif
+
+ pc980155_int_enable(regs);
+
+ wd33c93_init(pc980155_host, regs, dma_setup, dma_stop,
+ WD33C93_FS_12_15);
+
+ return 1;
+ }
+
+ printk("PC-9801-55: not found\n");
+ return 0;
+}
+
+int pc980155_proc_info(char *buf, char **start, off_t off, int len,
+ int hostno, int in)
+{
+ /* NOT SUPPORTED YET! */
+
+ if (in) {
+ return -EPERM;
+ }
+ *start = buf;
+ return sprintf(buf, "Sorry, not supported yet.\n");
+}
+
+int pc980155_setup(char *str)
+{
+next:
+ if (!strncmp(str, "io:", 3)){
+ base_ios[0] = simple_strtoul(str+3,NULL,0);
+ nr_base_ios = 1;
+ while (*str > ' ' && *str != ',')
+ str++;
+ if (*str == ','){
+ str++;
+ goto next;
+ }
+ }
+ return 0;
+}
+
+int scsi_pc980155_release(struct Scsi_Host *pc980155_host)
+{
+#ifdef MODULE
+ pc980155_int_disable(regs);
+ release_region(pc980155_host->io_port, pc980155_host->n_io_port);
+ free_irq(pc980155_host->irq, NULL);
+ free_dma(pc980155_host->dma_channel);
+ wd33c93_release();
+#endif
+ return 1;
+}
+
+__setup("pc980155=", pc980155_setup);
+
+Scsi_Host_Template driver_template = SCSI_PC980155;
+
+#include "scsi_module.c"
diff -Nru linux/drivers/scsi/pc980155.h linux98/drivers/scsi/pc980155.h
--- linux/drivers/scsi/pc980155.h 1970-01-01 09:00:00.000000000 +0900
+++ linux98/drivers/scsi/pc980155.h 2002-12-15 12:05:05.000000000 +0900
@@ -0,0 +1,47 @@
+/*
+ * PC-9801-55 SCSI host adapter driver
+ *
+ * Copyright (C) 1997-2000 Kyoto University Microcomputer Club
+ * (Linux/98 project)
+ */
+
+#ifndef _SCSI_PC9801_55_H
+#define _SCSI_PC9801_55_H
+
+#include <linux/types.h>
+#include <linux/kdev_t.h>
+#include <scsi/scsicam.h>
+
+int wd33c93_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
+int wd33c93_abort(Scsi_Cmnd *);
+int wd33c93_reset(Scsi_Cmnd *, unsigned int);
+int scsi_pc980155_detect(Scsi_Host_Template *);
+int scsi_pc980155_release(struct Scsi_Host *);
+int pc980155_proc_info(char *, char **, off_t, int, int, int);
+
+#ifndef CMD_PER_LUN
+#define CMD_PER_LUN 2
+#endif
+
+#ifndef CAN_QUEUE
+#define CAN_QUEUE 16
+#endif
+
+#define SCSI_PC980155 { .proc_name = "PC-9801-55", \
+ .name = "SCSI PC-9801-55", \
+ .proc_info = pc980155_proc_info, \
+ .detect = scsi_pc980155_detect, \
+ .release = scsi_pc980155_release, \
+ /* command: use queue command */ \
+ .queuecommand = wd33c93_queuecommand, \
+ .abort = wd33c93_abort, \
+ .reset = wd33c93_reset, \
+ .bios_param = scsicam_bios_param, \
+ .can_queue = CAN_QUEUE, \
+ .this_id = 7, \
+ .sg_tablesize = SG_ALL, \
+ .cmd_per_lun = CMD_PER_LUN, /* dont use link command */ \
+ .unchecked_isa_dma = 1, /* use dma **XXXX***/ \
+ .use_clustering = ENABLE_CLUSTERING }
+
+#endif /* _SCSI_PC9801_55_H */
diff -Nru linux/drivers/scsi/pc980155regs.h linux98/drivers/scsi/pc980155regs.h
--- linux/drivers/scsi/pc980155regs.h 1970-01-01 09:00:00.000000000 +0900
+++ linux98/drivers/scsi/pc980155regs.h 2001-12-03 18:44:10.000000000 +0900
@@ -0,0 +1,89 @@
+#ifndef __PC980155REGS_H
+#define __PC980155REGS_H
+
+#include "wd33c93.h"
+
+#define REG_ADDRST (base_io+0)
+#define REG_CONTRL (base_io+2)
+#define REG_CWRITE (base_io+4)
+#define REG_STATRD (base_io+4)
+
+#define WD_MEMORYBANK 0x30
+#define WD_RESETINT 0x33
+
+#if 0
+#define WAIT() outb(0x00,0x5f)
+#else
+#define WAIT() do{}while(0)
+#endif
+
+static inline uchar read_wd33c93(const wd33c93_regs regs, uchar reg_num)
+{
+ uchar data;
+ outb(reg_num, *regs.SASR);
+ WAIT();
+ data = inb(*regs.SCMD);
+ WAIT();
+ return data;
+}
+
+static inline uchar read_aux_stat(const wd33c93_regs regs)
+{
+ uchar result;
+ result = inb(*regs.SASR);
+ WAIT();
+ /* printk("PC-9801-55: regp->SASR(%x) = %x\n", regp->SASR, result); */
+ return result;
+}
+#define READ_AUX_STAT() read_aux_stat(regs)
+
+static inline void write_wd33c93(const wd33c93_regs regs, uchar reg_num,
+ uchar value)
+{
+ outb(reg_num, *regs.SASR);
+ WAIT();
+ outb(value, *regs.SCMD);
+ WAIT();
+}
+
+
+#define write_wd33c93_cmd(regs,cmd) write_wd33c93(regs,WD_COMMAND,cmd)
+
+static inline void write_wd33c93_count(const wd33c93_regs regs,
+ unsigned long value)
+{
+ outb(WD_TRANSFER_COUNT_MSB, *regs.SASR);
+ WAIT();
+ outb((value >> 16) & 0xff, *regs.SCMD);
+ WAIT();
+ outb((value >> 8) & 0xff, *regs.SCMD);
+ WAIT();
+ outb( value & 0xff, *regs.SCMD);
+ WAIT();
+}
+
+
+static inline unsigned long read_wd33c93_count(const wd33c93_regs regs)
+{
+unsigned long value;
+
+ outb(WD_TRANSFER_COUNT_MSB, *regs.SASR);
+ value = inb(*regs.SCMD) << 16;
+ value |= inb(*regs.SCMD) << 8;
+ value |= inb(*regs.SCMD);
+ return value;
+}
+
+static inline void write_wd33c93_cdb(const wd33c93_regs regs, unsigned int len,
+ unsigned char cmnd[])
+{
+ int i;
+ outb(WD_CDB_1, *regs.SASR);
+ for (i=0; i<len; i++)
+ outb(cmnd[i], *regs.SCMD);
+}
+
+#define pc980155_int_enable(regs) write_wd33c93(regs, WD_MEMORYBANK, read_wd33c93(regs, WD_MEMORYBANK) | 0x04)
+#define pc980155_int_disable(regs) write_wd33c93(regs, WD_MEMORYBANK, read_wd33c93(regs, WD_MEMORYBANK) & ~0x04)
+
+#endif
diff -Nru linux/drivers/scsi/scsi_scan.c linux98/drivers/scsi/scsi_scan.c
--- linux/drivers/scsi/scsi_scan.c 2002-12-24 14:21:04.000000000 +0900
+++ linux98/drivers/scsi/scsi_scan.c 2002-12-26 14:28:56.000000000 +0900
@@ -128,6 +128,7 @@
{"MITSUMI", "CD-R CR-2201CS", "6119", BLIST_NOLUN}, /* locks up */
{"RELISYS", "Scorpio", NULL, BLIST_NOLUN}, /* responds to all lun */
{"MICROTEK", "ScanMaker II", "5.61", BLIST_NOLUN}, /* responds to all lun */
+ {"NEC", "D3856", "0009", BLIST_NOLUN},

/*
* Other types of devices that have special flags.
diff -Nru linux/drivers/scsi/scsi_syms.c linux98/drivers/scsi/scsi_syms.c
--- linux/drivers/scsi/scsi_syms.c 2002-12-24 14:20:26.000000000 +0900
+++ linux98/drivers/scsi/scsi_syms.c 2002-12-26 14:28:56.000000000 +0900
@@ -97,6 +97,10 @@
EXPORT_SYMBOL(scsi_host_put);
EXPORT_SYMBOL(scsi_device_types);

+/* For PC-9800 architecture support */
+extern struct scsi_device *sd_find_params_by_bdev(struct block_device *, char **, sector_t *);
+EXPORT_SYMBOL(sd_find_params_by_bdev);
+
/*
* This is for st to find the bounce limit
*/
diff -Nru linux/drivers/scsi/scsicam98.c linux98/drivers/scsi/scsicam98.c
--- linux/drivers/scsi/scsicam98.c 1970-01-01 09:00:00.000000000 +0900
+++ linux98/drivers/scsi/scsicam98.c 2002-12-14 14:55:28.000000000 +0900
@@ -0,0 +1,192 @@
+/*
+ *
+ * scsicam98.c
+ * SCSI CAM support functions for NEC PC-9801 , use for HDIO_GETGEO, etc.
+ *
+ * Copyright (c) 1999-2002 Osamu Tomita <[email protected]>
+ * Based on scsicam.c written by Drew Eckhardt
+ *
+ */
+
+#include <linux/module.h>
+
+#include <linux/fs.h>
+#include <linux/genhd.h>
+#include <linux/kernel.h>
+#include <linux/blk.h>
+#include <linux/buffer_head.h>
+#include <asm/unaligned.h>
+#include "scsi.h"
+#include "hosts.h"
+#include <scsi/scsicam.h>
+#include <asm/pc9800.h>
+
+
+unsigned char *scsi_bios_ptable(struct block_device *dev)
+{
+ unsigned char *res = kmalloc(66, GFP_KERNEL);
+ if (res) {
+ struct block_device *bdev = dev->bd_contains;
+ struct buffer_head *bh = __bread(bdev, 0, block_size(bdev));
+ if (bh) {
+ memcpy(res, bh->b_data + 0x1be, 66);
+ brelse(bh);
+ } else {
+ kfree(res);
+ res = NULL;
+ }
+ }
+ return res;
+}
+
+/*
+ * Function : static int scsi_partsize(unsigned char *buf, unsigned long
+ * capacity,unsigned int *cyls, unsigned int *hds, unsigned int *secs);
+ *
+ * Purpose : to determine the BIOS mapping used to create the partition
+ * table, storing the results in *cyls, *hds, and *secs
+ *
+ * Returns : -1 on failure, 0 on success.
+ *
+ */
+
+int scsi_partsize(unsigned char *buf, unsigned long capacity,
+ unsigned int *cyls, unsigned int *hds, unsigned int *secs)
+{
+ struct partition *p = (struct partition *)buf, *largest = NULL;
+ int i, largest_cyl;
+ int cyl, ext_cyl, end_head, end_cyl, end_sector;
+ unsigned int logical_end, physical_end, ext_physical_end;
+
+
+ if (*(unsigned short *) (buf + 64) == 0xAA55) {
+ for (largest_cyl = -1, i = 0; i < 4; ++i, ++p) {
+ if (!p->sys_ind)
+ continue;
+#ifdef DEBUG
+ printk("scsicam98 : partition %d has system \n", i);
+#endif
+ cyl = p->cyl + ((p->sector & 0xc0) << 2);
+ if (cyl > largest_cyl) {
+ largest_cyl = cyl;
+ largest = p;
+ }
+ }
+ }
+ if (largest) {
+ end_cyl = largest->end_cyl + ((largest->end_sector & 0xc0) << 2);
+ end_head = largest->end_head;
+ end_sector = largest->end_sector & 0x3f;
+
+ if (end_head + 1 == 0 || end_sector == 0)
+ return -1;
+
+#ifdef DEBUG
+ printk("scsicam98 : end at h = %d, c = %d, s = %d\n",
+ end_head, end_cyl, end_sector);
+#endif
+
+ physical_end = end_cyl * (end_head + 1) * end_sector +
+ end_head * end_sector + end_sector;
+
+ /* This is the actual _sector_ number at the end */
+ logical_end = get_unaligned(&largest->start_sect)
+ + get_unaligned(&largest->nr_sects);
+
+ /* This is for >1023 cylinders */
+ ext_cyl = (logical_end - (end_head * end_sector + end_sector))
+ / (end_head + 1) / end_sector;
+ ext_physical_end = ext_cyl * (end_head + 1) * end_sector +
+ end_head * end_sector + end_sector;
+
+#ifdef DEBUG
+ printk("scsicam98 : logical_end=%d physical_end=%d ext_physical_end=%d ext_cyl=%d\n"
+ ,logical_end, physical_end, ext_physical_end, ext_cyl);
+#endif
+
+ if ((logical_end == physical_end) ||
+ (end_cyl == 1023 && ext_physical_end == logical_end)) {
+ *secs = end_sector;
+ *hds = end_head + 1;
+ *cyls = capacity / ((end_head + 1) * end_sector);
+ return 0;
+ }
+#ifdef DEBUG
+ printk("scsicam98 : logical (%u) != physical (%u)\n",
+ logical_end, physical_end);
+#endif
+ }
+ return -1;
+}
+
+/* XXX - For now, we assume the first (i.e. having the least host_no)
+ real (i.e. non-emulated) host adapter shall be BIOS-controlled one.
+ We *SHOULD* invent another way. */
+
+static inline struct Scsi_Host *first_real_host(void)
+{
+ struct Scsi_Host *h = NULL;
+
+ while ((h = scsi_host_get_next(h)))
+ if (!h->hostt->emulated)
+ break;
+
+ return h;
+}
+
+extern struct scsi_device *sd_find_params_by_bdev(struct block_device *, char **, sector_t *);
+
+/*
+ * Function : int scsicam_bios_param (struct block_device *bdev, ector_t capacity, int *ip)
+ *
+ * Purpose : to determine the BIOS mapping used for a drive in a
+ * SCSI-CAM system, storing the results in ip as required
+ * by the HDIO_GETGEO ioctl().
+ *
+ * Returns : -1 on failure, 0 on success.
+ *
+ */
+
+int scsicam_bios_param(struct block_device *bdev, sector_t capacity, int *ip)
+{
+ char *name;
+ struct scsi_device *device = sd_find_params_by_bdev(bdev, &name, NULL);
+
+ if (device && first_real_host() == device->host && device->id < 7
+ && __PC9800SCA_TEST_BIT(PC9800SCA_DISK_EQUIPS, device->id))
+ {
+ const u8 *p = (&__PC9800SCA(u8, PC9800SCA_SCSI_PARAMS)
+ + device->id * 4);
+
+ ip[0] = p[1]; /* # of heads */
+ ip[1] = p[0]; /* # of sectors/track */
+ ip[2] = *(u16 *)&p[2] & 0x0FFF; /* # of cylinders */
+ if (p[3] & (1 << 6)) { /* #-of-cylinders is 16-bit */
+ ip[2] |= (ip[0] & 0xF0) << 8;
+ ip[0] &= 0x0F;
+ }
+ printk(KERN_INFO "%s: "
+ "BIOS parameters CHS:%d/%d/%d, %u bytes %s sector\n",
+ name, ip[2], ip[0], ip[1], 256 << ((p[3] >> 4) & 3),
+ p[3] & 0x80 ? "hard" : "soft");
+ return 0;
+ }
+
+ /* Assume PC-9801-92 compatible parameters for HAs without BIOS. */
+ ip[0] = 8;
+ ip[1] = 32;
+ ip[2] = capacity / (8 * 32);
+ if (ip[2] > 65535) { /* if capacity >= 8GB */
+ /* Recent on-board adapters seem to use this parameter. */
+ ip[1] = 128;
+ ip[2] = capacity / (8 * 128);
+ if (ip[2] > 65535) { /* if capacity >= 32GB */
+ /* Clip the number of cylinders. Currently this
+ is the limit that we deal with. */
+ ip[2] = 65535;
+ }
+ }
+ printk(KERN_INFO "%s: BIOS parameters CHS:%d/%d/%d (assumed)\n",
+ name, ip[2], ip[0], ip[1]);
+ return 0;
+}
diff -Nru linux/drivers/scsi/sd.c linux98/drivers/scsi/sd.c
--- linux/drivers/scsi/sd.c 2003-01-14 14:59:09.000000000 +0900
+++ linux98/drivers/scsi/sd.c 2003-01-14 23:19:49.000000000 +0900
@@ -480,7 +480,7 @@
diskinfo[2] = sdkp->capacity >> 11;

/* override with calculated, extended default, or driver values */
- if (host->hostt->bios_param)
+ if (!pc98 && host->hostt->bios_param)
host->hostt->bios_param(sdp, bdev, sdkp->capacity, diskinfo);
else
scsicam_bios_param(bdev, sdkp->capacity, diskinfo);
@@ -1377,6 +1377,27 @@
kfree(sdkp);
}

+struct scsi_device *sd_find_params_by_bdev(struct block_device *bdev, char **disk_name, sector_t *capacity)
+{
+ struct scsi_disk *sdkp;
+ int major = major(to_kdev_t(bdev->bd_dev));
+
+ spin_lock(&sd_devlist_lock);
+ list_for_each_entry(sdkp, &sd_devlist, list) {
+ if (sdkp->disk->major == major) {
+ if (capacity)
+ *capacity = sdkp->capacity;
+ if (disk_name)
+ *disk_name = sdkp->disk->disk_name;
+ spin_unlock(&sd_devlist_lock);
+ return sdkp->device;
+ }
+ }
+
+ spin_unlock(&sd_devlist_lock);
+ return NULL;
+}
+
/**
* init_sd - entry point for this driver (both when built in or when
* a module).
diff -Nru linux/drivers/scsi/wd33c93.c linux98/drivers/scsi/wd33c93.c
--- linux/drivers/scsi/wd33c93.c 2003-01-02 12:22:29.000000000 +0900
+++ linux98/drivers/scsi/wd33c93.c 2003-01-04 16:17:32.000000000 +0900
@@ -84,6 +84,7 @@
#include <linux/init.h>
#include <asm/irq.h>
#include <linux/blk.h>
+#include <linux/spinlock.h>

#include "scsi.h"
#include "hosts.h"
@@ -173,7 +174,11 @@
MODULE_PARM(setup_strings, "s");
#endif

+static spinlock_t wd_lock = SPIN_LOCK_UNLOCKED;

+#if defined(CONFIG_SCSI_PC980155) || defined(CONFIG_SCSI_PC980155_MODULE)
+#include "pc980155regs.h"
+#else /* !CONFIG_SCSI_PC980155 */

static inline uchar read_wd33c93(const wd33c93_regs regs, uchar reg_num)
{
@@ -203,6 +208,7 @@
*regs.SCMD = cmd;
mb();
}
+#endif /* CONFIG_SCSI_PC980155 */


static inline uchar read_1_byte(const wd33c93_regs regs)
@@ -220,6 +226,7 @@
return x;
}

+#if !defined(CONFIG_SCSI_PC980155) && !defined(CONFIG_SCSI_PC980155_MODULE)

static void write_wd33c93_count(const wd33c93_regs regs, unsigned long value)
{
@@ -244,6 +251,7 @@
mb();
return value;
}
+#endif /* !CONFIG_SCSI_PC980155 */


/* The 33c93 needs to be told which direction a command transfers its
@@ -426,7 +434,6 @@
struct WD33C93_hostdata *hostdata = (struct WD33C93_hostdata *)instance->hostdata;
const wd33c93_regs regs = hostdata->regs;
Scsi_Cmnd *cmd, *prev;
-int i;

DB(DB_EXECUTE,printk("EX("))

@@ -589,9 +596,16 @@
* (take advantage of auto-incrementing)
*/

- *regs.SASR = WD_CDB_1;
- for (i=0; i<cmd->cmd_len; i++)
- *regs.SCMD = cmd->cmnd[i];
+#if defined(CONFIG_SCSI_PC980155) || defined(CONFIG_SCSI_PC980155_MODULE)
+ write_wd33c93_cdb(regs, cmd->cmd_len, cmd->cmnd);
+#else /* !CONFIG_SCSI_PC980155 */
+ {
+ int i;
+ *regs.SASR = WD_CDB_1;
+ for (i = 0; i < cmd->cmd_len; i++)
+ *regs.SCMD = cmd->cmnd[i];
+ }
+#endif /* CONFIG_SCSI_PC980155 */

/* The wd33c93 only knows about Group 0, 1, and 5 commands when
* it's doing a 'select-and-transfer'. To be safe, we write the
@@ -1703,7 +1717,7 @@
return 1;
}

-__setup("wd33c93", wd33c93_setup);
+__setup("wd33c93=", wd33c93_setup);


/* check_setup_args() returns index if key found, 0 if not
@@ -2037,4 +2051,10 @@
{
}

+EXPORT_SYMBOL(wd33c93_reset);
+EXPORT_SYMBOL(wd33c93_init);
+EXPORT_SYMBOL(wd33c93_release);
+EXPORT_SYMBOL(wd33c93_abort);
+EXPORT_SYMBOL(wd33c93_queuecommand);
+EXPORT_SYMBOL(wd33c93_intr);
MODULE_LICENSE("GPL");
diff -Nru linux/drivers/scsi/wd33c93.h linux98/drivers/scsi/wd33c93.h
--- linux/drivers/scsi/wd33c93.h 2002-10-12 13:21:35.000000000 +0900
+++ linux98/drivers/scsi/wd33c93.h 2002-10-12 14:18:53.000000000 +0900
@@ -186,8 +186,13 @@

/* This is what the 3393 chip looks like to us */
typedef struct {
+#if defined(CONFIG_SCSI_PC980155) || defined(CONFIG_SCSI_PC980155_MODULE)
+ volatile unsigned int *SASR;
+ volatile unsigned int *SCMD;
+#else
volatile unsigned char *SASR;
volatile unsigned char *SCMD;
+#endif
} wd33c93_regs;


2003-01-19 06:48:02

by Osamu Tomita

[permalink] [raw]
Subject: [PATCHSET] PC-9800 sub-arch (21/29) ac-update

This is patchset to support NEC PC-9800 subarchitecture
against 2.5.59 (21/29).

Updates drivers/pci/quirks.c in 2.5.50-ac1.

diff -Nru linux-2.5.53/drivers/pci/quirks.c linux98-2.5.53/drivers/pci/quirks.c
--- linux-2.5.53/drivers/pci/quirks.c 2002-12-24 14:19:26.000000000 +0900
+++ linux98-2.5.53/drivers/pci/quirks.c 2002-12-26 14:24:57.000000000 +0900
@@ -551,6 +551,8 @@
{ PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C596, quirk_isa_dma_hangs },
{ PCI_FIXUP_FINAL, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_0, quirk_isa_dma_hangs },
{ PCI_FIXUP_FINAL, PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_CBUS_1, quirk_isa_dma_hangs },
+ { PCI_FIXUP_FINAL, PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_CBUS_2, quirk_isa_dma_hangs },
+ { PCI_FIXUP_FINAL, PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_CBUS_3, quirk_isa_dma_hangs },
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_868, quirk_s3_64M },
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_968, quirk_s3_64M },
{ PCI_FIXUP_FINAL, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82437, quirk_triton },

2003-01-19 06:55:57

by Osamu Tomita

[permalink] [raw]
Subject: [PATCHSET] PC-9800 sub-arch (29/29) ac-update

This is patchset to support NEC PC-9800 subarchitecture
against 2.5.59 (29/29).

Updates include/asm-i386/upd4990a.h in 2.5.50-ac1.

diff -Nru linux-2.5.50-ac1/include/asm-i386/upd4990a.h linux98-2.5.54/include/asm-i386/upd4990a.h
--- linux-2.5.50-ac1/include/asm-i386/upd4990a.h 2003-01-04 10:47:57.000000000 +0900
+++ linux98-2.5.54/include/asm-i386/upd4990a.h 2003-01-04 13:51:27.000000000 +0900
@@ -13,10 +13,6 @@
#ifndef _ASM_I386_uPD4990A_H
#define _ASM_I386_uPD4990A_H

-#include <linux/config.h>
-
-#ifdef CONFIG_PC9800
-
#include <asm/io.h>

#define UPD4990A_IO (0x0020)
@@ -53,6 +49,4 @@
/* Caller should ignore all bits except bit0 */
#define UPD4990A_READ_DATA() inb(UPD4990A_IO_DATAOUT)

-#endif /* CONFIG_PC9800 */
-
#endif

2003-01-19 06:55:57

by Osamu Tomita

[permalink] [raw]
Subject: [PATCHSET] PC-9800 sub-arch (27/29) serial

This is patchset to support NEC PC-9800 subarchitecture
against 2.5.59 (27/29).

Serial port driver.

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/drivers/serial/Makefile linux98/drivers/serial/Makefile
--- linux/drivers/serial/Makefile 2003-01-09 13:04:14.000000000 +0900
+++ linux98/drivers/serial/Makefile 2003-01-10 11:04:30.000000000 +0900
@@ -29,3 +29,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 <[email protected]>
+ *
+ * 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 <[email protected]>");
+MODULE_DESCRIPTION("PC-9801 standard serial port driver Version 0.1alpha");
+MODULE_LICENSE("GPL");
diff -Nru linux/include/linux/serial_core.h linux98/include/linux/serial_core.h
--- linux/include/linux/serial_core.h 2003-01-09 13:03:55.000000000 +0900
+++ linux98/include/linux/serial_core.h 2003-01-10 10:53:38.000000000 +0900
@@ -58,6 +58,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__

2003-01-19 06:52:48

by Osamu Tomita

[permalink] [raw]
Subject: [PATCHSET] PC-9800 sub-arch (24/29) PNP

This is patchset to support NEC PC-9800 subarchitecture
against 2.5.59 (24/29).

Legacy bus PNP support.

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");

+#ifndef CONFIG_X86_PC9800
#define _PIDXR 0x279
#define _PNPWRP 0xa79
+#else
+#define _PIDXR 0x259
+#define _PNPWRP 0xa59
+#endif

/* short tags */
#define _STAG_PNPVERNO 0x01

2003-01-21 11:28:37

by Osamu Tomita

[permalink] [raw]
Subject: Re: [PATCHSET] PC-9800 sub-arch (3/29) alsa

Takashi Iwai wrote:
>
> Hi,
>
> At Sun, 19 Jan 2003 15:34:22 +0900,
> Osamu Tomita wrote:
> >
> > This is patchset to support NEC PC-9800 subarchitecture
> > against 2.5.59 (3/29).
> >
> > ALSA sound drivers for PC98
> > Fix bug in 2.5.59 and additional driver.
>
> are there any essential changes except for the replacement of
> CONFIG_PC9800 with CONFIG_X86_PC9800 ?
Only one change below.

diff -Nru linux/sound/drivers/mpu401/mpu401.c linux98/sound/drivers/mpu401/mpu40
1.c
--- linux/sound/drivers/mpu401/mpu401.c 2002-12-24 14:20:59.000000000 +0900
+++ linux98/sound/drivers/mpu401/mpu401.c 2003-01-04 14:05:38.000000000 +0
900
@@ -154,6 +154,9 @@
(void)(get_option(&str,&enable[nr_dev]) == 2 &&
get_option(&str,&index[nr_dev]) == 2 &&
get_id(&str,&id[nr_dev]) == 2 &&
+#ifdef CONFIG_X86_PC9800
+ get_option(&str,&pc98ii[nr_dev]) == 2 &&
+#endif
get_option(&str,(int *)&port[nr_dev]) == 2 &&
get_option(&str,&irq[nr_dev]) == 2);
nr_dev++;

Thanks,
Osamu Tomita

2003-01-21 11:32:06

by Takashi Iwai

[permalink] [raw]
Subject: Re: [PATCHSET] PC-9800 sub-arch (3/29) alsa

At Tue, 21 Jan 2003 20:37:28 +0900,
Osamu Tomita wrote:
>
> Takashi Iwai wrote:
> >
> > Hi,
> >
> > At Sun, 19 Jan 2003 15:34:22 +0900,
> > Osamu Tomita wrote:
> > >
> > > This is patchset to support NEC PC-9800 subarchitecture
> > > against 2.5.59 (3/29).
> > >
> > > ALSA sound drivers for PC98
> > > Fix bug in 2.5.59 and additional driver.
> >
> > are there any essential changes except for the replacement of
> > CONFIG_PC9800 with CONFIG_X86_PC9800 ?
> Only one change below.

thanks, i'll apply this change to ALSA cvs, too.


ciao,

Takashi