2003-03-21 02:18:42

by Osamu Tomita

[permalink] [raw]
Subject: [PATCH 2.5.65-ac1] Support PC-9800 subarchitecture (0/14) summary

This is the patchset to support NEC PC-9800 subarchitecture
against 2.5.65-ac1.

There is archived patchset at URL bellow.
http://downloads.sourceforge.jp/linux98/2768/linux98-2.5.65-ac1.patch.tar.bz2
Comments and test reports are wellcome.

Description:
o boot98-update.patch (1/14)
Update arch/i386/Makefile and arch/i386/boot98/*.
o console.patch (2/14)
PC98 Standard console support (without japanese kanji character).
o core-misc.patch (3/14)
Small patches for PC98 support core.
o dma.patch (4/14)
DMA support for PC98.
o floppy98-update.patch (5/14)
Update PC98 standard floppy driver.
o ide.patch (6/14)
PC98 standard IDE I/F support.
o kanji.patch (7/14)
japanese kanji character support for PC98 console.
o kconfig.patch (8/14)
Add selection for CONFIG_X86_PC9800.
o network_card.patch (9/14)
C-bus(PC98's legacy bus like ISA) network cards support.
o parport.patch (10/14)
Parallel port support.
o pci.patch (11/14)
Small changes for PCI support.
o pcmcia.patch (12/14)
Small change for PCMCIA (16bits) support.
o scsi.patch (13/14)
SCSI host adapter support.
o video_card-update.patch (14/14)
Add missing files for PC98 Standard text mode video driver.

Thanks,
Osamu Tomita <[email protected]>


2003-03-21 02:28:15

by Osamu Tomita

[permalink] [raw]
Subject: [PATCH 2.5.65-ac1] Support PC-9800 subarchitecture (1/14) boot98 update

This is the patch to support NEC PC-9800 subarchitecture
against 2.5.65-ac1. (1/14)

Update arch/i386/Makefile and arch/i386/boot98/* to syncronize with 2.5.65.

Regards,
Osamu Tomita

diff -Nru linux-2.5.65-ac1/arch/i386/Makefile linux98-2.5.65/arch/i386/Makefile
--- linux-2.5.65-ac1/arch/i386/Makefile 2003-03-20 09:09:40.000000000 +0900
+++ linux98-2.5.65/arch/i386/Makefile 2003-03-18 10:51:26.000000000 +0900
@@ -65,10 +65,6 @@
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
@@ -77,6 +73,10 @@
mflags-$(CONFIG_X86_SUMMIT) := -Iinclude/asm-i386/mach-summit
mcore-$(CONFIG_X86_SUMMIT) := mach-default

+# PC-9800 subarch support
+mflags-$(CONFIG_X86_PC9800) := -Iinclude/asm-i386/mach-pc9800
+mcore-$(CONFIG_X86_PC9800) := mach-pc9800
+
# default subarch .h files
mflags-y += -Iinclude/asm-i386/mach-default

diff -Nru linux-2.5.65-ac1/arch/i386/boot98/Makefile linux98-2.5.65/arch/i386/boot98/Makefile
--- linux-2.5.65-ac1/arch/i386/boot98/Makefile 2003-03-20 09:09:40.000000000 +0900
+++ linux98-2.5.65/arch/i386/boot98/Makefile 2003-03-18 08:52:00.000000000 +0900
@@ -25,9 +25,8 @@

#RAMDISK := -DRAMDISK=512

-EXTRA_TARGETS := vmlinux.bin bootsect bootsect.o \
- setup setup.o zImage bzImage
-
+targets := vmlinux.bin bootsect bootsect.o setup setup.o \
+ zImage bzImage
subdir- := compressed

host-progs := tools/build
@@ -62,8 +61,36 @@
$(Q)$(MAKE) -f scripts/Makefile.build obj=$(obj)/compressed \
IMAGE_OFFSET=$(IMAGE_OFFSET) $@

-zdisk: $(BOOTIMAGE)
- dd bs=8192 if=$(BOOTIMAGE) of=/dev/fd0
+# Set this if you want to pass append arguments to the zdisk/fdimage kernel
+FDARGS =
+
+$(obj)/mtools.conf: $(src)/mtools.conf.in
+ sed -e 's|@OBJ@|$(obj)|g' < $< > $@
+
+# This requires write access to /dev/fd0
+zdisk: $(BOOTIMAGE) $(obj)/mtools.conf
+ MTOOLSRC=$(obj)/mtools.conf mformat a: ; sync
+ syslinux /dev/fd0 ; sync
+ echo 'default linux $(FDARGS)' | \
+ MTOOLSRC=$(src)/mtools.conf mcopy - a:syslinux.cfg
+ MTOOLSRC=$(obj)/mtools.conf mcopy $(BOOTIMAGE) a:linux ; sync
+
+# These require being root or having syslinux 2.02 or higher installed
+fdimage fdimage144: $(BOOTIMAGE) $(obj)/mtools.conf
+ dd if=/dev/zero of=$(obj)/fdimage bs=1024 count=1440
+ MTOOLSRC=$(obj)/mtools.conf mformat v: ; sync
+ syslinux $(obj)/fdimage ; sync
+ echo 'default linux $(FDARGS)' | \
+ MTOOLSRC=$(obj)/mtools.conf mcopy - v:syslinux.cfg
+ MTOOLSRC=$(obj)/mtools.conf mcopy $(BOOTIMAGE) v:linux ; sync
+
+fdimage288: $(BOOTIMAGE) $(obj)/mtools.conf
+ dd if=/dev/zero of=$(obj)/fdimage bs=1024 count=2880
+ MTOOLSRC=$(obj)/mtools.conf mformat w: ; sync
+ syslinux $(obj)/fdimage ; sync
+ echo 'default linux $(FDARGS)' | \
+ MTOOLSRC=$(obj)/mtools.conf mcopy - w:syslinux.cfg
+ MTOOLSRC=$(obj)/mtools.conf mcopy $(BOOTIMAGE) w:linux ; sync

zlilo: $(BOOTIMAGE)
if [ -f $(INSTALL_PATH)/vmlinuz ]; then mv $(INSTALL_PATH)/vmlinuz $(INSTALL_PATH)/vmlinuz.old; fi
diff -Nru linux-2.5.65-ac1/arch/i386/boot98/compressed/Makefile linux98-2.5.65/arch/i386/boot98/compressed/Makefile
--- linux-2.5.65-ac1/arch/i386/boot98/compressed/Makefile 2003-03-20 09:09:40.000000000 +0900
+++ linux98-2.5.65/arch/i386/boot98/compressed/Makefile 2003-03-18 08:52:00.000000000 +0900
@@ -4,7 +4,7 @@
# create a compressed vmlinux image from the original vmlinux
#

-EXTRA_TARGETS := vmlinux vmlinux.bin vmlinux.bin.gz head.o misc.o piggy.o
+targets := vmlinux vmlinux.bin vmlinux.bin.gz head.o misc.o piggy.o
EXTRA_AFLAGS := -traditional

LDFLAGS_vmlinux := -Ttext $(IMAGE_OFFSET) -e startup_32
diff -Nru linux-2.5.65/arch/i386/boot98/mtools.conf.in linux98-2.5.65/arch/i386/boot98/mtools.conf.in
--- linux-2.5.65/arch/i386/boot98/mtools.conf.in 1970-01-01 09:00:00.000000000 +0900
+++ linux98-2.5.65/arch/i386/boot98/mtools.conf.in 2003-03-18 08:52:00.000000000 +0900
@@ -0,0 +1,17 @@
+#
+# mtools configuration file for "make (b)zdisk"
+#
+
+# Actual floppy drive
+drive a:
+ file="/dev/fd0"
+
+# 1.44 MB floppy disk image
+drive v:
+ file="@OBJ@/fdimage" cylinders=80 heads=2 sectors=18 filter
+
+# 2.88 MB floppy disk image (mostly for virtual uses)
+drive w:
+ file="@OBJ@/fdimage" cylinders=80 heads=2 sectors=36 filter
+
+
diff -Nru linux-2.5.65-ac1/arch/i386/boot98/tools/build.c linux98-2.5.65/arch/i386/boot98/tools/build.c
--- linux-2.5.65-ac1/arch/i386/boot98/tools/build.c 2003-03-20 09:09:40.000000000 +0900
+++ linux98-2.5.65/arch/i386/boot98/tools/build.c 2003-03-18 10:39:05.000000000 +0900
@@ -149,13 +149,10 @@
sz = sb.st_size;
fprintf (stderr, "System is %d kB\n", sz/1024);
sys_size = (sz + 15) / 16;
- /* 0x28000*16 = 2.5 MB, conservative estimate for the current maximum */
- if (sys_size > (is_big_kernel ? 0x28000 : DEF_SYSSIZE))
+ /* 0x40000*16 = 4.0 MB, reasonable estimate for the current maximum */
+ if (sys_size > (is_big_kernel ? 0x40000 : DEF_SYSSIZE))
die("System is too big. Try using %smodules.",
is_big_kernel ? "" : "bzImage or ");
- if (sys_size > 0xefff)
- fprintf(stderr,"warning: kernel is too big for standalone boot "
- "from floppy\n");
while (sz > 0) {
int l, n;

2003-03-21 02:37:05

by Osamu Tomita

[permalink] [raw]
Subject: [PATCH 2.5.65-ac1] Support PC-9800 subarchitecture (6/14) IDE

This is the patch to support NEC PC-9800 subarchitecture
against 2.5.65-ac1. (6/14)

PC98 standard IDE I/F support.
- Change default IO port address and IRQ.
- Add chipset "ide_pc9800".
- Add IDE0/1 select function becase PC98 uses common IO port to access them.
- Request region exactly for other optional cards.
- Get BIOS C/H/S parameter for PC98.

Regards,
Osamu Tomita

diff -Nru linux-2.5.64-ac3/drivers/ide/ide-disk.c linux98-2.5.64-ac3/drivers/ide/ide-disk.c
--- linux-2.5.64-ac3/drivers/ide/ide-disk.c 2003-03-08 12:13:46.000000000 +0900
+++ linux98-2.5.64-ac3/drivers/ide/ide-disk.c 2003-03-08 12:29:29.000000000 +0900
@@ -1574,6 +1574,71 @@

(void) probe_lba_addressing(drive, 1);

+#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;
@@ -1607,6 +1672,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-2.5.65-ac1/drivers/ide/ide-probe.c linux98-2.5.65-ac1/drivers/ide/ide-probe.c
--- linux-2.5.65-ac1/drivers/ide/ide-probe.c 2003-03-20 09:09:44.000000000 +0900
+++ linux98-2.5.65-ac1/drivers/ide/ide-probe.c 2003-03-20 11:20:47.000000000 +0900
@@ -669,7 +669,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])
@@ -718,7 +718,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);
@@ -806,6 +808,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) {
@@ -1167,7 +1172,7 @@
ide_init_drive(drive);
}

-#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,
@@ -1177,6 +1182,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-2.5.65-ac1/drivers/ide/ide.c linux98-2.5.65-ac1/drivers/ide/ide.c
--- linux-2.5.65-ac1/drivers/ide/ide.c 2003-03-20 09:09:44.000000000 +0900
+++ linux98-2.5.65-ac4/drivers/ide/ide.c 2003-03-20 11:20:47.000000000 +0900
@@ -550,7 +550,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);
}
}
}
@@ -2117,6 +2118,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/include/linux/hdreg.h linux98/include/linux/hdreg.h
--- linux/include/linux/hdreg.h 2003-02-15 08:51:42.000000000 +0900
+++ linux98/include/linux/hdreg.h 2003-02-20 10:18:37.000000000 +0900
@@ -5,11 +5,29 @@
* This file contains some defines for the AT-hd-controller.
* Various sources.
*/
+#include <linux/config.h>

/* ide.c has its own port definitions in "ide.h" */

#define HD_IRQ 14

+#ifdef CONFIG_X86_PC9800
+/* Hd controller regs. for NEC PC-9800 */
+#define HD_DATA 0x640 /* _CTL when writing */
+#define HD_ERROR 0x642 /* see err-bits */
+#define HD_NSECTOR 0x644 /* nr of sectors to read/write */
+#define HD_SECTOR 0x646 /* starting sector */
+#define HD_LCYL 0x648 /* starting cylinder */
+#define HD_HCYL 0x64a /* high byte of starting cyl */
+#define HD_CURRENT 0x64c /* 101dhhhh , d=drive, hhhh=head */
+#define HD_STATUS 0x64e /* see status-bits */
+#define HD_FEATURE HD_ERROR /* same io address, read=error, write=feature */
+#define HD_PRECOMP HD_FEATURE /* obsolete use of this port - predates IDE */
+#define HD_COMMAND HD_STATUS /* same io address, read=status, write=cmd */
+
+#define HD_CMD 0x74c /* used for resets */
+#define HD_ALTSTATUS 0x74c /* same as HD_STATUS but doesn't clear irq */
+#else /* !CONFIG_X86_PC9800 */
/* Hd controller regs. Ref: IBM AT Bios-listing */
#define HD_DATA 0x1f0 /* _CTL when writing */
#define HD_ERROR 0x1f1 /* see err-bits */
@@ -25,6 +43,7 @@

#define HD_CMD 0x3f6 /* used for resets */
#define HD_ALTSTATUS 0x3f6 /* same as HD_STATUS but doesn't clear irq */
+#endif /* CONFIG_X86_PC9800 */

/* remainder is shared between hd.c, ide.c, ide-cd.c, and the hdparm utility */

2003-03-21 02:35:43

by Osamu Tomita

[permalink] [raw]
Subject: [PATCH 2.5.65-ac1] Support PC-9800 subarchitecture (5/14) floppy update

This is the patch to support NEC PC-9800 subarchitecture
against 2.5.65-ac1. (5/14)

Update drivers/block/floppy98.c to syncronize with 2.5.65.
(Driver for PC98 standard floppy disk drive.)

diff -Nru linux-2.5.65-ac1/drivers/block/floppy98.c linux98-2.5.65/drivers/block/floppy98.c
--- linux-2.5.65-ac1/drivers/block/floppy98.c 2003-03-20 09:09:42.000000000 +0900
+++ linux98-2.5.65/drivers/block/floppy98.c 2003-03-18 11:57:40.000000000 +0900
@@ -4273,8 +4273,7 @@
}

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);
+ if (register_blkdev(FLOPPY_MAJOR,"fd")) {
err = -EBUSY;
goto out;
}

2003-03-21 02:31:31

by Osamu Tomita

[permalink] [raw]
Subject: [PATCH 2.5.65-ac1] Support PC-9800 subarchitecture (2/14) console

This is the patch to support NEC PC-9800 subarchitecture
against 2.5.65-ac1. (2/14)

PC98 Standard console support (without japanese kanji character).
Text mode video card on PC98 is useing 2bytes of VRAM by 1 character to
support japanese kanji character. VRAM for attributes is mapped another
address (+0x2000).
Character codes 0x80-0xff are diffrent with standerd PC.

Regards,
Osamu Tomita

diff -Nru linux-2.5.60/drivers/char/Makefile linux98-2.5.60/drivers/char/Makefile
--- linux-2.5.60/drivers/char/Makefile 2003-02-18 11:10:03.000000000 +0900
+++ linux98-2.5.60/drivers/char/Makefile 2003-02-20 09:16:30.000000000 +0900
@@ -5,7 +5,11 @@
#
# This file contains the font map for the default (hardware) font
#
+ifeq ($(CONFIG_X86_PC9800),y)
+FONTMAPFILE = pc9800.uni
+else
FONTMAPFILE = cp437.uni
+endif

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

diff -Nru linux/drivers/char/console_macros.h linux98/drivers/char/console_macros.h
--- linux/drivers/char/console_macros.h Sat Oct 19 13:01:17 2002
+++ linux98/drivers/char/console_macros.h Mon Oct 28 16:53:39 2002
@@ -55,6 +55,10 @@
#define s_reverse (vc_cons[currcons].d->vc_s_reverse)
#define ulcolor (vc_cons[currcons].d->vc_ulcolor)
#define halfcolor (vc_cons[currcons].d->vc_halfcolor)
+#define def_attr (vc_cons[currcons].d->vc_def_attr)
+#define ul_attr (vc_cons[currcons].d->vc_ul_attr)
+#define half_attr (vc_cons[currcons].d->vc_half_attr)
+#define bold_attr (vc_cons[currcons].d->vc_bold_attr)
#define tab_stop (vc_cons[currcons].d->vc_tab_stop)
#define palette (vc_cons[currcons].d->vc_palette)
#define bell_pitch (vc_cons[currcons].d->vc_bell_pitch)
diff -Nru linux/drivers/char/console_pc9800.h linux98/drivers/char/console_pc9800.h
--- linux/drivers/char/console_pc9800.h Thu Jan 1 09:00:00 1970
+++ linux98/drivers/char/console_pc9800.h Mon Oct 28 11:48:10 2002
@@ -0,0 +1,14 @@
+#ifndef __CONSOLE_PC9800_H
+#define __CONSOLE_PC9800_H
+
+#define BLANK_ATTR 0x00E1
+
+#define JIS_CODE 0x01
+#define EUC_CODE 0x00
+#define SJIS_CODE 0x02
+#define JIS_CODE_ASCII 0x00
+#define JIS_CODE_78 0x01
+#define JIS_CODE_83 0x02
+#define JIS_CODE_90 0x03
+
+#endif /* __CONSOLE_PC9800_H */
diff -Nru linux/drivers/char/consolemap.c linux98/drivers/char/consolemap.c
--- linux/drivers/char/consolemap.c 2002-12-10 11:46:14.000000000 +0900
+++ linux98/drivers/char/consolemap.c 2002-12-16 11:27:23.000000000 +0900
@@ -23,7 +23,7 @@
#include <linux/consolemap.h>
#include <linux/vt_kern.h>

-static unsigned short translations[][256] = {
+unsigned short translations[][256] = {
/* 8-bit Latin-1 mapped to Unicode -- trivial mapping */
{
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
@@ -163,7 +163,59 @@
0xf0e8, 0xf0e9, 0xf0ea, 0xf0eb, 0xf0ec, 0xf0ed, 0xf0ee, 0xf0ef,
0xf0f0, 0xf0f1, 0xf0f2, 0xf0f3, 0xf0f4, 0xf0f5, 0xf0f6, 0xf0f7,
0xf0f8, 0xf0f9, 0xf0fa, 0xf0fb, 0xf0fc, 0xf0fd, 0xf0fe, 0xf0ff
- }
+ },
+ /* JIS X0201 mapped to Unicode */
+ /* code marked with ** is not defined in JIS X0201.
+ So 0x00 - 0x1f are mapped to same to Laten1,
+ and others are mapped to PC-9800 internal font# directry */
+ {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+/* ** ** ** ** ** ** ** ** */
+ 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
+/* ** ** ** ** ** ** ** ** */
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+/* ** ** ** ** ** ** ** ** */
+ 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
+/* ** ** ** ** ** ** ** ** */
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+ 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+ 0x0058, 0x0059, 0x005a, 0x005b, 0x00a5, 0x005d, 0x005e, 0x005f,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+ 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x203e, 0xf07f,
+/* ** */
+ 0xf080, 0xf081, 0xf082, 0xf083, 0xf084, 0xf085, 0xf086, 0xf087,
+/* ** ** ** ** ** ** ** ** */
+ 0xf088, 0xf089, 0xf08a, 0xf08b, 0xf08c, 0xf08d, 0xf08e, 0xf08f,
+/* ** ** ** ** ** ** ** ** */
+ 0xf090, 0xf091, 0xf092, 0xf093, 0xf094, 0xf095, 0xf096, 0xf097,
+/* ** ** ** ** ** ** ** ** */
+ 0xf098, 0xf099, 0xf09a, 0xf09b, 0xf09c, 0xf09d, 0xf09e, 0xf09f,
+/* ** ** ** ** ** ** ** ** */
+ 0xf0a0, 0xff61, 0xff62, 0xff63, 0xff64, 0xff65, 0xff66, 0xff67,
+/* ** */
+ 0xff68, 0xff69, 0xff6a, 0xff6b, 0xff6c, 0xff6d, 0xff6e, 0xff6f,
+ 0xff70, 0xff71, 0xff72, 0xff73, 0xff74, 0xff75, 0xff76, 0xff77,
+ 0xff78, 0xff79, 0xff7a, 0xff7b, 0xff7c, 0xff7d, 0xff7e, 0xff7f,
+ 0xff80, 0xff81, 0xff82, 0xff83, 0xff84, 0xff85, 0xff86, 0xff87,
+ 0xff88, 0xff89, 0xff8a, 0xff8b, 0xff8c, 0xff8d, 0xff8e, 0xff8f,
+ 0xff90, 0xff91, 0xff92, 0xff93, 0xff94, 0xff95, 0xff96, 0xff97,
+ 0xff98, 0xff99, 0xff9a, 0xff9b, 0xff9c, 0xff9d, 0xff9e, 0xff9f,
+ 0xf0e0, 0xf0e1, 0xf0e2, 0xf0e3, 0xf0e4, 0xf0e5, 0xf0e6, 0xf0e7,
+/* ** ** ** ** ** ** ** ** */
+ 0xf0e8, 0xf0e9, 0xf0ea, 0xf0eb, 0xf0ec, 0xf0ed, 0xf0ee, 0xf0ef,
+/* ** ** ** ** ** ** ** ** */
+ 0xf0f0, 0xf0f1, 0xf0f2, 0xf0f3, 0xf0f4, 0xf0f5, 0xf0f6, 0xf0f7,
+/* ** ** ** ** ** ** ** ** */
+ 0xf0f8, 0xf0f9, 0xf0fa, 0xf0fb, 0xf0fc, 0xf0fd, 0xf0fe, 0xf0ff
+/* ** ** ** ** ** ** ** ** */
+ },
};

/* The standard kernel character-to-font mappings are not invertible
@@ -177,7 +229,7 @@
u16 **uni_pgdir[32];
unsigned long refcount;
unsigned long sum;
- unsigned char *inverse_translations[4];
+ unsigned char *inverse_translations[5];
int readonly;
};

diff -Nru linux/drivers/char/pc9800.uni linux98/drivers/char/pc9800.uni
--- linux/drivers/char/pc9800.uni Thu Jan 1 09:00:00 1970
+++ linux98/drivers/char/pc9800.uni Fri Aug 17 21:50:17 2001
@@ -0,0 +1,260 @@
+#
+# Unicode table for PC-9800 console.
+# Copyright (C) 1998,2001 Linux/98 project (project Seraphim)
+# Kyoto University Microcomputer Club (KMC).
+#
+
+# Kore ha unicode wo 98 no ROM no font ni taio saseru tame no
+# map desu.
+
+# Characters for control codes.
+# PC-9800 uses 2-char sequences while Unicode uses 3-char for some codes.
+0x00
+0x01 U+2401 # SH / SOH
+0x02 U+2402 # SX / SOX
+0x03 U+2403 # EX / ETX
+0x04 U+2404 # ET / EOT
+0x05 U+2405 # EQ / ENQ
+0x06 U+2406 # AK / ACK
+0x07 U+2407 # BL / BEL
+0x08 U+2408 # BS
+0x09 U+2409 # HT
+0x0a U+240a # LF
+0x0b # HM / (VT)
+0x0c # CL / (FF)
+0x0d U+240d # CR
+0x0e # SO / (SS)
+0x0f U+240f # SI
+0x10 U+2410 # DE / DLE
+0x11 U+2411 # D1 / DC1
+0x12 U+2412 # D2 / DC2
+0x13 U+2413 # D3 / DC3
+0x14 U+2414 # D4 / DC4
+0x15 U+2415 # NK / NAK
+0x16 U+2416 # SN / SYN
+0x17 U+2417 # EB / ETB
+0x18 U+2418 # CN / CAN
+0x19 U+2419 # EM
+0x1a U+241a # SB / SUB
+0x1b U+241b # EC / ESC
+
+# arrow
+0x1c U+2192 U+ffeb # right
+0x1d U+2190 U+ffe9 # left
+0x1e U+2191 U+ffea # up
+0x1f U+2193 U+ffec # down
+
+#
+# The ASCII range is identity-mapped, but some of the characters also
+# have to act as substitutes, especially the upper-case characters.
+#
+0x20 U+0020
+0x21 U+0021
+# U+00a8 is Latin-1 Supplement DIAELESIS.
+0x22 U+0022 U+00a8
+0x23 U+0023
+0x24 U+0024
+0x25 U+0025
+0x26 U+0026
+0x26 U+2019 # General Punctuation "RIGHT SINGLE QUOTATION MARK"
+0x27 U+0027 U+2032
+0x28 U+0028
+0x29 U+0029
+0x2a U+002a
+0x2b U+002b
+# U+00b8 is Latin-1 Supplement CEDILLA.
+0x2c U+002c U+00b8
+# U+00b8 is Latin-1 Supplement SOFT HYPHEN.
+0x2d U+002d U+00ad
+0x2d U+2212 # Mathematical Operators "MINUS SIGN"
+0x2e U+002e
+0x2f U+002f
+0x2f U+2044 # General Punctuation "FRACTION SLASH"
+0x2f U+2215 # Mathematical Operators "DIVISION SLASH"
+0x30 U+0030
+0x31 U+0031
+0x32 U+0032
+0x33 U+0033
+0x34 U+0034
+0x35 U+0035
+0x36 U+0036
+0x37 U+0037
+0x38 U+0038
+0x39 U+0039
+0x3a U+003a
+0x3a U+003a # Mathematical Operators "RATIO"
+0x3b U+003b
+0x3c U+003c
+0x3d U+003d
+0x3e U+003e
+0x3f U+003f
+0x40 U+0040
+0x41 U+0041 U+00c0 U+00c1 U+00c2 U+00c3
+0x42 U+0042
+# U+00a9 is Latin-1 Supplement COPYRIGHT SIGN.
+0x43 U+0043 U+00a9
+0x44 U+0044
+0x45 U+0045 U+00c8 U+00ca U+00cb
+0x46 U+0046
+0x47 U+0047
+0x48 U+0048
+0x49 U+0049 U+00cc U+00cd U+00ce U+00cf
+0x4a U+004a
+# U+212a: Letterlike Symbols "KELVIN SIGN"
+0x4b U+004b U+212a
+0x4c U+004c
+0x4d U+004d
+0x4e U+004e
+0x4f U+004f U+00d2 U+00d3 U+00d4 U+00d5
+0x50 U+0050
+0x51 U+0051
+# U+00ae: Latin-1 Supplement "REGISTERED SIGN"
+0x52 U+0052 U+00ae
+0x53 U+0053
+0x54 U+0054
+0x55 U+0055 U+00d9 U+00da U+00db
+0x56 U+0056
+0x57 U+0057
+0x58 U+0058
+0x59 U+0059 U+00dd
+0x5a U+005a
+0x5b U+005b
+0x5c U+00a5 # Latin-1 Supplement "YEN SIGN"
+0x5d U+005d
+0x5e U+005e
+0x5f U+005f U+f804
+0x60 U+0060 U+2035
+0x61 U+0061 U+00e3
+0x62 U+0062
+0x63 U+0063
+0x64 U+0064
+0x65 U+0065
+0x66 U+0066
+0x67 U+0067
+0x68 U+0068
+0x69 U+0069
+0x6a U+006a
+0x6b U+006b
+0x6c U+006c
+0x6d U+006d
+0x6e U+006e
+0x6f U+006f U+00f5
+0x70 U+0070
+0x71 U+0071
+0x72 U+0072
+0x73 U+0073
+0x74 U+0074
+0x75 U+0075
+0x76 U+0076
+0x77 U+0077
+0x78 U+0078 U+00d7
+0x79 U+0079 U+00fd
+0x7a U+007a
+0x7b U+007b
+# U+00a6: Latin-1 Supplement "BROKEN (VERTICAL) BAR"
+0x7c U+007c U+00a6
+0x7d U+007d
+0x7e U+007e
+
+# kuhaku
+0x7f # U+2302
+
+# Block Elements.
+0x80 U+2581 # LOWER ONE EIGHTH BLOCK
+0x81 U+2582 # LOWER ONE QUARTER BLOCK
+0x82 U+2583 # LOWER THREE EIGHTHS BLOCK
+0x83 U+2584 # LOWER HALF BLOCK
+0x84 U+2585 # LOWER FIVE EIGHTHS BLOCK
+0x85 U+2586 # LOWER THREE QUARTERS BLOCK
+0x86 U+2587 # LOWER SEVEN EIGHTHS BLOCK
+0x87 U+2588 # FULL BLOCK
+0x88 U+258f # LEFT ONE EIGHTH BLOCK
+0x89 U+258e # LEFT ONE QUARTER BLOCK
+0x8a U+258d # LEFT THREE EIGHTHS BLOCK
+0x8b U+258c # LEFT HALF BLOCK
+0x8c U+258b # LEFT FIVE EIGHTHS BLOCK
+0x8d U+258a # LEFT THREE QUARTERS BLOCK
+0x8e U+2589 # LEFT SEVEN EIGHTHS BLOCK
+
+# Box Drawing.
+0x8f U+253c
+0x90 U+2534
+0x91 U+252c
+0x92 U+2524
+0x93 U+251c
+0x94 U+203e # General Punctuation "OVERLINE" (= "SPACING OVERSCORE")
+0x95 U+2500 # Box Drawing "BOX DRAWING LIGHT HORIZONTAL"
+0x96 U+2502 # Box Drawing "BOX DRAWING LIGHT VERTICAL"
+0x96 U+ffe8 # Halfwidth symbol variants "HALFWIDTH FORMS LIGHT VERTICAL"
+0x97 U+2595 # Block Elements "RIGHT ONE EIGHTH BLOCK"
+0x98 U+250c
+0x99 U+2510
+0x9a U+2514
+0x9b U+2518
+
+0x9c U+256d # "BOX DRAWING LIGHT ARC DOWN AND RIGHT"
+0x9d U+256e # "BOX DRAWING LIGHT ARC DOWN AND LEFT"
+0x9e U+2570 # "BOX DRAWING LIGHT ARC UP AND RIGHT"
+0x9f U+256f # "BOX DRAWING LIGHT ARC UP AND LEFT"
+
+0xa0 # another whitespace
+
+# Halfwidth CJK punctuation
+0xa1 - 0xa4 U+ff61 - U+ff64
+
+# Halfwidth Katakana variants
+0xa5 - 0xdf U+ff65 - U+ff9f
+0xa5 U+00b7 # Latin-1 Supplement "MIDDLE DOT"
+0xdf U+00b0 # Latin-1 Supplement "DEGREE SIGN"
+
+# Box Drawing
+0xe0 U+2550 # "BOX DRAWING DOUBLE HORIZONTAL"
+0xe1 U+255e # "BOX DRAWING VERTICAL SINGLE AND RIGHT DOUBLE"
+0xe2 U+256a # "BOX DRAWING VERTICAL SINGLE AND HORIZONTAL DOUBLE"
+0xe3 U+2561 # "BOX DRAWING VERTICAL SINGLE AND LEFT DOUBLE"
+
+# Geometric Shapes
+0xe4 U+25e2 # "BLACK LOWER RIGHT TRIANGLE"
+0xe5 U+25e3 # "BLACK LOWER LEFT TRIANGLE"
+0xe6 U+25e5 # "BLACK UPPER RIGHT TRIANGLE"
+0xe7 U+25e4 # "BLACK UPPER LEFT TRIANGLE"
+
+# Playing card symbols
+0xe8 U+2660 # "BLACK SPADE SUIT"
+0xe9 U+2665 # "BLACK HEART SUIT"
+0xea U+2666 # "BLACK DIAMOND SUIT"
+0xeb U+2663 # "BLACK CLUB SUIT"
+
+# Geometric Shapes
+0xec U+25cf # "BLACK CIRCLE"
+0xed U+25cb U+25ef # "WHITE CIRCLE", "LARGE CIRCLE"
+
+# Box Drawing
+0xee U+2571 # "BOX DRAWING LIGHT DIAGONAL UPPER RIGHT TO LOWER LEFT"
+0xef U+2572 # "BOX DRAWING LIGHT DIAGONAL UPPER LEFT TO LOWER RIGHT"
+0xf0 U+2573 # "BOX DRAWING LIGHT DIAGONAL CROSS"
+
+# CJK Unified Ideographs (XXX - should these be here?)
+0xf1 U+5186
+0xf2 U+5e74
+0xf3 U+6708
+0xf4 U+65e5
+0xf5 U+6642
+0xf6 U+5206
+0xf7 U+79d2
+
+# unassigned
+0xf8
+0xf9
+0xfa
+0xfb
+
+0xfc U+005c # "REVERSE SOLIDUS" / "BACKSLASH"
+0xfc U+2216 # Mathematical Operators "SET MINUS"
+
+# unassigned
+0xfd
+0xfe
+0xff
+
+# End of pc9800.uni
diff -Nru linux-2.5.65/drivers/char/vt.c linux98-2.5.65/drivers/char/vt.c
--- linux-2.5.65/drivers/char/vt.c 2003-03-18 08:52:14.000000000 +0900
+++ linux98-2.5.65/drivers/char/vt.c 2003-03-18 11:12:28.000000000 +0900
@@ -107,6 +107,10 @@

#include "console_macros.h"

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

const struct consw *conswitchp;

@@ -301,7 +305,7 @@
xx = nxx; yy = nyy;
}
for(;;) {
- u16 attrib = scr_readw(p) & 0xff00;
+ vram_char_t attrib = scr_readw(p) & 0xff00;
int startx = xx;
u16 *q = p;
while (xx < video_num_columns && count) {
@@ -387,6 +391,8 @@
{
attr = build_attr(currcons, color, intensity, blink, underline, reverse ^ decscnm);
video_erase_char = (build_attr(currcons, color, 1, blink, 0, decscnm) << 8) | ' ';
+ if (pc98 && decscnm)
+ video_erase_char |= 0x0400; /* reverse */
}

/* Note: inverting the screen twice should revert to the original state */
@@ -403,7 +409,7 @@
else {
u16 *q = p;
int cnt = count;
- u16 a;
+ vram_char_t a;

if (!can_do_color) {
while (cnt--) {
@@ -437,7 +443,7 @@
void complement_pos(int currcons, int offset)
{
static unsigned short *p;
- static unsigned short old;
+ static vram_char_t old;
static unsigned short oldx, oldy;

if (p) {
@@ -448,10 +454,15 @@
if (offset == -1)
p = NULL;
else {
- unsigned short new;
+ vram_char_t new;
p = screenpos(currcons, offset, 1);
old = scr_readw(p);
+#ifdef CONFIG_FB_EGC
+ new = (old & 0xff0000ff) | ((old & 0xf000) >> 4)
+ | ((old & 0xf00) << 4);
+#else
new = old ^ complement_mask;
+#endif
scr_writew(new, p);
if (DO_UPDATE) {
oldx = (offset >> 1) % video_num_columns;
@@ -510,7 +521,7 @@

static void add_softcursor(int currcons)
{
- int i = scr_readw((u16 *) pos);
+ vram_char_t i = scr_readw((u16 *) pos);
u32 type = cursor_type;

if (! (type & 0x10)) return;
@@ -646,8 +657,12 @@
complement_mask = 0;
can_do_color = 0;
sw->con_init(vc_cons[currcons].d, init);
- if (!complement_mask)
- complement_mask = can_do_color ? 0x7700 : 0x0800;
+ if (!complement_mask) {
+ if (pc98)
+ complement_mask = 0x0400;
+ else
+ complement_mask = can_do_color ? 0x7700 : 0x0800;
+ }
s_complement_mask = complement_mask;
video_size_row = video_num_columns<<1;
screenbuf_size = video_num_lines*video_size_row;
@@ -679,7 +694,7 @@
visual_init(currcons, 1);
if (!*vc_cons[currcons].d->vc_uni_pagedir_loc)
con_set_default_unimap(currcons);
- q = (long)kmalloc(screenbuf_size, GFP_KERNEL);
+ q = (long)kmalloc(screenbuf_size + (pc98 ? screenbuf_size : 0), GFP_KERNEL);
if (!q) {
kfree((char *) p);
vc_cons[currcons].d = NULL;
@@ -732,7 +747,7 @@
if (new_cols == video_num_columns && new_rows == video_num_lines)
return 0;

- newscreen = (unsigned short *) kmalloc(new_screen_size, GFP_USER);
+ newscreen = (unsigned short *) kmalloc(new_screen_size + (pc98 ? new_screen_size : 0), GFP_USER);
if (!newscreen)
return -ENOMEM;

@@ -1263,6 +1278,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) {
@@ -2429,9 +2448,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);
}
@@ -2472,7 +2499,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);
@@ -2976,9 +3008,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;
@@ -3040,8 +3075,10 @@
EXPORT_SYMBOL(default_red);
EXPORT_SYMBOL(default_grn);
EXPORT_SYMBOL(default_blu);
+#ifndef CONFIG_X86_PC9800
EXPORT_SYMBOL(video_font_height);
EXPORT_SYMBOL(video_scan_lines);
+#endif
EXPORT_SYMBOL(vc_cons_allocated);
EXPORT_SYMBOL(update_region);
EXPORT_SYMBOL(redraw_screen);
diff -Nru linux/drivers/char/vt_ioctl.c linux98/drivers/char/vt_ioctl.c
--- linux/drivers/char/vt_ioctl.c 2002-12-10 11:46:13.000000000 +0900
+++ linux98/drivers/char/vt_ioctl.c 2002-12-16 13:15:34.000000000 +0900
@@ -63,9 +63,11 @@
asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int on);
#endif

+#ifndef CONFIG_X86_PC9800
unsigned int video_font_height;
unsigned int default_font_height;
unsigned int video_scan_lines;
+#endif

/*
* these are the valid i/o ports we're allowed to change. they map all the
@@ -637,6 +639,17 @@
return 0;
}

+#ifdef CONFIG_X86_PC9800
+ case VT_GDC_RESIZE:
+ {
+ if (!perm)
+ return -EPERM;
+/* con_adjust_height(0);*/
+ update_screen(console);
+ return 0;
+ }
+#endif
+
case VT_SETMODE:
{
struct vt_mode tmp;
@@ -830,7 +843,9 @@
__get_user(clin, &vtconsize->v_clin);
__get_user(vcol, &vtconsize->v_vcol);
__get_user(ccol, &vtconsize->v_ccol);
+#ifndef CONFIG_X86_PC9800
vlin = vlin ? vlin : video_scan_lines;
+#endif
if (clin) {
if (ll) {
if (ll != vlin/clin)
@@ -849,10 +864,12 @@
if (clin > 32)
return -EINVAL;

+#ifndef CONFIG_X86_PC9800
if (vlin)
video_scan_lines = vlin;
if (clin)
video_font_height = clin;
+#endif

for (i = 0; i < MAX_NR_CONSOLES; i++)
vc_resize(i, cc, ll);
@@ -1022,8 +1039,10 @@
vt_cons[new_console]->vt_mode.frsig = 0;
vt_cons[new_console]->vt_pid = -1;
vt_cons[new_console]->vt_newvt = -1;
+#ifndef CONFIG_X86_PC9800
if (!in_interrupt()) /* Via keyboard.c:SAK() - akpm */
reset_palette(new_console) ;
+#endif
}

/*
diff -Nru linux-2.5.59/drivers/video/console/Kconfig linux98-2.5.59/drivers/video/console/Kconfig
--- linux-2.5.59/drivers/video/console/Kconfig 2003-01-17 13:22:14.000000000 +0900
+++ linux98-2.5.59/drivers/video/console/Kconfig 2003-01-17 13:43:44.000000000 +0900
@@ -6,7 +6,7 @@

config VGA_CONSOLE
bool "VGA text console"
- depends on !ARCH_ACORN && !ARCH_EBSA110 || !4xx && !8xx
+ depends on !X86_PC9800 && !ARCH_ACORN && !ARCH_EBSA110 || !4xx && !8xx
help
Saying Y here will allow you to use Linux in text mode through a
display that complies with the generic VGA standard. Virtually
@@ -97,6 +97,18 @@
Say Y to build a console driver for Sun machines that uses the
terminal emulation built into their console PROMS.

+config GDC_CONSOLE
+ bool "PC-9800 GDC text console"
+ depends on X86_PC9800
+ default y
+ help
+ This enables support for PC-9800 standard text mode console.
+ If use NEC PC-9801/PC-9821, Say Y.
+
+config GDC_32BITACCESS
+ bool "Enable 32-bit access to text video RAM"
+ depends on GDC_CONSOLE
+
config DUMMY_CONSOLE
bool
depends on PROM_CONSOLE!=y || VGA_CONSOLE!=y || SGI_NEWPORT_CONSOLE!=y
diff -Nru linux/include/linux/console.h linux98/include/linux/console.h
--- linux/include/linux/console.h 2003-02-15 08:51:33.000000000 +0900
+++ linux98/include/linux/console.h 2003-02-20 09:47:41.000000000 +0900
@@ -17,6 +17,13 @@
#include <linux/types.h>
#include <linux/kdev_t.h>
#include <linux/spinlock.h>
+#include <linux/config.h>
+
+#ifdef CONFIG_X86_PC9800
+typedef __u32 vram_char_t;
+#else
+typedef __u16 vram_char_t;
+#endif

struct vc_data;
struct console_font_op;
@@ -32,7 +39,7 @@
void (*con_init)(struct vc_data *, int);
void (*con_deinit)(struct vc_data *);
void (*con_clear)(struct vc_data *, int, int, int, int);
- void (*con_putc)(struct vc_data *, int, int, int);
+ void (*con_putc)(struct vc_data *, int, vram_char_t, int);
void (*con_putcs)(struct vc_data *, const unsigned short *, int, int, int);
void (*con_cursor)(struct vc_data *, int);
int (*con_scroll)(struct vc_data *, int, int, int, int);
@@ -49,6 +56,7 @@
void (*con_invert_region)(struct vc_data *, u16 *, int);
u16 *(*con_screen_pos)(struct vc_data *, int);
unsigned long (*con_getxy)(struct vc_data *, unsigned long, int *, int *);
+ int (*con_setterm_command)(struct vc_data *);
};

extern const struct consw *conswitchp;
@@ -56,6 +64,7 @@
extern const struct consw dummy_con; /* dummy console buffer */
extern const struct consw fb_con; /* frame buffer based console */
extern const struct consw vga_con; /* VGA text console */
+extern const struct consw gdc_con; /* PC-9800 GDC text console */
extern const struct consw newport_con; /* SGI Newport console */
extern const struct consw prom_con; /* SPARC PROM console */

diff -Nru linux/include/linux/console_struct.h linux98/include/linux/console_struct.h
--- linux/include/linux/console_struct.h 2002-12-10 11:45:40.000000000 +0900
+++ linux98/include/linux/console_struct.h 2002-12-16 13:25:55.000000000 +0900
@@ -9,6 +9,9 @@
* to achieve effects such as fast scrolling by changing the origin.
*/

+#include <linux/config.h>
+#include <linux/console.h>
+
#define NPAR 16

struct vc_data {
@@ -25,10 +28,14 @@
unsigned char vc_s_color; /* Saved foreground & background */
unsigned char vc_ulcolor; /* Color for underline mode */
unsigned char vc_halfcolor; /* Color for half intensity mode */
+ unsigned char vc_def_attr; /* Default attributes */
+ unsigned char vc_ul_attr; /* Attribute for underline mode */
+ unsigned char vc_half_attr; /* Attribute for half intensity mode */
+ unsigned char vc_bold_attr; /* Attribute for bold mode */
unsigned short vc_complement_mask; /* [#] Xor mask for mouse pointer */
unsigned short vc_hi_font_mask; /* [#] Attribute set for upper 256 chars of font or 0 if not supported */
struct console_font_op vc_font; /* Current VC font set */
- unsigned short vc_video_erase_char; /* Background erase character */
+ vram_char_t vc_video_erase_char; /* Background erase character */
unsigned short vc_s_complement_mask; /* Saved mouse pointer mask */
unsigned int vc_x, vc_y; /* Cursor position */
unsigned int vc_top, vc_bottom; /* Scrolling region */
@@ -106,6 +113,10 @@
#define CUR_HWMASK 0x0f
#define CUR_SWMASK 0xfff0

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

#define CON_IS_VISIBLE(conp) (*conp->vc_display_fg == conp)
diff -Nru linux/include/linux/tty.h linux98/include/linux/tty.h
--- linux/include/linux/tty.h Sat Oct 19 13:01:54 2002
+++ linux98/include/linux/tty.h Mon Oct 21 14:22:18 2002
@@ -123,6 +123,10 @@

#define VIDEO_TYPE_PMAC 0x60 /* PowerMacintosh frame buffer. */

+#define VIDEO_TYPE_98NORMAL 0xa4 /* NEC PC-9800 normal */
+#define VIDEO_TYPE_9840 0xa5 /* NEC PC-9800 normal 40 lines */
+#define VIDEO_TYPE_98HIRESO 0xa6 /* NEC PC-9800 hireso */
+
/*
* This character is the same as _POSIX_VDISABLE: it cannot be used as
* a c_cc[] character, but indicates that a particular special character
diff -Nru linux/include/linux/vt.h linux98/include/linux/vt.h
--- linux/include/linux/vt.h Sat Oct 19 13:02:30 2002
+++ linux98/include/linux/vt.h Mon Oct 21 14:26:03 2002
@@ -50,5 +50,6 @@
#define VT_RESIZEX 0x560A /* set kernel's idea of screensize + more */
#define VT_LOCKSWITCH 0x560B /* disallow vt switching */
#define VT_UNLOCKSWITCH 0x560C /* allow vt switching */
+#define VT_GDC_RESIZE 0x5698

#endif /* _LINUX_VT_H */
diff -Nru linux/include/linux/vt_buffer.h linux98/include/linux/vt_buffer.h
--- linux/include/linux/vt_buffer.h Sat Oct 19 13:02:24 2002
+++ linux98/include/linux/vt_buffer.h Mon Oct 21 14:28:40 2002
@@ -19,6 +19,10 @@
#include <asm/vga.h>
#endif

+#ifdef CONFIG_GDC_CONSOLE
+#include <asm/gdc.h>
+#endif
+
#ifndef VT_BUF_HAVE_RW
#define scr_writew(val, addr) (*(addr) = (val))
#define scr_readw(addr) (*(addr))

2003-03-21 02:34:58

by Osamu Tomita

[permalink] [raw]
Subject: [PATCH 2.5.65-ac1] Support PC-9800 subarchitecture (4/14) DMA

This is the patch to support NEC PC-9800 subarchitecture
against 2.5.65-ac1. (4/14)

DMA support for PC98.
For fix differences of IO port assign and memory addressing.
PC98 has 'page register' to expand DMA accesible address.

I re-wrote this patch by another way. Please comment.

Regards,
Osamu Tomita

diff -Nru linux/include/asm-i386/dma.h linux98/include/asm-i386/dma.h
--- linux/include/asm-i386/dma.h 2003-03-05 12:29:19.000000000 +0900
+++ linux98/include/asm-i386/dma.h 2003-03-17 15:24:26.000000000 +0900
@@ -1,298 +1,10 @@
-/* $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_DMA_H
#define _ASM_DMA_H

-#include <linux/config.h>
-#include <linux/spinlock.h> /* And spinlocks */
-#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 8
-
-/* The maximum address that we can perform a DMA transfer to on this platform */
-#define MAX_DMA_ADDRESS (PAGE_OFFSET+0x1000000)
-
-/* 8237 DMA controllers */
-#define IO_DMA1_BASE 0x00 /* 8 bit slave DMA, channels 0..3 */
-#define IO_DMA2_BASE 0xC0 /* 16 bit master DMA, ch 4(=slave input)..7 */
-
-/* DMA controller registers */
-#define DMA1_CMD_REG 0x08 /* command register (w) */
-#define DMA1_STAT_REG 0x08 /* status register (r) */
-#define DMA1_REQ_REG 0x09 /* request register (w) */
-#define DMA1_MASK_REG 0x0A /* single-channel mask (w) */
-#define DMA1_MODE_REG 0x0B /* mode register (w) */
-#define DMA1_CLEAR_FF_REG 0x0C /* clear pointer flip-flop (w) */
-#define DMA1_TEMP_REG 0x0D /* Temporary Register (r) */
-#define DMA1_RESET_REG 0x0D /* Master Clear (w) */
-#define DMA1_CLR_MASK_REG 0x0E /* Clear Mask */
-#define DMA1_MASK_ALL_REG 0x0F /* all-channels mask (w) */
-
-#define DMA2_CMD_REG 0xD0 /* command register (w) */
-#define DMA2_STAT_REG 0xD0 /* status register (r) */
-#define DMA2_REQ_REG 0xD2 /* request register (w) */
-#define DMA2_MASK_REG 0xD4 /* single-channel mask (w) */
-#define DMA2_MODE_REG 0xD6 /* mode register (w) */
-#define DMA2_CLEAR_FF_REG 0xD8 /* clear pointer flip-flop (w) */
-#define DMA2_TEMP_REG 0xDA /* Temporary Register (r) */
-#define DMA2_RESET_REG 0xDA /* Master Clear (w) */
-#define DMA2_CLR_MASK_REG 0xDC /* Clear Mask */
-#define DMA2_MASK_ALL_REG 0xDE /* all-channels mask (w) */
-
-#define DMA_ADDR_0 0x00 /* DMA address registers */
-#define DMA_ADDR_1 0x02
-#define DMA_ADDR_2 0x04
-#define DMA_ADDR_3 0x06
-#define DMA_ADDR_4 0xC0
-#define DMA_ADDR_5 0xC4
-#define DMA_ADDR_6 0xC8
-#define DMA_ADDR_7 0xCC
-
-#define DMA_CNT_0 0x01 /* DMA count registers */
-#define DMA_CNT_1 0x03
-#define DMA_CNT_2 0x05
-#define DMA_CNT_3 0x07
-#define DMA_CNT_4 0xC2
-#define DMA_CNT_5 0xC6
-#define DMA_CNT_6 0xCA
-#define DMA_CNT_7 0xCE
-
-#define DMA_PAGE_0 0x87 /* DMA page registers */
-#define DMA_PAGE_1 0x83
-#define DMA_PAGE_2 0x81
-#define DMA_PAGE_3 0x82
-#define DMA_PAGE_5 0x8B
-#define DMA_PAGE_6 0x89
-#define DMA_PAGE_7 0x8A
-
-#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_MODE_CASCADE 0xC0 /* pass thru DREQ->HRQ, DACK<-HLDA only */
-
-#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)
-{
- if (dmanr<=3)
- dma_outb(dmanr, DMA1_MASK_REG);
- else
- dma_outb(dmanr & 3, DMA2_MASK_REG);
-}
-
-static __inline__ void disable_dma(unsigned int dmanr)
-{
- if (dmanr<=3)
- dma_outb(dmanr | 4, DMA1_MASK_REG);
- else
- dma_outb((dmanr & 3) | 4, DMA2_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)
-{
- if (dmanr<=3)
- dma_outb(0, DMA1_CLEAR_FF_REG);
- else
- dma_outb(0, DMA2_CLEAR_FF_REG);
-}
-
-/* set mode (above) for a specific DMA channel */
-static __inline__ void set_dma_mode(unsigned int dmanr, char mode)
-{
- if (dmanr<=3)
- dma_outb(mode | dmanr, DMA1_MODE_REG);
- else
- dma_outb(mode | (dmanr&3), DMA2_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, char pagenr)
-{
- switch(dmanr) {
- case 0:
- dma_outb(pagenr, DMA_PAGE_0);
- break;
- case 1:
- dma_outb(pagenr, DMA_PAGE_1);
- break;
- case 2:
- dma_outb(pagenr, DMA_PAGE_2);
- break;
- case 3:
- dma_outb(pagenr, DMA_PAGE_3);
- break;
- case 5:
- dma_outb(pagenr & 0xfe, DMA_PAGE_5);
- break;
- case 6:
- dma_outb(pagenr & 0xfe, DMA_PAGE_6);
- break;
- case 7:
- dma_outb(pagenr & 0xfe, DMA_PAGE_7);
- 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);
- if (dmanr <= 3) {
- dma_outb( a & 0xff, ((dmanr&3)<<1) + IO_DMA1_BASE );
- dma_outb( (a>>8) & 0xff, ((dmanr&3)<<1) + IO_DMA1_BASE );
- } else {
- dma_outb( (a>>1) & 0xff, ((dmanr&3)<<2) + IO_DMA2_BASE );
- dma_outb( (a>>9) & 0xff, ((dmanr&3)<<2) + IO_DMA2_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--;
- if (dmanr <= 3) {
- dma_outb( count & 0xff, ((dmanr&3)<<1) + 1 + IO_DMA1_BASE );
- dma_outb( (count>>8) & 0xff, ((dmanr&3)<<1) + 1 + IO_DMA1_BASE );
- } else {
- dma_outb( (count>>1) & 0xff, ((dmanr&3)<<2) + 2 + IO_DMA2_BASE );
- dma_outb( (count>>9) & 0xff, ((dmanr&3)<<2) + 2 + IO_DMA2_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)
-{
- unsigned int io_port = (dmanr<=3)? ((dmanr&3)<<1) + 1 + IO_DMA1_BASE
- : ((dmanr&3)<<2) + 2 + IO_DMA2_BASE;
-
- /* using short to get 16-bit wrap around */
- unsigned short count;
-
- count = 1 + dma_inb(io_port);
- count += dma_inb(io_port) << 8;
-
- return (dmanr<=3)? count : (count<<1);
-}
-
-
-/* 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;
+#ifdef CONFIG_X86_PC9800
+#include <asm-i386/mach-pc9800/mach_dma.h>
#else
-#define isa_dma_bridge_buggy (0)
+#include <asm-i386/mach-default/mach_dma.h>
#endif

#endif /* _ASM_DMA_H */
diff -Nru linux/include/asm-i386/mach-default/mach_dma.h linux98/include/asm-i386/mach-default/mach_dma.h
--- linux/include/asm-i386/mach-default/mach_dma.h 1970-01-01 09:00:00.000000000 +0900
+++ linux98/include/asm-i386/mach-default/mach_dma.h 2003-03-17 15:28:32.000000000 +0900
@@ -0,0 +1,298 @@
+/* $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_MACH_DMA_H
+#define _ASM_MACH_DMA_H
+
+#include <linux/config.h>
+#include <linux/spinlock.h> /* And spinlocks */
+#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 8
+
+/* The maximum address that we can perform a DMA transfer to on this platform */
+#define MAX_DMA_ADDRESS (PAGE_OFFSET+0x1000000)
+
+/* 8237 DMA controllers */
+#define IO_DMA1_BASE 0x00 /* 8 bit slave DMA, channels 0..3 */
+#define IO_DMA2_BASE 0xC0 /* 16 bit master DMA, ch 4(=slave input)..7 */
+
+/* DMA controller registers */
+#define DMA1_CMD_REG 0x08 /* command register (w) */
+#define DMA1_STAT_REG 0x08 /* status register (r) */
+#define DMA1_REQ_REG 0x09 /* request register (w) */
+#define DMA1_MASK_REG 0x0A /* single-channel mask (w) */
+#define DMA1_MODE_REG 0x0B /* mode register (w) */
+#define DMA1_CLEAR_FF_REG 0x0C /* clear pointer flip-flop (w) */
+#define DMA1_TEMP_REG 0x0D /* Temporary Register (r) */
+#define DMA1_RESET_REG 0x0D /* Master Clear (w) */
+#define DMA1_CLR_MASK_REG 0x0E /* Clear Mask */
+#define DMA1_MASK_ALL_REG 0x0F /* all-channels mask (w) */
+
+#define DMA2_CMD_REG 0xD0 /* command register (w) */
+#define DMA2_STAT_REG 0xD0 /* status register (r) */
+#define DMA2_REQ_REG 0xD2 /* request register (w) */
+#define DMA2_MASK_REG 0xD4 /* single-channel mask (w) */
+#define DMA2_MODE_REG 0xD6 /* mode register (w) */
+#define DMA2_CLEAR_FF_REG 0xD8 /* clear pointer flip-flop (w) */
+#define DMA2_TEMP_REG 0xDA /* Temporary Register (r) */
+#define DMA2_RESET_REG 0xDA /* Master Clear (w) */
+#define DMA2_CLR_MASK_REG 0xDC /* Clear Mask */
+#define DMA2_MASK_ALL_REG 0xDE /* all-channels mask (w) */
+
+#define DMA_ADDR_0 0x00 /* DMA address registers */
+#define DMA_ADDR_1 0x02
+#define DMA_ADDR_2 0x04
+#define DMA_ADDR_3 0x06
+#define DMA_ADDR_4 0xC0
+#define DMA_ADDR_5 0xC4
+#define DMA_ADDR_6 0xC8
+#define DMA_ADDR_7 0xCC
+
+#define DMA_CNT_0 0x01 /* DMA count registers */
+#define DMA_CNT_1 0x03
+#define DMA_CNT_2 0x05
+#define DMA_CNT_3 0x07
+#define DMA_CNT_4 0xC2
+#define DMA_CNT_5 0xC6
+#define DMA_CNT_6 0xCA
+#define DMA_CNT_7 0xCE
+
+#define DMA_PAGE_0 0x87 /* DMA page registers */
+#define DMA_PAGE_1 0x83
+#define DMA_PAGE_2 0x81
+#define DMA_PAGE_3 0x82
+#define DMA_PAGE_5 0x8B
+#define DMA_PAGE_6 0x89
+#define DMA_PAGE_7 0x8A
+
+#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_MODE_CASCADE 0xC0 /* pass thru DREQ->HRQ, DACK<-HLDA only */
+
+#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)
+{
+ if (dmanr<=3)
+ dma_outb(dmanr, DMA1_MASK_REG);
+ else
+ dma_outb(dmanr & 3, DMA2_MASK_REG);
+}
+
+static __inline__ void disable_dma(unsigned int dmanr)
+{
+ if (dmanr<=3)
+ dma_outb(dmanr | 4, DMA1_MASK_REG);
+ else
+ dma_outb((dmanr & 3) | 4, DMA2_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)
+{
+ if (dmanr<=3)
+ dma_outb(0, DMA1_CLEAR_FF_REG);
+ else
+ dma_outb(0, DMA2_CLEAR_FF_REG);
+}
+
+/* set mode (above) for a specific DMA channel */
+static __inline__ void set_dma_mode(unsigned int dmanr, char mode)
+{
+ if (dmanr<=3)
+ dma_outb(mode | dmanr, DMA1_MODE_REG);
+ else
+ dma_outb(mode | (dmanr&3), DMA2_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, char pagenr)
+{
+ switch(dmanr) {
+ case 0:
+ dma_outb(pagenr, DMA_PAGE_0);
+ break;
+ case 1:
+ dma_outb(pagenr, DMA_PAGE_1);
+ break;
+ case 2:
+ dma_outb(pagenr, DMA_PAGE_2);
+ break;
+ case 3:
+ dma_outb(pagenr, DMA_PAGE_3);
+ break;
+ case 5:
+ dma_outb(pagenr & 0xfe, DMA_PAGE_5);
+ break;
+ case 6:
+ dma_outb(pagenr & 0xfe, DMA_PAGE_6);
+ break;
+ case 7:
+ dma_outb(pagenr & 0xfe, DMA_PAGE_7);
+ 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);
+ if (dmanr <= 3) {
+ dma_outb( a & 0xff, ((dmanr&3)<<1) + IO_DMA1_BASE );
+ dma_outb( (a>>8) & 0xff, ((dmanr&3)<<1) + IO_DMA1_BASE );
+ } else {
+ dma_outb( (a>>1) & 0xff, ((dmanr&3)<<2) + IO_DMA2_BASE );
+ dma_outb( (a>>9) & 0xff, ((dmanr&3)<<2) + IO_DMA2_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--;
+ if (dmanr <= 3) {
+ dma_outb( count & 0xff, ((dmanr&3)<<1) + 1 + IO_DMA1_BASE );
+ dma_outb( (count>>8) & 0xff, ((dmanr&3)<<1) + 1 + IO_DMA1_BASE );
+ } else {
+ dma_outb( (count>>1) & 0xff, ((dmanr&3)<<2) + 2 + IO_DMA2_BASE );
+ dma_outb( (count>>9) & 0xff, ((dmanr&3)<<2) + 2 + IO_DMA2_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)
+{
+ unsigned int io_port = (dmanr<=3)? ((dmanr&3)<<1) + 1 + IO_DMA1_BASE
+ : ((dmanr&3)<<2) + 2 + IO_DMA2_BASE;
+
+ /* using short to get 16-bit wrap around */
+ unsigned short count;
+
+ count = 1 + dma_inb(io_port);
+ count += dma_inb(io_port) << 8;
+
+ return (dmanr<=3)? count : (count<<1);
+}
+
+
+/* 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_MACH_DMA_H */
diff -Nru linux/include/asm-i386/mach-pc9800/mach_dma.h linux98/include/asm-i386/mach-pc9800/mach_dma.h
--- linux/include/asm-i386/mach-pc9800/mach_dma.h 1970-01-01 09:00:00.000000000 +0900
+++ linux98/include/asm-i386/mach-pc9800/mach_dma.h 2003-03-17 16:28:14.000000000 +0900
@@ -0,0 +1,258 @@
+/* $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.
+ *
+ * Modified for PC-9800 sub architecture by Osamu Tomita <[email protected]>
+ */
+
+#ifndef _ASM_MACH_DMA_H
+#define _ASM_MACH_DMA_H
+
+#include <linux/config.h>
+#include <linux/spinlock.h> /* And spinlocks */
+#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 01-1F
+ *
+ * - ALL registers are 8 bits only, regardless of transfer size
+ * - channels 0-3 are byte - addresses/counts are for physical bytes
+ * - transfers must not cross physical 64K (0-3) boundaries
+ * - transfer count loaded to registers is 1 less than actual count
+ * - page registers for 0-3 use bit 0, represent 64K pages
+ *
+ * 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:
+ *
+ * A31 ... A24 A23 ... A16 A15 ... A8 A7 ... A0 (Physical addresses)
+ * | ... | | ... | | ... | | ... |
+ * | ... | | ... | | ... | | ... |
+ * | ... | | ... | | ... | | ... |
+ * P7 ... P0 P7 ... P0 A7 ... A0 A7 ... A0
+ * | Ex Page | Page | Addr MSB | Addr LSB | (DMA registers)
+ *
+ * Transfer count (_not # bytes_) is limited to 64K, represented as actual
+ * count - 1 : 64K => 0xFFFF, 1 => 0x0000. Thus, count is always 1 or more.
+ *
+ */
+
+#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_DMA1_BASE 0x01 /* 8 bit DMA, channels 0..3 */
+#define IO_DMA2_BASE 0x00 /* none */
+
+/* DMA controller registers */
+#define DMA1_CMD_REG 0x11 /* command register (w) */
+#define DMA1_STAT_REG 0x11 /* status register (r) */
+#define DMA1_REQ_REG 0x13 /* request register (w) */
+#define DMA1_MASK_REG 0x15 /* single-channel mask (w) */
+#define DMA1_MODE_REG 0x17 /* mode register (w) */
+#define DMA1_CLEAR_FF_REG 0x19 /* clear pointer flip-flop (w) */
+#define DMA1_TEMP_REG 0x1B /* Temporary Register (r) */
+#define DMA1_RESET_REG 0x1B /* Master Clear (w) */
+#define DMA1_CLR_MASK_REG 0x1D /* Clear Mask */
+#define DMA1_MASK_ALL_REG 0x1F /* all-channels mask (w) */
+
+#define DMA2_CMD_REG 0x00 /* none */
+#define DMA2_STAT_REG 0x00 /* none */
+#define DMA2_REQ_REG 0x00 /* none */
+#define DMA2_MASK_REG 0x00 /* none */
+#define DMA2_MODE_REG 0x00 /* none */
+#define DMA2_CLEAR_FF_REG 0x00 /* none */
+#define DMA2_TEMP_REG 0x00 /* none */
+#define DMA2_RESET_REG 0x00 /* none */
+#define DMA2_CLR_MASK_REG 0x00 /* none */
+#define DMA2_MASK_ALL_REG 0x00 /* none */
+
+#define DMA_ADDR_0 0x01 /* DMA address registers */
+#define DMA_ADDR_1 0x05
+#define DMA_ADDR_2 0x09
+#define DMA_ADDR_3 0x0D
+#define DMA_ADDR_4 0x00 /* none */
+#define DMA_ADDR_5 0x00 /* none */
+#define DMA_ADDR_6 0x00 /* none */
+#define DMA_ADDR_7 0x00 /* none */
+
+#define DMA_CNT_0 0x03 /* DMA count registers */
+#define DMA_CNT_1 0x07
+#define DMA_CNT_2 0x0B
+#define DMA_CNT_3 0x0F
+#define DMA_CNT_4 0x00 /* none */
+#define DMA_CNT_5 0x00 /* none */
+#define DMA_CNT_6 0x00 /* none */
+#define DMA_CNT_7 0x00 /* none */
+
+#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_PAGE_5 0x00 /* none */
+#define DMA_PAGE_6 0x00 /* none */
+#define DMA_PAGE_7 0x00 /* none */
+
+#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_MODE_CASCADE 0x00 /* none */
+
+#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, DMA1_MASK_REG);
+}
+
+static __inline__ void disable_dma(unsigned int dmanr)
+{
+ dma_outb(dmanr | 4, DMA1_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, DMA1_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, DMA1_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_DMA1_BASE );
+ dma_outb( (a>>8) & 0xff, ((dmanr&3)<<2) + IO_DMA1_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_DMA1_BASE );
+ dma_outb( (count>>8) & 0xff, ((dmanr&3)<<2) + 2 + IO_DMA1_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_DMA1_BASE);
+ count += dma_inb(((dmanr&3)<<2) + 2 + IO_DMA1_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_MACH_DMA_H */
diff -Nru linux/include/asm-i386/scatterlist.h linux98/include/asm-i386/scatterlist.h
--- linux/include/asm-i386/scatterlist.h 2002-04-15 04:18:52.000000000 +0900
+++ linux98/include/asm-i386/scatterlist.h 2002-04-17 10:37:22.000000000 +0900
@@ -1,6 +1,8 @@
#ifndef _I386_SCATTERLIST_H
#define _I386_SCATTERLIST_H

+#include <linux/config.h>
+
struct scatterlist {
struct page *page;
unsigned int offset;
@@ -8,6 +10,10 @@
unsigned int length;
};

+#ifdef CONFIG_X86_PC9800
+#define ISA_DMA_THRESHOLD (0xffffffff)
+#else
#define ISA_DMA_THRESHOLD (0x00ffffff)
+#endif

#endif /* !(_I386_SCATTERLIST_H) */
diff -Nru linux/kernel/dma.c linux98/kernel/dma.c
--- linux/kernel/dma.c 2002-08-11 10:41:22.000000000 +0900
+++ linux98/kernel/dma.c 2002-08-21 09:53:59.000000000 +0900
@@ -9,6 +9,7 @@
* [It also happened to remove the sizeof(char *) == sizeof(int)
* assumption introduced because of those /proc/dma patches. -- Hennus]
*/
+#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
@@ -62,10 +63,12 @@
{ 0, 0 },
{ 0, 0 },
{ 0, 0 },
+#ifndef CONFIG_X86_PC9800
{ 1, "cascade" },
{ 0, 0 },
{ 0, 0 },
{ 0, 0 }
+#endif
};


2003-03-21 02:31:42

by Osamu Tomita

[permalink] [raw]
Subject: [PATCH 2.5.65-ac1] Support PC-9800 subarchitecture (3/14) misc core

This is the patch to support NEC PC-9800 subarchitecture
against 2.5.65-ac1. (3/14)

Small patches for PC98 core support.
io.h: Using ioport 0x5f to wait is recomended by vendor.
irq.h: Cascade IRQ is 7 for PC98 not 2.
pc98*.h: Add macros to access BIOS parameters.
kernel.h: define "pc98" for other files.
I think these are small and clean.

Regards,
Osamu Tomita

diff -Nru linux/include/asm-i386/io.h linux98/include/asm-i386/io.h
--- linux/include/asm-i386/io.h 2002-10-12 13:22:45.000000000 +0900
+++ linux98/include/asm-i386/io.h 2002-10-12 19:25:19.000000000 +0900
@@ -27,6 +27,8 @@
* Linus
*/

+#include <linux/config.h>
+
/*
* Bit simplified and optimized by Jan Hubicka
* Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999.
@@ -288,7 +290,11 @@
#ifdef SLOW_IO_BY_JUMPING
#define __SLOW_DOWN_IO "jmp 1f; 1: jmp 1f; 1:"
#else
+#ifdef CONFIG_X86_PC9800
+#define __SLOW_DOWN_IO "outb %%al,$0x5f;"
+#else
#define __SLOW_DOWN_IO "outb %%al,$0x80;"
+#endif
#endif

static inline void slow_down_io(void) {
diff -Nru linux/include/asm-i386/irq.h linux98/include/asm-i386/irq.h
--- linux/include/asm-i386/irq.h 2002-09-21 00:20:16.000000000 +0900
+++ linux98/include/asm-i386/irq.h 2002-09-21 07:17:56.000000000 +0900
@@ -17,7 +17,11 @@

static __inline__ int irq_cannonicalize(int irq)
{
+#ifdef CONFIG_X86_PC9800
+ return ((irq == 7) ? 11 : irq);
+#else
return ((irq == 2) ? 9 : irq);
+#endif
}

extern void disable_irq(unsigned int);
diff -Nru linux/include/asm-i386/pc9800.h linux98/include/asm-i386/pc9800.h
--- linux/include/asm-i386/pc9800.h 1970-01-01 09:00:00.000000000 +0900
+++ linux98/include/asm-i386/pc9800.h 2002-08-17 21:50:18.000000000 +0900
@@ -0,0 +1,27 @@
+/*
+ * PC-9800 machine types.
+ *
+ * Copyright (C) 1999 TAKAI Kosuke <[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-2.5.65/include/linux/kernel.h linux98-2.5.65/include/linux/kernel.h
--- linux-2.5.65/include/linux/kernel.h 2003-03-18 06:43:37.000000000 +0900
+++ linux98-2.5.65/include/linux/kernel.h 2003-03-20 10:21:22.000000000 +0900
@@ -235,4 +235,10 @@
#define __FUNCTION__ (__func__)
#endif

+#ifdef CONFIG_X86_PC9800
+#define pc98 1
+#else
+#define pc98 0
+#endif
+
#endif

2003-03-21 02:42:34

by Osamu Tomita

[permalink] [raw]
Subject: [PATCH 2.5.65-ac1] Support PC-9800 subarchitecture (8/14) kconfig

This is the patch to support NEC PC-9800 subarchitecture
against 2.5.65-ac1. (8/14)

Add selection CONFIG_X86_PC9800.

Regards,
Osamu Tomita

diff -Nru linux-2.5.64-ac4/arch/i386/Kconfig linux98-2.5.64-ac4/arch/i386/Kconfig
--- linux-2.5.64-ac4/arch/i386/Kconfig 2003-03-15 01:15:40.000000000 +0900
+++ linux98-2.5.64-ac4/arch/i386/Kconfig 2003-03-15 01:59:17.000000000 +0900
@@ -104,6 +104,12 @@
A kernel compiled for the Visual Workstation will not run on PCs
and vice versa. See <file:Documentation/sgi-visws.txt> for details.

+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.
+
endchoice


@@ -1081,7 +1087,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.
@@ -1099,7 +1105,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

2003-03-21 02:47:29

by Osamu Tomita

[permalink] [raw]
Subject: [PATCH 2.5.65-ac1] Support PC-9800 subarchitecture (10/14) parport

This is the patch to support NEC PC-9800 subarchitecture
against 2.5.65-ac1. (10/14)

Parallel port support.
- Change IO port and IRQ assign.
- Add probing for PC98 parport.

I make this patch simplify by limiting usage bi-directioal only.
Since lp_old98 supports output only parpose.

Regards,
Osamu Tomita

diff -Nru linux-2.5.64-ac2/drivers/parport/parport_pc.c linux98-2.5.64-ac2/drivers/parport/parport_pc.c
--- linux-2.5.64-ac2/drivers/parport/parport_pc.c 2003-03-08 08:25:20.000000000 +0900
+++ linux98-2.5.64-ac2/drivers/parport/parport_pc.c 2003-03-08 10:44:43.000000000 +0900
@@ -1892,6 +1892,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);
@@ -2032,6 +2035,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);
@@ -2248,7 +2254,7 @@
parport_ECR_present(p);
}

- if (base != 0x3bc) {
+ if (!pc98 && base != 0x3bc) {
EPP_res = request_region(base+0x3, 5, fake_name);
if (EPP_res)
if (!parport_EPP_supported(p))
@@ -3022,6 +3028,26 @@
{
int count = 0;

+ if (pc98) {
+ /* Set default settings for IEEE1284 parport */
+ int base = 0x140;
+ int base_hi = 0x14c;
+ int irq = 14;
+ 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 ? */
+ 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))

2003-03-21 02:53:01

by Osamu Tomita

[permalink] [raw]
Subject: [PATCH 2.5.65-ac1] Support PC-9800 subarchitecture (13/14) SCSI

This is the patch to support NEC PC-9800 subarchitecture
against 2.5.65-ac1. (13/14)

SCSI host adapter support.
- BIOS parameter change for PC98.
- Add pc980155 driver for old PC98.
- wd33c93.c update error handler for eh_*.
- wd33c93.h register to int for PIO mode.

Regards,
Osamu Tomita

diff -Nru linux-2.5.64/drivers/scsi/Kconfig linux98-2.5.64/drivers/scsi/Kconfig
--- linux-2.5.64/drivers/scsi/Kconfig 2003-03-05 13:18:53.000000000 +0900
+++ linux98-2.5.64/drivers/scsi/Kconfig 2003-03-05 15:34:46.000000000 +0900
@@ -1715,6 +1715,11 @@
If you have the NEC PC-9801-55 SCSI interface card or compatibles
for NEC PC-9801/PC-9821, say Y.

+config WD33C93_PIO
+ bool
+ depends on SCSI_PC980155
+ default 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-2.5.64/drivers/scsi/Makefile linux98-2.5.64/drivers/scsi/Makefile
--- linux-2.5.64/drivers/scsi/Makefile 2003-03-05 13:18:54.000000000 +0900
+++ linux98-2.5.64/drivers/scsi/Makefile 2003-03-05 13:40:14.000000000 +0900
@@ -29,6 +29,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
diff -Nru linux-2.5.64/drivers/scsi/pc980155.c linux98-2.5.64/drivers/scsi/pc980155.c
--- linux-2.5.64/drivers/scsi/pc980155.c 1970-01-01 09:00:00.000000000 +0900
+++ linux98-2.5.64/drivers/scsi/pc980155.c 2003-03-13 14:31:08.000000000 +0900
@@ -0,0 +1,299 @@
+/*
+ *
+ * drivers/scsi/pc980155.c
+ *
+ * PC-9801-55 SCSI host adapter driver
+ *
+ * Copyright (C) 1997-2003 Kyoto University Microcomputer Club
+ * (Linux/98 project)
+ * Tomoharu Ugawa <[email protected]>
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/blk.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+
+#include <asm/dma.h>
+
+#include "scsi.h"
+#include "hosts.h"
+#include "wd33c93.h"
+#include "pc980155.h"
+
+extern int pc98_bios_param(struct scsi_device *, struct block_device *,
+ sector_t, int *);
+static int scsi_pc980155_detect(Scsi_Host_Template *);
+static int scsi_pc980155_release(struct Scsi_Host *);
+
+#ifndef CMD_PER_LUN
+#define CMD_PER_LUN 2
+#endif
+
+#ifndef CAN_QUEUE
+#define CAN_QUEUE 16
+#endif
+
+#undef PC_9801_55_DEBUG
+#undef PC_9801_55_DEBUG_VERBOSE
+
+#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 wd33c93_regs init_regs;
+static int io;
+
+static struct Scsi_Host *pc980155_host = NULL;
+
+static void pc980155_intr_handle(int irq, void *dev_id, struct pt_regs *regp);
+
+static inline void pc980155_dma_enable(unsigned int base_io)
+{
+ outb(0x01, REG_CWRITE);
+}
+
+static inline void pc980155_dma_disable(unsigned int base_io)
+{
+ outb(0x02, REG_CWRITE);
+}
+
+
+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->device->host->dma_channel);
+ set_dma_mode(sc->device->host->dma_channel,
+ 0x40 | (dir_in ? 0x04 : 0x08));
+ clear_dma_ff(sc->device->host->dma_channel);
+ set_dma_addr(sc->device->host->dma_channel, virt_to_phys(sc->SCp.ptr));
+ set_dma_count(sc->device->host->dma_channel, sc->SCp.this_residual);
+#ifdef PC_9801_55_DEBUG
+ printk("D%d(%x)D", sc->device->host->dma_channel,
+ sc->SCp.this_residual);
+#endif
+ enable_dma(sc->device->host->dma_channel);
+ pc980155_dma_enable(sc->device->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->device->host->io_port);
+ disable_dma(sc->device->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 (inb(regs.SASR) == 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_pc980155_resetint(regs);
+ 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);
+ *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 PC_9801_55_DEBUG
+ printk("PC-9801-55: end of getconfig\n");
+#endif
+ return 1;
+}
+
+/* return non-zero on detection */
+static int scsi_pc980155_detect(Scsi_Host_Template* tpnt)
+{
+ unsigned int base_io;
+ unsigned char irq, dma, scsi_id;
+ int i;
+#ifdef PC_9801_55_DEBUG
+ unsigned char debug;
+#endif
+
+ if (io) {
+ base_ios[0] = io;
+ nr_base_ios = 1;
+ }
+
+ for (i = 0; i < nr_base_ios; i++) {
+ base_io = base_ios[i];
+ init_regs.SASR = REG_ADDRST;
+ init_regs.SCMD = REG_CONTRL;
+#ifdef PC_9801_55_DEBUG
+ printk("PC-9801-55: SASR(%x = %x)\n", SASR, REG_ADDRST);
+#endif
+ if (!request_region(base_io, 6, "PC-9801-55"))
+ continue;
+
+ if (pc980155_test_port(init_regs) &&
+ pc980155_getconfig(base_io, init_regs,
+ &irq, &dma, &scsi_id))
+ goto found;
+
+ release_region(base_io, 6);
+ }
+
+ printk("PC-9801-55: not found\n");
+ return 0;
+
+ found:
+#ifdef PC_9801_55_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);
+ goto err1;
+ }
+
+ if (request_dma(dma, "PC-9801-55")) {
+ printk(KERN_ERR "PC-9801-55: unable to allocate DMA channel %d\n", dma);
+ goto err2;
+ }
+
+ pc980155_host = scsi_register(tpnt, sizeof(struct WD33C93_hostdata));
+ if (pc980155_host) {
+ 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;
+ printk("PC-9801-55: scsi host found at %x irq = %d, use dma channel %d.\n", base_io, irq, dma);
+ pc980155_int_enable(init_regs);
+ wd33c93_init(pc980155_host, init_regs, dma_setup, dma_stop,
+ WD33C93_FS_12_15);
+ return 1;
+ }
+
+ printk(KERN_ERR "PC-9801-55: failed to register device\n");
+
+err2:
+ free_irq(irq, NULL);
+err1:
+ release_region(base_io, 6);
+ return 0;
+}
+
+static int scsi_pc980155_release(struct Scsi_Host *shost)
+{
+ struct WD33C93_hostdata *hostdata
+ = (struct WD33C93_hostdata *)shost->hostdata;
+
+ pc980155_int_disable(hostdata->regs);
+ release_region(shost->io_port, shost->n_io_port);
+ free_irq(shost->irq, NULL);
+ free_dma(shost->dma_channel);
+ wd33c93_release();
+ return 1;
+}
+
+static int pc980155_bus_reset(Scsi_Cmnd *cmd)
+{
+ struct WD33C93_hostdata *hostdata
+ = (struct WD33C93_hostdata *)cmd->device->host->hostdata;
+
+ pc980155_int_disable(hostdata->regs);
+ pc980155_assert_bus_reset(hostdata->regs);
+ udelay(50);
+ pc980155_negate_bus_reset(hostdata->regs);
+ (void) inb(hostdata->regs.SASR);
+ (void) read_pc980155(hostdata->regs, WD_SCSI_STATUS);
+ pc980155_int_enable(hostdata->regs);
+ wd33c93_host_reset(cmd);
+ return SUCCESS;
+}
+
+
+#ifndef MODULE
+static int __init pc980155_setup(char *str)
+{
+ int ints[4];
+
+ str = get_options(str, ARRAY_SIZE(ints), ints);
+ if (ints[0] > 0)
+ io = ints[1];
+ return 1;
+}
+__setup("pc980155_io=", pc980155_setup);
+#endif
+
+MODULE_PARM(io, "i");
+MODULE_AUTHOR("Tomoharu Ugawa <[email protected]>");
+MODULE_DESCRIPTION("PC-9801-55 SCSI host adapter driver");
+MODULE_LICENSE("GPL");
+
+static Scsi_Host_Template driver_template = {
+ .proc_info = wd33c93_proc_info,
+ .name = "SCSI PC-9801-55",
+ .detect = scsi_pc980155_detect,
+ .release = scsi_pc980155_release,
+ .queuecommand = wd33c93_queuecommand,
+ .eh_abort_handler = wd33c93_abort,
+ .eh_bus_reset_handler = pc980155_bus_reset,
+ .eh_host_reset_handler = wd33c93_host_reset,
+ .bios_param = pc98_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,
+ .proc_name = "PC_9801_55",
+};
+
+#include "scsi_module.c"
diff -Nru linux-2.5.64/drivers/scsi/pc980155.h linux98-2.5.64/drivers/scsi/pc980155.h
--- linux-2.5.64/drivers/scsi/pc980155.h 1970-01-01 09:00:00.000000000 +0900
+++ linux98-2.5.64/drivers/scsi/pc980155.h 2003-03-13 13:48:15.000000000 +0900
@@ -0,0 +1,52 @@
+/*
+ *
+ * drivers/scsi/pc980155.h
+ *
+ * PC-9801-55 SCSI host adapter driver
+ *
+ * Copyright (C) 1997-2003 Kyoto University Microcomputer Club
+ * (Linux/98 project)
+ * Tomoharu Ugawa <[email protected]>
+ *
+ */
+
+#ifndef __PC980155_H
+#define __PC980155_H
+
+#include "wd33c93.h"
+
+#define REG_ADDRST (base_io)
+#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
+
+static inline uchar read_pc980155(const wd33c93_regs regs, uchar reg_num)
+{
+ outb(reg_num, regs.SASR);
+ return (uchar)inb(regs.SCMD);
+}
+
+static inline void write_memorybank(const wd33c93_regs regs, uchar value)
+{
+ outb(WD_MEMORYBANK, regs.SASR);
+ outb(value, regs.SCMD);
+}
+
+#define read_pc980155_resetint(regs) \
+ read_pc980155((regs), WD_RESETINT)
+#define pc980155_int_enable(regs) \
+ write_memorybank((regs), read_pc980155((regs), WD_MEMORYBANK) | 0x04)
+
+#define pc980155_int_disable(regs) \
+ write_memorybank((regs), read_pc980155((regs), WD_MEMORYBANK) & ~0x04)
+
+#define pc980155_assert_bus_reset(regs) \
+ write_memorybank((regs), read_pc980155((regs), WD_MEMORYBANK) | 0x02)
+
+#define pc980155_negate_bus_reset(regs) \
+ write_memorybank((regs), read_pc980155((regs), WD_MEMORYBANK) & ~0x02)
+
+#endif /* __PC980155_H */
diff -Nru linux/drivers/scsi/scsi_pc98.c linux98/drivers/scsi/scsi_pc98.c
--- linux/drivers/scsi/scsi_pc98.c 2003-03-05 13:18:57.000000000 +0900
+++ linux98/drivers/scsi/scsi_pc98.c 2003-03-05 13:49:21.000000000 +0900
@@ -48,7 +48,7 @@
int pc98_bios_param(struct scsi_device *sdev, struct block_device *bdev,
sector_t capacity, int *ip)
{
- static struct Scsi_Host *first_real = first_real_host();
+ struct Scsi_Host *first_real = first_real_host();

if (sdev->host == first_real && sdev->id < 7 &&
__PC9800SCA_TEST_BIT(PC9800SCA_DISK_EQUIPS, sdev->id))
diff -Nru linux-2.5.65/drivers/scsi/sd.c linux98-2.5.65/drivers/scsi/sd.c
--- linux-2.5.65/drivers/scsi/sd.c 2003-03-18 06:44:22.000000000 +0900
+++ linux98-2.5.65/drivers/scsi/sd.c 2003-03-20 11:50:17.000000000 +0900
@@ -488,6 +488,15 @@
else
scsicam_bios_param(bdev, sdkp->capacity, diskinfo);

+#ifdef CONFIG_X86_PC9800
+ {
+ extern int pc98_bios_param(struct scsi_device *,
+ struct block_device *,
+ sector_t, int *);
+ pc98_bios_param(sdp, bdev, sdkp->capacity, diskinfo);
+ }
+#endif
+
if (put_user(diskinfo[0], &loc->heads))
return -EFAULT;
if (put_user(diskinfo[1], &loc->sectors))
diff -Nru linux/drivers/scsi/wd33c93.c linux98/drivers/scsi/wd33c93.c
--- linux/drivers/scsi/wd33c93.c 2003-03-05 12:29:31.000000000 +0900
+++ linux98/drivers/scsi/wd33c93.c 2003-03-13 14:38:57.000000000 +0900
@@ -162,8 +162,8 @@
{
uchar data;

- outb(reg_num, *regs.SASR);
- data = inb(*regs.SCMD);
+ outb(reg_num, regs.SASR);
+ data = inb(regs.SCMD);
return data;
}

@@ -172,33 +172,33 @@
{
unsigned long value;

- outb(WD_TRANSFER_COUNT_MSB, *regs.SASR);
- value = inb(*regs.SCMD) << 16;
- value |= inb(*regs.SCMD) << 8;
- value |= inb(*regs.SCMD);
+ 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 uchar
read_aux_stat(const wd33c93_regs regs)
{
- return inb(*regs.SASR);
+ return inb(regs.SASR);
}

static inline void
write_wd33c93(const wd33c93_regs regs, uchar reg_num, uchar value)
{
- outb(reg_num, *regs.SASR);
- outb(value, *regs.SCMD);
+ outb(reg_num, regs.SASR);
+ outb(value, regs.SCMD);
}

static inline void
write_wd33c93_count(const wd33c93_regs regs, unsigned long value)
{
- outb(WD_TRANSFER_COUNT_MSB, *regs.SASR);
- outb((value >> 16) & 0xff, *regs.SCMD);
- outb((value >> 8) & 0xff, *regs.SCMD);
- outb( value & 0xff, *regs.SCMD);
+ outb(WD_TRANSFER_COUNT_MSB, regs.SASR);
+ outb((value >> 16) & 0xff, regs.SCMD);
+ outb((value >> 8) & 0xff, regs.SCMD);
+ outb( value & 0xff, regs.SCMD);
}

#define write_wd33c93_cmd(regs, cmd) \
@@ -209,9 +209,9 @@
{
int i;

- outb(WD_CDB_1, *regs.SASR);
+ outb(WD_CDB_1, regs.SASR);
for (i=0; i<len; i++)
- outb(cmnd[i], *regs.SCMD);
+ outb(cmnd[i], regs.SCMD);
}

#else /* CONFIG_WD33C93_PIO */
@@ -1522,7 +1522,7 @@
}

int
-wd33c93_reset(Scsi_Cmnd * SCpnt, unsigned int reset_flags)
+wd33c93_host_reset(Scsi_Cmnd * SCpnt)
{
struct Scsi_Host *instance;
struct WD33C93_hostdata *hostdata;
@@ -1553,7 +1553,7 @@
reset_wd33c93(instance);
SCpnt->result = DID_RESET << 16;
enable_irq(instance->irq);
- return 0;
+ return SUCCESS;
}

int
@@ -1591,7 +1591,7 @@
instance->host_no, cmd->pid);
enable_irq(cmd->device->host->irq);
cmd->scsi_done(cmd);
- return SCSI_ABORT_SUCCESS;
+ return SUCCESS;
}
prev = tmp;
tmp = (Scsi_Cmnd *) tmp->host_scribble;
@@ -1666,7 +1666,7 @@

enable_irq(cmd->device->host->irq);
cmd->scsi_done(cmd);
- return SCSI_ABORT_SUCCESS;
+ return SUCCESS;
}

/*
@@ -1681,9 +1681,9 @@
printk
("scsi%d: Abort - command %ld found on disconnected_Q - ",
instance->host_no, cmd->pid);
- printk("returning ABORT_SNOOZE. ");
+ printk("Abort SNOOZE. ");
enable_irq(cmd->device->host->irq);
- return SCSI_ABORT_SNOOZE;
+ return FAILED;
}
tmp = (Scsi_Cmnd *) tmp->host_scribble;
}
@@ -1704,7 +1704,7 @@
enable_irq(cmd->device->host->irq);
printk("scsi%d: warning : SCSI command probably completed successfully"
" before abortion. ", instance->host_no);
- return SCSI_ABORT_NOT_RUNNING;
+ return FAILED;
}

#define MAX_WD33C93_HOSTS 4
@@ -1755,7 +1755,7 @@

return 1;
}
-__setup("wd33c9=", wd33c93_setup);
+__setup("wd33c93=", wd33c93_setup);

/* check_setup_args() returns index if key found, 0 if not
*/
@@ -2080,9 +2080,10 @@
{
}

-EXPORT_SYMBOL(wd33c93_reset);
+EXPORT_SYMBOL(wd33c93_host_reset);
EXPORT_SYMBOL(wd33c93_init);
EXPORT_SYMBOL(wd33c93_release);
EXPORT_SYMBOL(wd33c93_abort);
EXPORT_SYMBOL(wd33c93_queuecommand);
EXPORT_SYMBOL(wd33c93_intr);
+EXPORT_SYMBOL(wd33c93_proc_info);
diff -Nru linux/drivers/scsi/wd33c93.h linux98/drivers/scsi/wd33c93.h
--- linux/drivers/scsi/wd33c93.h 2003-03-05 12:29:03.000000000 +0900
+++ linux98/drivers/scsi/wd33c93.h 2003-03-13 14:38:15.000000000 +0900
@@ -186,8 +186,13 @@

/* This is what the 3393 chip looks like to us */
typedef struct {
+#ifdef CONFIG_WD33C93_PIO
+ unsigned int SASR;
+ unsigned int SCMD;
+#else
volatile unsigned char *SASR;
volatile unsigned char *SCMD;
+#endif
} wd33c93_regs;


@@ -334,7 +339,7 @@
int wd33c93_queuecommand (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *));
void wd33c93_intr (struct Scsi_Host *instance);
int wd33c93_proc_info(char *, char **, off_t, int, int, int);
-int wd33c93_reset (Scsi_Cmnd *, unsigned int);
+int wd33c93_host_reset (Scsi_Cmnd *);
void wd33c93_release(void);

#endif /* WD33C93_H */

2003-03-21 02:49:00

by Osamu Tomita

[permalink] [raw]
Subject: [PATCH 2.5.65-ac1] Support PC-9800 subarchitecture (11/14) PCI

This is the patch to support NEC PC-9800 subarchitecture
against 2.5.65-ac1. (11/14)

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

Regards,
Osamu Tomita

diff -Nru linux/arch/i386/pci/irq.c linux98/arch/i386/pci/irq.c
--- linux/arch/i386/pci/irq.c 2002-10-12 13:22:46.000000000 +0900
+++ linux98/arch/i386/pci/irq.c 2002-10-12 14:18:52.000000000 +0900
@@ -5,6 +5,7 @@
*/

#include <linux/config.h>
+#include <linux/pci_ids.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/pci.h>
@@ -25,6 +26,7 @@

static struct irq_routing_table *pirq_table;

+#ifndef CONFIG_X86_PC9800
/*
* Never use: 0, 1, 2 (timer, keyboard, and cascade)
* Avoid using: 13, 14 and 15 (FP error and IDE).
@@ -36,6 +38,20 @@
1000000, 1000000, 1000000, 1000, 1000, 0, 1000, 1000,
0, 0, 0, 0, 1000, 100000, 100000, 100000
};
+#else
+/*
+ * Never use: 0, 1, 2, 7 (timer, keyboard, CRT VSYNC and cascade)
+ * Avoid using: 8, 9 and 15 (FP error and IDE).
+ * Penalize: 4, 5, 11, 12, 13, 14 (known ISA uses: serial, floppy, sound, mouse
+ * and parallel)
+ */
+unsigned int pcibios_irq_mask = 0xff78;
+
+static int pirq_penalty[16] = {
+ 1000000, 1000000, 1000000, 0, 1000, 1000, 0, 1000000,
+ 100000, 100000, 0, 1000, 1000, 1000, 1000, 100000
+};
+#endif

struct irq_router {
char *name;
@@ -612,6 +628,17 @@
r->set(pirq_router_dev, dev, pirq, 11);
}

+#ifdef CONFIG_X86_PC9800
+ if ((dev->class >> 8) == PCI_CLASS_BRIDGE_CARDBUS) {
+ if (pci_find_device(PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_INTEL_82439TX, NULL) != NULL) {
+ if (mask & 0x0040) {
+ mask &= 0x0040; /* assign IRQ 6 only */
+ printk("pci-irq: Use IRQ6 for CardBus controller\n");
+ }
+ }
+ }
+#endif
/*
* Find the best IRQ to assign: use the one
* reported by the device if possible.
diff -Nru linux/drivers/pcmcia/yenta.c linux98/drivers/pcmcia/yenta.c
--- linux/drivers/pcmcia/yenta.c 2002-11-18 13:29:48.000000000 +0900
+++ linux98/drivers/pcmcia/yenta.c 2002-11-19 11:02:09.000000000 +0900
@@ -8,6 +8,7 @@
* Dynamically adjust the size of the bridge resource
*
*/
+#include <linux/config.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/sched.h>
@@ -510,6 +511,7 @@
add_timer(&socket->poll_timer);
}

+#ifndef CONFIG_X86_PC9800
/*
* Only probe "regular" interrupts, don't
* touch dangerous spots like the mouse irq,
@@ -520,6 +522,10 @@
* Default to 11, 10, 9, 7, 6, 5, 4, 3.
*/
static u32 isa_interrupts = 0x0ef8;
+#else
+/* Default to 12, 10, 6, 5, 3. */
+static u32 isa_interrupts = 0x1468;
+#endif

static unsigned int yenta_probe_irq(pci_socket_t *socket, u32 isa_irq_mask)
{
diff -Nru linux/include/asm-i386/pci.h linux98/include/asm-i386/pci.h
--- linux/include/asm-i386/pci.h 2002-06-09 14:29:24.000000000 +0900
+++ linux98/include/asm-i386/pci.h 2002-06-10 20:49:15.000000000 +0900
@@ -17,7 +17,11 @@
#endif

extern unsigned long pci_mem_start;
+#ifdef CONFIG_X86_PC9800
+#define PCIBIOS_MIN_IO 0x4000
+#else
#define PCIBIOS_MIN_IO 0x1000
+#endif
#define PCIBIOS_MIN_MEM (pci_mem_start)

void pcibios_config_init(void);

2003-03-21 02:50:18

by Osamu Tomita

[permalink] [raw]
Subject: [PATCH 2.5.65-ac1] Support PC-9800 subarchitecture (12/14) PCMCIA

This is the patch to support NEC PC-9800 subarchitecture
against 2.5.65-ac1. (12/14)

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

Regards,
Osamu Tomita

diff -Nru linux-2.5.62-ac1/drivers/pcmcia/i82365.c linux98-2.5.62-ac1/drivers/pcmcia/i82365.c
--- linux-2.5.62-ac1/drivers/pcmcia/i82365.c 2003-02-18 07:56:55.000000000 +0900
+++ linux98-2.5.62-ac1/drivers/pcmcia/i82365.c 2003-02-21 11:14:30.000000000 +0900
@@ -188,7 +188,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-03-21 02:40:19

by Osamu Tomita

[permalink] [raw]
Subject: [PATCH 2.5.65-ac1] Support PC-9800 subarchitecture (7/14) kanji

This is the patch to support NEC PC-9800 subarchitecture
against 2.5.65-ac1. (7/14)

Add japanese kanji character support to PC98 console.

Regards,
Osamu Tomita

diff -Nru linux/drivers/char/console_macros.h linux98/drivers/char/console_macros.h
--- linux/drivers/char/console_macros.h 2003-03-18 11:12:28.000000000 +0900
+++ linux98/drivers/char/console_macros.h 2003-03-18 13:18:49.000000000 +0900
@@ -68,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/vt.c linux98/drivers/char/vt.c
--- linux/drivers/char/vt.c 2003-03-18 11:12:28.000000000 +0900
+++ linux98/drivers/char/vt.c 2003-03-18 13:18:49.000000000 +0900
@@ -155,6 +155,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);
@@ -439,6 +443,25 @@
do_update_region(currcons, (unsigned long) p, count);
}

+#ifdef CONFIG_KANJI
+/* can called form keyboard.c */
+void do_change_kanji_mode(int currcons, unsigned long mode)
+{
+ switch (mode) {
+ case 0:
+ kanji_mode = EUC_CODE;
+ break;
+ case 1:
+ kanji_mode = JIS_CODE;
+ break;
+ case 2:
+ kanji_mode = SJIS_CODE;
+ break;
+ }
+ kanji_char1 = 0;
+}
+#endif /* CONFIG_KANJI */
+
/* used by selection: complement pointer position */
void complement_pos(int currcons, int offset)
{
@@ -1102,6 +1125,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;
@@ -1110,6 +1136,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;
@@ -1118,6 +1147,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;
@@ -1331,6 +1363,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 */
}
}

@@ -1408,8 +1456,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()) */
@@ -1419,9 +1485,18 @@
bottom = video_num_lines;
vc_state = ESnormal;
ques = 0;
+#ifdef CONFIG_KANJI
+ translate = set_translate(JP_MAP, currcons);
+ translate_ex = 0;
+ G0_charset = JP_MAP;
+ G0_charset_ex = 0;
+ G1_charset = GRAF_MAP;
+ G1_charset_ex = 0;
+#else
translate = set_translate(LAT1_MAP,currcons);
G0_charset = LAT1_MAP;
G1_charset = GRAF_MAP;
+#endif
charset = 0;
need_wrap = 0;
report_mouse = 0;
@@ -1463,6 +1538,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)
@@ -1505,11 +1586,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:
@@ -1566,6 +1653,11 @@
case ')':
vc_state = ESsetG1;
return;
+#ifdef CONFIG_KANJI
+ case '$':
+ vc_state = ESsetJIS;
+ return;
+#endif
case '#':
vc_state = EShash;
return;
@@ -1815,8 +1907,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:
@@ -1828,10 +1937,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;
}
@@ -1863,7 +2013,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;
@@ -1920,48 +2070,151 @@
hide_cursor(currcons);

while (!tty->stopped && count) {
+ int realkanji = 0;
+ int kanjioverrun = 0;
c = *buf;
buf++;
n++;
count--;

- if (utf) {
- /* Combine UTF-8 into Unicode */
- /* Incomplete characters silently ignored */
- if(c > 0x7f) {
- if (utf_count > 0 && (c & 0xc0) == 0x80) {
- utf_char = (utf_char << 6) | (c & 0x3f);
- utf_count--;
- if (utf_count == 0)
- tc = c = utf_char;
- else continue;
- } else {
- if ((c & 0xe0) == 0xc0) {
- utf_count = 1;
- utf_char = (c & 0x1f);
- } else if ((c & 0xf0) == 0xe0) {
- utf_count = 2;
- utf_char = (c & 0x0f);
- } else if ((c & 0xf8) == 0xf0) {
- utf_count = 3;
- utf_char = (c & 0x07);
- } else if ((c & 0xfc) == 0xf8) {
- utf_count = 4;
- utf_char = (c & 0x03);
- } else if ((c & 0xfe) == 0xfc) {
- utf_count = 5;
- utf_char = (c & 0x01);
- } else
- utf_count = 0;
- continue;
- }
- } else {
- tc = c;
- utf_count = 0;
- }
- } else { /* no utf */
- tc = translate[toggle_meta ? (c|0x80) : c];
- }
+#ifdef CONFIG_KANJI
+ if (vc_state == ESnormal && !disp_ctrl) {
+ switch (kanji_jis_mode) {
+ case JIS_CODE_78:
+ case JIS_CODE_83:
+ case JIS_CODE_90:
+ if (utf)
+ break;
+ if (c >= 127 || c <= 0x20) {
+ kanji_char1 = 0;
+ break;
+ }
+ if (kanji_char1) {
+ tc = (((unsigned int)kanji_char1) << 8) |
+ (((unsigned int)c) & 0x007f);
+ kanji_char1 = 0;
+ realkanji = 1;
+ } else {
+ kanji_char1 = ((unsigned int)c) & 0x007f;
+ continue;
+ }
+ break;
+ case JIS_CODE_ASCII:
+ default:
+ switch (kanji_mode) {
+ case SJIS_CODE:
+ if (kanji_char1) {
+ if ((0x40 <= c && c <= 0x7E) ||
+ (0x80 <= c && c <= 0xFC)) {
+ realkanji = 1;
+ /* SJIS to JIS */
+ kanji_char1 <<= 1; /* 81H-9FH --> 22H-3EH */
+ /* EOH-EFH --> C0H-DEH */
+ c -= 0x1f; /* 40H-7EH --> 21H-5FH */
+ /* 80H-9EH --> 61H-7FH */
+ /* 9FH-FCH --> 80H-DDH */
+ if (!(c & 0x80)) {
+ if (c < 0x61)
+ c++;
+ c += 0xde;
+ }
+ c &= 0xff;
+ c += 0xa1;
+ kanji_char1 += 0x1f;
+ tc = (kanji_char1 << 8) + c;
+ tc &= 0x7f7f;
+ kanji_char1 = 0;
+ }
+ } else {
+ if ((0x81 <= c && c <= 0x9f) ||
+ (0xE0 <= c && c <= 0xEF)) {
+ realkanji = 1;
+ kanji_char1 = c;
+ continue;
+ } else if (0xA1 <= c && c <= 0xDF) {
+ tc = (unsigned int)translations[JP_MAP][c];
+ goto hankana_skip;
+ }
+ }
+ break;
+ case EUC_CODE:
+ if (utf)
+ break;
+ if (c <= 0x7f) {
+ kanji_char1 = 0;
+ break;
+ }
+ if (kanji_char1) {
+ if (kanji_char1 == 0x8e) { /* SS2 */
+ /* realkanji ha tatenai */
+ tc = (unsigned int)translations[JP_MAP][c];
+ kanji_char1 = 0;
+ goto hankana_skip;
+ } else {
+ tc = (((unsigned int)kanji_char1) << 8) |
+ (((unsigned int)c) & 0x007f);
+ kanji_char1 = 0;
+ realkanji = 1;
+ }
+ } else {
+ kanji_char1 = (unsigned int)c;
+ continue;
+ }
+ break;
+ case JIS_CODE:
+ /* to be supported */
+ break;
+ } /* switch (kanji_mode) */
+ } /* switch (kanji_jis_mode) */
+ } /* if (vc_state == ESnormal) */
+
+#endif /* CONFIG_KANJI */
+ if (!realkanji) {
+ if (utf) {
+ /* Combine UTF-8 into Unicode */
+ /* Incomplete characters silently ignored */
+ if(c > 0x7f) {
+ if (utf_count > 0 && (c & 0xc0) == 0x80) {
+ utf_char = (utf_char << 6) | (c & 0x3f);
+ utf_count--;
+ if (utf_count == 0)
+ tc = c = utf_char;
+ else continue;
+ } else {
+ if ((c & 0xe0) == 0xc0) {
+ utf_count = 1;
+ utf_char = (c & 0x1f);
+ } else if ((c & 0xf0) == 0xe0) {
+ utf_count = 2;
+ utf_char = (c & 0x0f);
+ } else if ((c & 0xf8) == 0xf0) {
+ utf_count = 3;
+ utf_char = (c & 0x07);
+ } else if ((c & 0xfc) == 0xf8) {
+ utf_count = 4;
+ utf_char = (c & 0x03);
+ } else if ((c & 0xfe) == 0xfc) {
+ utf_count = 5;
+ utf_char = (c & 0x01);
+ } else
+ utf_count = 0;
+ continue;
+ }
+ } else {
+ tc = c;
+ utf_count = 0;
+ }
+ } else { /* no utf */
+#ifdef CONFIG_KANJI
+ tc = translate[(toggle_meta || translate_ex) ? (c | 0x80) : c];
+#else
+ tc = translate[toggle_meta ? (c|0x80) : c];
+#endif
+ }
+ } /* if (!realkanji) */
+#ifdef CONFIG_KANJI
+ hankana_skip:
+#endif

/* If the original code was a control character we
* only allow a glyph to be displayed if the code is
@@ -1978,43 +2231,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;
@@ -2022,6 +2303,16 @@
x++;
draw_to = (pos+=2);
}
+#else /* CONFIG_KANJI */
+ if (x >= video_num_columns - 1) {
+ need_wrap = decawm;
+ kanjioverrun = x - video_num_columns + 1;
+ draw_to = pos + 2;
+ } else {
+ x++;
+ draw_to = (pos += 2);
+ }
+#endif /* !CONFIG_KANJI */
continue;
}
FLUSH
diff -Nru linux-2.5.65/drivers/video/console/Kconfig linux98-2.5.65/drivers/video/console/Kconfig
--- linux-2.5.65/drivers/video/console/Kconfig 2003-03-18 11:12:28.000000000 +0900
+++ linux98-2.5.65/drivers/video/console/Kconfig 2003-03-18 13:18:49.000000000 +0900
@@ -233,5 +233,9 @@
bool "Mini 4x6 font"
depends on !SPARC32 && !SPARC64 && FONTS

+config KANJI
+ bool "Japanese Kanji support"
+ depends on X86_PC9800
+
endmenu

diff -Nru linux/include/linux/console_struct.h linux98/include/linux/console_struct.h
--- linux/include/linux/console_struct.h 2003-03-18 11:12:28.000000000 +0900
+++ linux98/include/linux/console_struct.h 2003-03-18 13:18:49.000000000 +0900
@@ -90,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 */
};

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;

2003-03-21 02:44:42

by Osamu Tomita

[permalink] [raw]
Subject: [PATCH 2.5.65-ac1] Support PC-9800 subarchitecture (9/14) NIC

This is the patch to support NEC PC-9800 subarchitecture
against 2.5.65-ac1. (9/14)

C-bus(PC98's legacy bus like ISA) network cards support.
Change IO port and IRQ assign.
Add NE2000 compatible driver for PC-9800.
PCI netwwork card works fine without patch.

Regards,
Osamu Tomita

diff -Nru linux-2.5.64/drivers/net/3c509.c linux98-2.5.64/drivers/net/3c509.c
--- linux-2.5.64/drivers/net/3c509.c 2003-03-05 11:22:46.000000000 +0900
+++ linux98-2.5.64/drivers/net/3c509.c 2003-03-05 11:45:08.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"
@@ -257,7 +261,7 @@
};
#endif /* CONFIG_MCA */

-#ifdef __ISAPNP__
+#if defined(__ISAPNP__) && !defined(CONFIG_X86_PC9800)
static struct isapnp_device_id el3_isapnp_adapters[] __initdata = {
{ ISAPNP_ANY_ID, ISAPNP_ANY_ID,
ISAPNP_VENDOR('T', 'C', 'M'), ISAPNP_FUNCTION(0x5090),
@@ -350,7 +354,7 @@
if (lp->pmdev)
pm_unregister(lp->pmdev);
#endif
-#ifdef __ISAPNP__
+#if defined(__ISAPNP__) && !defined(CONFIG_X86_PC9800)
if (lp->type == EL3_PNP)
pnp_device_detach(to_pnp_dev(lp->dev));
#endif
@@ -368,12 +372,12 @@
int ioaddr, irq, if_port;
u16 phys_addr[3];
static int current_tag;
-#ifdef __ISAPNP__
+#if defined(__ISAPNP__) && !defined(CONFIG_X86_PC9800)
static int pnp_cards;
struct pnp_dev *idev = NULL;
#endif /* __ISAPNP__ */

-#ifdef __ISAPNP__
+#if defined(__ISAPNP__) && !defined(CONFIG_X86_PC9800)
if (nopnp == 1)
goto no_pnp;

@@ -421,6 +425,9 @@
no_pnp:
#endif /* __ISAPNP__ */

+#ifdef CONFIG_X86_PC9800
+ id_port = 0x71d0;
+#else
/* Select an open I/O location at 0x1*0 to do contention select. */
for ( ; id_port < 0x200; id_port += 0x10) {
if (check_region(id_port, 1))
@@ -435,6 +442,7 @@
printk(" WARNING: No I/O port available for 3c509 activation.\n");
return -ENODEV;
}
+#endif /* CONFIG_X86_PC9800 */
/* Next check for all ISA bus boards by sending the ID sequence to the
ID_PORT. We find cards past the first by setting the 'current_tag'
on cards as they are found. Cards with their tag set will not
@@ -465,7 +473,7 @@
phys_addr[i] = htons(id_read_eeprom(i));
}

-#ifdef __ISAPNP__
+#if defined(__ISAPNP__) && !defined(CONFIG_X86_PC9800)
if (nopnp == 0) {
/* The ISA PnP 3c509 cards respond to the ID sequence.
This check is needed in order not to register them twice. */
@@ -490,9 +498,19 @@
{
unsigned int iobase = id_read_eeprom(8);
if_port = iobase >> 14;
+#ifdef CONFIG_X86_PC9800
+ ioaddr = 0x40d0 + ((iobase & 0x1f) << 8);
+#else
ioaddr = 0x200 + ((iobase & 0x1f) << 4);
+#endif
}
irq = id_read_eeprom(9) >> 12;
+#ifdef CONFIG_X86_PC9800
+ if (irq == 7)
+ irq = 6;
+ else if (irq == 15)
+ irq = 13;
+#endif

if (!(dev = init_etherdev(NULL, sizeof(struct el3_private))))
return -ENOMEM;
@@ -522,7 +540,11 @@
outb(0xd0 + ++current_tag, id_port);

/* Activate the adaptor at the EEPROM location. */
+#ifdef CONFIG_X86_PC9800
+ outb((ioaddr >> 8) | 0xe0, id_port);
+#else
outb((ioaddr >> 4) | 0xe0, id_port);
+#endif

EL3WINDOW(0);
if (inw(ioaddr) != 0x6d50) {
@@ -534,7 +556,7 @@
/* Free the interrupt so that some other card can use it. */
outw(0x0f00, ioaddr + WN0_IRQ);

-#ifdef __ISAPNP__
+#if defined(__ISAPNP__) && !defined(CONFIG_X86_PC9800)
found: /* PNP jumps here... */
#endif /* __ISAPNP__ */

@@ -543,7 +565,7 @@
dev->irq = irq;
dev->if_port = if_port;
lp = dev->priv;
-#ifdef __ISAPNP__
+#if defined(__ISAPNP__) && !defined(CONFIG_X86_PC9800)
lp->dev = &idev->dev;
#endif

@@ -1388,6 +1410,12 @@
outw(0x0001, ioaddr + 4);

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

/* Set the station address in window 2 each time opened. */
@@ -1550,7 +1578,7 @@
MODULE_PARM_DESC(irq, "IRQ number(s) (assigned)");
MODULE_PARM_DESC(xcvr,"transceiver(s) (0=internal, 1=external)");
MODULE_PARM_DESC(max_interrupt_work, "maximum events handled per interrupt");
-#ifdef __ISAPNP__
+#if defined(__ISAPNP__) && !defined(CONFIG_X86_PC9800)
MODULE_PARM(nopnp, "i");
MODULE_PARM_DESC(nopnp, "disable ISA PnP support (0-1)");
MODULE_DEVICE_TABLE(isapnp, el3_isapnp_adapters);
diff -Nru linux-2.5.42/drivers/net/8390.h linux98-2.5.42/drivers/net/8390.h
--- linux-2.5.42/drivers/net/8390.h 2002-10-12 13:22:14.000000000 +0900
+++ linux98-2.5.42/drivers/net/8390.h 2002-10-15 23:03:22.000000000 +0900
@@ -123,7 +123,8 @@
#define inb_p(port) in_8(port)
#define outb_p(val,port) out_8(port,val)

-#elif defined(CONFIG_ARM_ETHERH) || defined(CONFIG_ARM_ETHERH_MODULE)
+#elif defined(CONFIG_ARM_ETHERH) || defined(CONFIG_ARM_ETHERH_MODULE) || \
+ defined(CONFIG_NET_CBUS)
#define EI_SHIFT(x) (ei_local->reg_offset[x])
#else
#define EI_SHIFT(x) (x)
diff -Nru linux-2.5.62-ac1/drivers/net/Kconfig linux98-2.5.62-ac1/drivers/net/Kconfig
--- linux-2.5.62-ac1/drivers/net/Kconfig 2003-02-18 07:56:53.000000000 +0900
+++ linux98-2.5.62-ac1/drivers/net/Kconfig 2003-02-21 11:07:56.000000000 +0900
@@ -663,7 +663,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
@@ -932,7 +932,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
@@ -978,7 +978,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
@@ -1176,6 +1176,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.64/drivers/net/Makefile linux98-2.5.64/drivers/net/Makefile
--- linux-2.5.64/drivers/net/Makefile 2003-03-05 12:29:04.000000000 +0900
+++ linux98-2.5.64/drivers/net/Makefile 2003-03-13 17:06:03.000000000 +0900
@@ -81,6 +81,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) += ne2k_cbus.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.64-ac1/drivers/net/Space.c linux98-2.5.64-ac1/drivers/net/Space.c
--- linux-2.5.64-ac1/drivers/net/Space.c 2003-03-07 08:52:03.000000000 +0900
+++ linux98-2.5.64-ac1/drivers/net/Space.c 2003-03-07 13:30:51.000000000 +0900
@@ -229,7 +229,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.64/drivers/net/at1700.c linux98-2.5.64/drivers/net/at1700.c
--- linux-2.5.64/drivers/net/at1700.c 2003-03-05 12:29:16.000000000 +0900
+++ linux98-2.5.64/drivers/net/at1700.c 2003-03-15 12:54:58.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)
@@ -844,24 +920,28 @@
outb(0x02, ioaddr + RX_MODE); /* Use normal mode. */
}

- save_flags(flags);
- cli();
+ spin_lock_irqsave (&lp->lock, flags);
if (memcmp(mc_filter, lp->mc_filter, sizeof(mc_filter))) {
int saved_bank = inw(ioaddr + CONFIG_0);
/* 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);
}
- restore_flags(flags);
+ spin_unlock_irqrestore (&lp->lock, flags);
return;
}

#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 +981,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/drivers/net/ne2k_cbus.c linux98/drivers/net/ne2k_cbus.c
--- linux/drivers/net/ne2k_cbus.c 1970-01-01 09:00:00.000000000 +0900
+++ linux98/drivers/net/ne2k_cbus.c 2003-03-15 12:37:35.000000000 +0900
@@ -0,0 +1,879 @@
+/* ne.c: A general non-shared-memory NS8390 ethernet driver for linux. */
+/*
+ Written 1992-94 by Donald Becker.
+
+ Copyright 1993 United States Government as represented by the
+ Director, National Security Agency.
+
+ This software may be used and distributed according to the terms
+ of the GNU General Public License, incorporated herein by reference.
+
+ The author may be reached as [email protected], or C/O
+ Scyld Computing Corporation, 410 Severn Ave., Suite 210, Annapolis MD 21403
+
+ This driver should work with many programmed-I/O 8390-based ethernet
+ boards. Currently it supports the NE1000, NE2000, many clones,
+ and some Cabletron products.
+
+ Changelog:
+
+ Paul Gortmaker : use ENISR_RDC to monitor Tx PIO uploads, made
+ sanity checks and bad clone support optional.
+ Paul Gortmaker : new reset code, reset card after probe at boot.
+ Paul Gortmaker : multiple card support for module users.
+ Paul Gortmaker : Support for PCI ne2k clones, similar to lance.c
+ Paul Gortmaker : Allow users with bad cards to avoid full probe.
+ Paul Gortmaker : PCI probe changes, more PCI cards supported.
+ [email protected] : Changed init order so an interrupt will only
+ occur after memory is allocated for dev->priv. Deallocated memory
+ last in cleanup_modue()
+ Richard Guenther : Added support for ISAPnP cards
+ Paul Gortmaker : Discontinued PCI support - use ne2k-pci.c instead.
+ Osamu Tomita : Separate driver for NEC PC-9800.
+
+*/
+
+/* Routines for the NatSemi-based designs (NE[12]000). */
+
+static const char version1[] =
+"ne.c:v1.10 9/23/94 Donald Becker ([email protected])\n";
+static const char version2[] =
+"Last modified Nov 1, 2000 by Paul Gortmaker\n";
+
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/isapnp.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+
+#include "8390.h"
+
+/* Some defines that people can play with if so inclined. */
+
+/* Do we support clones that don't adhere to 14,15 of the SAprom ? */
+#define SUPPORT_NE_BAD_CLONES
+
+/* Do we perform extra sanity checks on stuff ? */
+/* #define NE_SANITY_CHECK */
+
+/* Do we implement the read before write bugfix ? */
+/* #define NE_RW_BUGFIX */
+
+/* Do we have a non std. amount of memory? (in units of 256 byte pages) */
+/* #define PACKETBUF_MEMSIZE 0x40 */
+
+#ifdef SUPPORT_NE_BAD_CLONES
+/* A list of bad clones that we none-the-less recognize. */
+static struct { const char *name8, *name16; unsigned char SAprefix[4];}
+bad_clone_list[] __initdata = {
+ {"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
+
+/* ---- No user-serviceable parts below ---- */
+
+#define NE_BASE (dev->base_addr)
+#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 */
+#define NE1SM_STOP_PG 0x40 /* Last page +1 of RX ring */
+#define NESM_START_PG 0x40 /* First page of TX buffer */
+#define NESM_STOP_PG 0x80 /* Last page +1 of RX ring */
+
+#include "ne2k_cbus.h"
+
+int ne_probe(struct net_device *dev);
+static int ne_probe1(struct net_device *dev, int ioaddr);
+static int ne_open(struct net_device *dev);
+static int ne_close(struct net_device *dev);
+
+static void ne_reset_8390(struct net_device *dev);
+static void ne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
+ int ring_page);
+static void ne_block_input(struct net_device *dev, int count,
+ struct sk_buff *skb, int ring_offset);
+static void ne_block_output(struct net_device *dev, const int count,
+ const unsigned char *buf, const int start_page);
+
+
+/* Probe for various non-shared-memory ethercards.
+
+ NEx000-clone boards have a Station Address PROM (SAPROM) in the packet
+ buffer memory space. NE2000 clones have 0x57,0x57 in bytes 0x0e,0x0f of
+ the SAPROM, while other supposed NE2000 clones must be detected by their
+ SA prefix.
+
+ Reading the SAPROM from a word-wide card with the 8390 set in byte-wide
+ mode results in doubled values, which can be detected and compensated for.
+
+ The probe is also responsible for initializing the card and filling
+ in the 'dev' and 'ei_status' structures.
+
+ We use the minimum memory size for some ethercard product lines, iff we can't
+ distinguish models. You can increase the packet buffer size by setting
+ PACKETBUF_MEMSIZE. Reported Cabletron packet buffer locations are:
+ E1010 starts at 0x100 and ends at 0x2000.
+ E1010-x starts at 0x100 and ends at 0x8000. ("-x" means "more memory")
+ E2010 starts at 0x100 and ends at 0x4000.
+ E2010-x starts at 0x100 and ends at 0xffff. */
+
+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++)
+ 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++)
+ 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;
+}
+
+static int __init ne_probe1(struct net_device *dev, int ioaddr)
+{
+ int i;
+ unsigned char SA_prom[32];
+ int wordlength = 2;
+ const char *name = NULL;
+ int start_page, stop_page;
+ int neX000, bad_card;
+ int reg0, ret;
+ static unsigned version_printed;
+ const struct ne2k_cbus_region *rlist;
+ 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);
+
+#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
+
+ for (rlist = hw->regionlist; rlist->range; rlist++)
+ if (!request_region(ioaddr + rlist->start,
+ rlist->range, dev->name)) {
+ ret = -EBUSY;
+ goto err_out;
+ }
+
+ 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 + 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 + EI_SHIFT(0x0d)); /* Restore the old values. */
+ ret = -ENODEV;
+ goto err_out;
+ }
+ }
+
+ if (ei_debug && version_printed++ == 0)
+ printk(KERN_INFO "%s" KERN_INFO "%s", version1, version2);
+
+ printk(KERN_INFO "NE*000 ethercard probe at %#3x:", ioaddr);
+
+ /* A user with a poor card that fails to ack the reset, or that
+ does not have a valid 0x57,0x57 signature can still use this
+ without having to recompile. Specifying an i/o address along
+ with an otherwise unused dev->mem_end value of "0xBAD" will
+ cause the driver to skip these parts of the probe. */
+
+ bad_card = ((dev->base_addr != 0) && (dev->mem_end == 0xbad));
+
+ /* Reset card. Who knows what dain-bramaged state it was left in. */
+
+ {
+ unsigned long reset_start_time = jiffies;
+
+ /* derived from CNET98EL-patch for bad clones */
+ outb_p(E8390_NODMA | E8390_STOP, ioaddr + E8390_CMD);
+
+ /* DON'T change these to inb_p/outb_p or reset will fail on clones. */
+ outb(inb(ioaddr + NE_RESET), ioaddr + NE_RESET);
+
+ while ((inb_p(ioaddr + EN0_ISR) & ENISR_RESET) == 0)
+ if (jiffies - reset_start_time > 2*HZ/100) {
+ if (bad_card) {
+ printk(" (warning: no reset ack)");
+ break;
+ } else {
+ printk(" not found (no reset ack).\n");
+ ret = -ENODEV;
+ goto err_out;
+ }
+ }
+
+ 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; unsigned short offset;} program_seq[] =
+ {
+ {E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD}, /* Select page 0*/
+ /* 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},
+ {0x00, EN0_RCNTLO}, /* Clear the count regs. */
+ {0x00, EN0_RCNTHI},
+ {0x00, EN0_IMR}, /* Mask completion irq. */
+ {0xFF, EN0_ISR},
+ {E8390_RXOFF, EN0_RXCR}, /* 0x20 Set to monitor */
+ {E8390_TXOFF, EN0_TXCR}, /* 0x02 and loopback mode. */
+ {32, EN0_RCNTLO},
+ {0x00, EN0_RCNTHI},
+ {0x00, EN0_RSARLO}, /* DMA starting at 0x0000. */
+ {0x00, EN0_RSARHI},
+ {E8390_RREAD+E8390_START, E8390_CMD},
+ };
+
+ for (i = 0; i < sizeof(program_seq)/sizeof(program_seq[0]); i++)
+ outb_p(program_seq[i].value, ioaddr + program_seq[i].offset);
+ insw(ioaddr + NE_DATAPORT, SA_prom, 32 >> 1);
+
+ }
+
+ if (wordlength == 2)
+ {
+ for (i = 0; i < 16; i++)
+ SA_prom[i] = SA_prom[i+i];
+ 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);
+ if (neX000) {
+ name = "C-Bus-NE2K-compat";
+ }
+ else
+ {
+#ifdef SUPPORT_NE_BAD_CLONES
+ /* Ack! Well, there might be a *bad* NE*000 clone there.
+ Check for total bogus addresses. */
+ for (i = 0; bad_clone_list[i].name8; i++)
+ {
+ if (SA_prom[0] == bad_clone_list[i].SAprefix[0] &&
+ SA_prom[1] == bad_clone_list[i].SAprefix[1] &&
+ SA_prom[2] == bad_clone_list[i].SAprefix[2])
+ {
+ if (wordlength == 2)
+ {
+ name = bad_clone_list[i].name16;
+ } else {
+ name = bad_clone_list[i].name8;
+ }
+ break;
+ }
+ }
+ if (bad_clone_list[i].name8 == NULL)
+ {
+ printk(" not found (invalid signature %2.2x %2.2x).\n",
+ SA_prom[14], SA_prom[15]);
+ ret = -ENXIO;
+ goto err_out;
+ }
+#else
+ printk(" not found.\n");
+ ret = -ENXIO;
+ goto err_out;
+#endif
+ }
+
+ if (dev->irq < 2)
+ {
+ unsigned long cookie = probe_irq_on();
+ outb_p(0x50, ioaddr + EN0_IMR); /* Enable one interrupt. */
+ outb_p(0x00, ioaddr + EN0_RCNTLO);
+ outb_p(0x00, ioaddr + EN0_RCNTHI);
+ outb_p(E8390_RREAD+E8390_START, ioaddr); /* Trigger it... */
+ mdelay(10); /* wait 10ms for interrupt to propagate */
+ outb_p(0x00, ioaddr + EN0_IMR); /* Mask it again. */
+ dev->irq = probe_irq_off(cookie);
+ if (ei_debug > 2)
+ printk(" autoirq is %d\n", dev->irq);
+ } 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;
+
+ if (! dev->irq) {
+ printk(" failed to detect IRQ line.\n");
+ ret = -EAGAIN;
+ goto err_out;
+ }
+
+ /* Allocate dev->priv and fill in 8390 specific dev fields. */
+ if (ethdev_init(dev))
+ {
+ printk (" unable to get memory for dev->priv.\n");
+ ret = -ENOMEM;
+ goto err_out;
+ }
+
+ /* Snarf the interrupt now. There's no point in waiting since we cannot
+ share and the board will usually be enabled. */
+ ret = request_irq(dev->irq, ei_interrupt, 0, name, dev);
+ if (ret) {
+ printk (" unable to get IRQ %d (errno=%d).\n", dev->irq, ret);
+ goto err_out_kfree;
+ }
+
+ dev->base_addr = ioaddr;
+
+ for(i = 0; i < ETHER_ADDR_LEN; i++) {
+ printk(" %2.2x", SA_prom[i]);
+ dev->dev_addr[i] = SA_prom[i];
+ }
+
+ 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);
+
+ ei_status.name = name;
+ ei_status.tx_start_page = start_page;
+ ei_status.stop_page = stop_page;
+ ei_status.word16 = (wordlength == 2);
+
+ ei_status.rx_start_page = start_page + TX_PAGES;
+#ifdef PACKETBUF_MEMSIZE
+ /* Allow the packet buffer size to be overridden by know-it-alls. */
+ ei_status.stop_page = ei_status.tx_start_page + PACKETBUF_MEMSIZE;
+#endif
+
+ ei_status.reset_8390 = &ne_reset_8390;
+ ei_status.block_input = &ne_block_input;
+ ei_status.block_output = &ne_block_output;
+ ei_status.get_8390_hdr = &ne_get_8390_hdr;
+ ei_status.priv = 0;
+ dev->open = &ne_open;
+ dev->stop = &ne_close;
+ NS8390_init(dev, 0);
+ return 0;
+
+err_out_kfree:
+ ne2k_cbus_destroy(dev);
+err_out:
+ while (rlist > hw->regionlist) {
+ rlist --;
+ release_region(ioaddr + rlist->start, rlist->range);
+ }
+ return ret;
+}
+
+static int ne_open(struct net_device *dev)
+{
+ ei_open(dev);
+ return 0;
+}
+
+static int ne_close(struct net_device *dev)
+{
+ if (ei_debug > 1)
+ printk(KERN_DEBUG "%s: Shutting down ethercard.\n", dev->name);
+ ei_close(dev);
+ return 0;
+}
+
+/* Hard reset the card. This used to pause for the same period that a
+ 8390 reset command required, but that shouldn't be necessary. */
+
+static void ne_reset_8390(struct net_device *dev)
+{
+ unsigned long reset_start_time = jiffies;
+ struct ei_device *ei_local = (struct ei_device *)(dev->priv);
+
+ if (ei_debug > 1)
+ printk(KERN_DEBUG "resetting the 8390 t=%ld...", jiffies);
+
+ /* derived from CNET98EL-patch for bad clones... */
+ outb_p(E8390_NODMA | E8390_STOP, NE_BASE + E8390_CMD); /* 0x20 | 0x1 */
+
+ /* 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);
+
+ ei_status.txing = 0;
+ ei_status.dmaing = 0;
+
+ /* This check _should_not_ be necessary, omit eventually. */
+ while ((inb_p(NE_BASE+EN0_ISR) & ENISR_RESET) == 0)
+ if (jiffies - reset_start_time > 2*HZ/100) {
+ printk(KERN_WARNING "%s: ne_reset_8390() did not complete.\n", dev->name);
+ break;
+ }
+ outb_p(ENISR_RESET, NE_BASE + EN0_ISR); /* Ack intr. */
+}
+
+/* Grab the 8390 specific header. Similar to the block_input routine, but
+ we don't need to be concerned with ring wrap as the header will be at
+ the start of a page, so we optimize accordingly. */
+
+static void ne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
+{
+ int nic_base = dev->base_addr;
+ struct ei_device *ei_local = (struct ei_device *)(dev->priv);
+
+ /* This *shouldn't* happen. If it does, it's the last thing you'll see */
+
+ if (ei_status.dmaing)
+ {
+ printk(KERN_EMERG "%s: DMAing conflict in ne_get_8390_hdr "
+ "[DMAstat:%d][irqlock:%d].\n",
+ dev->name, ei_status.dmaing, ei_status.irqlock);
+ return;
+ }
+
+ ei_status.dmaing |= 0x01;
+ outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
+ outb_p(sizeof(struct e8390_pkt_hdr), nic_base + EN0_RCNTLO);
+ outb_p(0, nic_base + EN0_RCNTHI);
+ outb_p(0, nic_base + EN0_RSARLO); /* On page boundary */
+ outb_p(ring_page, nic_base + EN0_RSARHI);
+ outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);
+
+ if (ei_status.word16)
+ insw(NE_BASE + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr)>>1);
+ else
+ insb(NE_BASE + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr));
+
+ outb_p(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */
+ ei_status.dmaing &= ~0x01;
+
+ le16_to_cpus(&hdr->count);
+}
+
+/* Block input and output, similar to the Crynwr packet driver. If you
+ are porting to a new ethercard, look at the packet driver source for hints.
+ The NEx000 doesn't share the on-board packet memory -- you have to put
+ the packet out through the "remote DMA" dataport using outb. */
+
+static void ne_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
+{
+#ifdef NE_SANITY_CHECK
+ int xfer_count = count;
+#endif
+ int nic_base = dev->base_addr;
+ char *buf = skb->data;
+ struct ei_device *ei_local = (struct ei_device *)(dev->priv);
+
+ /* This *shouldn't* happen. If it does, it's the last thing you'll see */
+ if (ei_status.dmaing)
+ {
+ printk(KERN_EMERG "%s: DMAing conflict in ne_block_input "
+ "[DMAstat:%d][irqlock:%d].\n",
+ dev->name, ei_status.dmaing, ei_status.irqlock);
+ return;
+ }
+ ei_status.dmaing |= 0x01;
+
+ /* round up count to a word (derived from ICM-patch) */
+ count = (count + 1) & ~1;
+
+ 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);
+ outb_p(ring_offset & 0xff, nic_base + EN0_RSARLO);
+ outb_p(ring_offset >> 8, nic_base + EN0_RSARHI);
+ outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);
+ if (ei_status.word16)
+ {
+ insw(NE_BASE + NE_DATAPORT,buf,count>>1);
+ if (count & 0x01)
+ {
+ buf[count-1] = inb(NE_BASE + NE_DATAPORT);
+#ifdef NE_SANITY_CHECK
+ xfer_count++;
+#endif
+ }
+ } else {
+ insb(NE_BASE + NE_DATAPORT, buf, count);
+ }
+
+#ifdef NE_SANITY_CHECK
+ /* This was for the ALPHA version only, but enough people have
+ been encountering problems so it is still here. If you see
+ this message you either 1) have a slightly incompatible clone
+ or 2) have noise/speed problems with your bus. */
+
+ if (ei_debug > 1)
+ {
+ /* DMA termination address check... */
+ int addr, tries = 20;
+ do {
+ /* DON'T check for 'inb_p(EN0_ISR) & ENISR_RDC' here
+ -- it's broken for Rx on some cards! */
+ int high = inb_p(nic_base + EN0_RSARHI);
+ int low = inb_p(nic_base + EN0_RSARLO);
+ addr = (high << 8) + low;
+ if (((ring_offset + xfer_count) & 0xff) == low)
+ break;
+ } while (--tries > 0);
+ if (tries <= 0)
+ printk(KERN_WARNING "%s: RX transfer address mismatch,"
+ "%#4.4x (expected) vs. %#4.4x (actual).\n",
+ dev->name, ring_offset + xfer_count, addr);
+ }
+#endif
+ outb_p(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */
+ ei_status.dmaing &= ~0x01;
+}
+
+static void ne_block_output(struct net_device *dev, int count,
+ const unsigned char *buf, const int start_page)
+{
+ int nic_base = NE_BASE;
+ unsigned long dma_start;
+#ifdef NE_SANITY_CHECK
+ int retries = 0;
+#endif
+ struct ei_device *ei_local = (struct ei_device *)(dev->priv);
+
+ /* Round the count up for word writes. Do we need to do this?
+ What effect will an odd byte count have on the 8390?
+ I should check someday. */
+
+ if (ei_status.word16 && (count & 0x01))
+ count++;
+
+ /* This *shouldn't* happen. If it does, it's the last thing you'll see */
+ if (ei_status.dmaing)
+ {
+ printk(KERN_EMERG "%s: DMAing conflict in ne_block_output."
+ "[DMAstat:%d][irqlock:%d]\n",
+ dev->name, ei_status.dmaing, ei_status.irqlock);
+ return;
+ }
+ ei_status.dmaing |= 0x01;
+ /* We should already be in page 0, but to be safe... */
+ outb_p(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base + NE_CMD);
+
+#ifdef NE_SANITY_CHECK
+retry:
+#endif
+
+#ifdef NE8390_RW_BUGFIX
+ /* Handle the read-before-write bug the same way as the
+ Crynwr packet driver -- the NatSemi method doesn't work.
+ Actually this doesn't always work either, but if you have
+ problems with your NEx000 this is better than nothing! */
+
+ outb_p(0x42, nic_base + EN0_RCNTLO);
+ outb_p(0x00, nic_base + EN0_RCNTHI);
+ outb_p(0x42, nic_base + EN0_RSARLO);
+ outb_p(0x00, nic_base + EN0_RSARHI);
+ outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);
+ /* Make certain that the dummy read has occurred. */
+ udelay(6);
+#endif
+
+ outb_p(ENISR_RDC, nic_base + EN0_ISR);
+
+ /* Now the normal output. */
+ outb_p(count & 0xff, nic_base + EN0_RCNTLO);
+ outb_p(count >> 8, nic_base + EN0_RCNTHI);
+ outb_p(0x00, nic_base + EN0_RSARLO);
+ outb_p(start_page, nic_base + EN0_RSARHI);
+
+ outb_p(E8390_RWRITE+E8390_START, nic_base + NE_CMD);
+ if (ei_status.word16) {
+ outsw(NE_BASE + NE_DATAPORT, buf, count>>1);
+ } else {
+ outsb(NE_BASE + NE_DATAPORT, buf, count);
+ }
+
+ dma_start = jiffies;
+
+#ifdef NE_SANITY_CHECK
+ /* This was for the ALPHA version only, but enough people have
+ been encountering problems so it is still here. */
+
+ if (ei_debug > 1)
+ {
+ /* DMA termination address check... */
+ int addr, tries = 20;
+ do {
+ int high = inb_p(nic_base + EN0_RSARHI);
+ int low = inb_p(nic_base + EN0_RSARLO);
+ addr = (high << 8) + low;
+ if ((start_page << 8) + count == addr)
+ break;
+ } while (--tries > 0);
+
+ if (tries <= 0)
+ {
+ printk(KERN_WARNING "%s: Tx packet transfer address mismatch,"
+ "%#4.4x (expected) vs. %#4.4x (actual).\n",
+ dev->name, (start_page << 8) + count, addr);
+ if (retries++ == 0)
+ goto retry;
+ }
+ }
+#endif
+
+ while ((inb_p(nic_base + EN0_ISR) & ENISR_RDC) == 0)
+ if (jiffies - dma_start > 2*HZ/100) { /* 20ms */
+ printk(KERN_WARNING "%s: timeout waiting for Tx RDC.\n", dev->name);
+ ne_reset_8390(dev);
+ NS8390_init(dev,1);
+ break;
+ }
+
+ outb_p(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */
+ ei_status.dmaing &= ~0x01;
+ return;
+}
+
+
+#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 hwtype[MAX_NE_CARDS] = { 0, }; /* board type */
+
+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");
+MODULE_PARM(hwtype, "1-" __MODULE_STRING(MAX_NE_CARDS) "i");
+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");
+MODULE_PARM_DESC(hwtype, "Board type of PC-9800 C-Bus NIC");
+MODULE_DESCRIPTION("NE1000/NE2000 PC-9800 C-bus Ethernet driver");
+MODULE_LICENSE("GPL");
+
+/* This is set up so that no ISA autoprobe takes place. We can't guarantee
+that the ne2k probe is the last 8390 based probe to take place (as it
+is at boot) and so the probe will get confused by any other 8390 cards.
+ISA device autoprobes on a running machine are not recommended anyway. */
+
+int init_module(void)
+{
+ int this_dev, found = 0;
+
+ for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
+ struct net_device *dev = &dev_ne[this_dev];
+ dev->irq = irq[this_dev];
+ dev->mem_end = bad[this_dev];
+ dev->base_addr = io[this_dev];
+ dev->mem_start = hwtype[this_dev];
+ dev->init = ne_probe;
+ if (register_netdev(dev) == 0) {
+ found++;
+ continue;
+ }
+ if (found != 0) { /* Got at least one. */
+ return 0;
+ }
+ if (io[this_dev] != 0)
+ printk(KERN_WARNING "ne.c: No NE*000 card found at i/o = %#x\n", io[this_dev]);
+ else
+ printk(KERN_NOTICE "ne.c: You must supply \"io=0xNNN\" value(s) for C-Bus cards.\n");
+ return -ENXIO;
+ }
+ return 0;
+}
+
+void cleanup_module(void)
+{
+ int this_dev;
+
+ for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
+ struct net_device *dev = &dev_ne[this_dev];
+ if (dev->priv != NULL) {
+ const struct ne2k_cbus_region *rlist;
+ const struct ne2k_cbus_hwinfo *hw = ne2k_cbus_get_hwinfo((int)(dev->mem_start & NE2K_CBUS_HARDWARE_TYPE_MASK));
+
+ free_irq(dev->irq, dev);
+ for (rlist = hw->regionlist; rlist->range; rlist++) {
+ release_region(dev->base_addr + rlist->start,
+ rlist->range);
+ }
+ unregister_netdev(dev);
+ ne2k_cbus_destroy(dev);
+ }
+ }
+}
+#endif /* MODULE */
+
+
+/*
+ * Local variables:
+ * compile-command: "gcc -DKERNEL -Wall -O6 -fomit-frame-pointer -I/usr/src/linux/net/tcp -c ne.c"
+ * version-control: t
+ * kept-new-versions: 5
+ * End:
+ */
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-03-21 02:54:41

by Osamu Tomita

[permalink] [raw]
Subject: [PATCH 2.5.65-ac1] Support PC-9800 subarchitecture (14/14) video update

This is the patch to support NEC PC-9800 subarchitecture
against 2.5.65-ac1. (14/14)

Add missing patch.
(PC98 standard video card text mode driver.)

Regards,
Osamu Tomita

diff -Nru linux-2.5.60/drivers/video/console/Makefile linux98-2.5.60/drivers/video/console/Makefile
--- linux-2.5.60/drivers/video/console/Makefile 2003-02-11 03:38:30.000000000 +0900
+++ linux98-2.5.60/drivers/video/console/Makefile 2003-02-11 09:47:18.000000000 +0900
@@ -19,6 +19,7 @@
# Each configuration option enables a list of files.

obj-$(CONFIG_DUMMY_CONSOLE) += dummycon.o
+obj-$(CONFIG_GDC_CONSOLE) += gdccon.o
obj-$(CONFIG_SGI_NEWPORT_CONSOLE) += newport_con.o
obj-$(CONFIG_PROM_CONSOLE) += promcon.o promcon_tbl.o
obj-$(CONFIG_STI_CONSOLE) += sticon.o sticore.o
diff -Nru linux-2.5.61/drivers/video/console/gdccon.c linux98-2.5.61/drivers/video/console/gdccon.c
--- linux-2.5.61/drivers/video/console/gdccon.c 1970-01-01 09:00:00.000000000 +0900
+++ linux98-2.5.61/drivers/video/console/gdccon.c 2003-02-16 17:19:03.000000000 +0900
@@ -0,0 +1,833 @@
+/*
+ * linux/drivers/video/gdccon.c
+ * Low level GDC based console driver for NEC PC-9800 series
+ *
+ * Created 24 Dec 1998 by Linux/98 project
+ *
+ * based on:
+ * linux/drivers/video/vgacon.c in Linux 2.1.131 by Geert Uytterhoeven
+ * linux/char/gdc.c in Linux/98 2.1.57 by Linux/98 project
+ * linux/char/console.c in Linux/98 2.1.57 by Linux/98 project
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/tty.h>
+#include <linux/console.h>
+#include <linux/string.h>
+#include <linux/kd.h>
+#include <linux/slab.h>
+#include <linux/vt_kern.h>
+#include <linux/selection.h>
+#include <linux/spinlock.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+#include <asm/pc9800.h>
+
+static spinlock_t gdc_lock = SPIN_LOCK_UNLOCKED;
+
+static char str_gdc_master[] = "GDC (master)";
+static char str_gdc_slave[] = "GDC (slave)";
+static char str_crtc[] = "crtc";
+static struct resource gdc_console_resources[] = {
+ {str_gdc_master, 0x60, 0x60, 0},
+ {str_gdc_master, 0x62, 0x62, 0},
+ {str_gdc_master, 0x64, 0x64, 0},
+ {str_gdc_master, 0x66, 0x66, 0},
+ {str_gdc_master, 0x68, 0x68, 0},
+ {str_gdc_master, 0x6a, 0x6a, 0},
+ {str_gdc_master, 0x6c, 0x6c, 0},
+ {str_gdc_master, 0x6e, 0x6e, 0},
+ {str_crtc, 0x70, 0x70, 0},
+ {str_crtc, 0x72, 0x72, 0},
+ {str_crtc, 0x74, 0x74, 0},
+ {str_crtc, 0x76, 0x76, 0},
+ {str_crtc, 0x78, 0x78, 0},
+ {str_crtc, 0x7a, 0x7a, 0},
+ {str_gdc_slave, 0xa0, 0xa0, 0},
+ {str_gdc_slave, 0xa2, 0xa2, 0},
+ {str_gdc_slave, 0xa4, 0xa4, 0},
+ {str_gdc_slave, 0xa6, 0xa6, 0},
+};
+
+#define GDC_CONSOLE_RESOURCES (sizeof(gdc_console_resources)/sizeof(struct resource))
+
+#define BLANK 0x0020
+#define BLANK_ATTR 0x00e1
+
+/* GDC/GGDC port# */
+#define GDC_COMMAND 0x62
+#define GDC_PARAM 0x60
+#define GDC_STAT 0x60
+#define GDC_DATA 0x62
+
+#define MODE_FF1 (0x0068) /* mode F/F register 1 */
+
+#define MODE_FF1_ATR_SEL (0x00) /* 0: vertical line 1: 8001 graphic */
+#define MODE_FF1_GRAPHIC_MODE (0x02) /* 0: color 1: mono */
+#define MODE_FF1_COLUMN_WIDTH (0x04) /* 0: 80col 1: 40col */
+#define MODE_FF1_FONT_SEL (0x06) /* 0: 6x8 1: 7x13 */
+#define MODE_FF1_GRP_MODE (0x08) /* 0: display odd-y raster 1: not */
+#define MODE_FF1_KAC_MODE (0x0a) /* 0: code access 1: dot access */
+#define MODE_FF1_NVMW_PERMIT (0x0c) /* 0: protect 1: permit */
+#define MODE_FF1_DISP_ENABLE (0x0e) /* 0: enable 1: disable */
+
+#define GGDC_COMMAND 0xa2
+#define GGDC_PARAM 0xa0
+#define GGDC_STAT 0xa0
+#define GGDC_DATA 0xa2
+
+/* GDC status */
+#define GDC_DATA_READY (1 << 0)
+#define GDC_FIFO_FULL (1 << 1)
+#define GDC_FIFO_EMPTY (1 << 2)
+#define GGDC_FIFO_EMPTY GDC_FIFO_EMPTY
+#define GDC_DRAWING (1 << 3)
+#define GDC_DMA_EXECUTE (1 << 4) /* nonsense on 98 */
+#define GDC_VERTICAL_SYNC (1 << 5)
+#define GDC_HORIZONTAL_BLANK (1 << 6)
+#define GDC_LIGHTPEN_DETECT (1 << 7) /* nonsense on 98 */
+
+#define ATTR_G (1U << 7)
+#define ATTR_R (1U << 6)
+#define ATTR_B (1U << 5)
+#define ATTR_GRAPHIC (1U << 4)
+#define ATTR_VERTBAR ATTR_GRAPHIC /* vertical bar */
+#define ATTR_UNDERLINE (1U << 3)
+#define ATTR_REVERSE (1U << 2)
+#define ATTR_BLINK (1U << 1)
+#define ATTR_NOSECRET (1U << 0)
+#define AMASK_NOCOLOR (ATTR_GRAPHIC | ATTR_UNDERLINE | ATTR_REVERSE \
+ | ATTR_BLINK | ATTR_NOSECRET)
+
+/*
+ * Interface used by the world
+ */
+static const char *gdccon_startup(void);
+static void gdccon_init(struct vc_data *c, int init);
+static void gdccon_deinit(struct vc_data *c);
+static void gdccon_cursor(struct vc_data *c, int mode);
+static int gdccon_switch(struct vc_data *c);
+static int gdccon_blank(struct vc_data *c, int blank);
+static int gdccon_scrolldelta(struct vc_data *c, int lines);
+static int gdccon_set_origin(struct vc_data *c);
+static void gdccon_save_screen(struct vc_data *c);
+static int gdccon_scroll(struct vc_data *c, int t, int b, int dir, int lines);
+static u8 gdccon_build_attr(struct vc_data *c, u8 color, u8 intensity, u8 blink, u8 underline, u8 reverse);
+static void gdccon_invert_region(struct vc_data *c, u16 *p, int count);
+static unsigned long gdccon_uni_pagedir[2];
+
+/* Description of the hardware situation */
+static unsigned long gdc_vram_base; /* Base of video memory */
+static unsigned long gdc_vram_end; /* End of video memory */
+static unsigned int gdc_video_num_columns = 80;
+ /* Number of text columns */
+static unsigned int gdc_video_num_lines = 25;
+ /* Number of text lines */
+static int gdc_can_do_color = 1; /* Do we support colors? */
+static unsigned char gdc_video_type; /* Card type */
+static unsigned char gdc_hardscroll_enabled;
+static unsigned char gdc_hardscroll_user_enable = 1;
+static int gdc_vesa_blanked = 0;
+static unsigned int gdc_rolled_over = 0;
+
+#define DISP_FREQ_AUTO 0
+#define DISP_FREQ_25k 1
+#define DISP_FREQ_31k 2
+
+static unsigned int gdc_disp_freq = DISP_FREQ_AUTO;
+
+#define gdc_attr_offset(x) ((typeof(x))((unsigned long)(x)+0x2000))
+
+#define gdc_outb(val, port) outb_p((val), (port))
+#define gdc_inb(port) inb_p(port)
+
+#define __gdc_write_command(cmd) gdc_outb((cmd), GDC_COMMAND)
+#define __gdc_write_param(param) gdc_outb((param), GDC_PARAM)
+
+static const char * __init gdccon_startup(void)
+{
+ const char *display_desc = NULL;
+ unsigned long hdots = gdc_video_num_lines * 16;
+ int i;
+
+ while (!(inb_p(GDC_STAT) & GDC_FIFO_EMPTY));
+ while (!(inb_p(GGDC_STAT) & GDC_FIFO_EMPTY));
+ spin_lock_irq(&gdc_lock);
+ outb_p(0x0c, GDC_COMMAND); /* STOP */
+ outb_p(0x0c, GGDC_COMMAND); /* STOP */
+ if (PC9800_9821_P() && gdc_disp_freq == DISP_FREQ_AUTO) {
+ if (gdc_video_num_lines >= 30 || (inb(0x9a8) & 0x01)) {
+ gdc_disp_freq = DISP_FREQ_31k;
+ }
+ }
+
+ if (PC9800_9821_P() && gdc_disp_freq == DISP_FREQ_31k) {
+ outb_p(0x01, 0x9a8); /* 31.47KHz */
+ outb_p(0x0e, GDC_COMMAND); /* SYNC, DE deny */
+ outb_p(0x00, GDC_PARAM); /* CHR, F, I, D, G, S = 0 */
+ outb_p(0x4e, GDC_PARAM); /* C/R = 78 (80 chars) */
+ outb_p(0x4b, GDC_PARAM); /* VSL = 2(3) ; HS = 11 */
+ outb_p(0x0c, GDC_PARAM); /* HFP = 3 ; VSH = 0(VS=2) */
+ outb_p(0x03, GDC_PARAM); /* DS, PH = 0 ; HBP = 3 */
+ outb_p(0x06, GDC_PARAM); /* VH, VL = 0 ; VFP = 6 */
+ outb_p(hdots & 0xff, GDC_PARAM); /* LFL */
+ outb_p(0x94 | ((hdots >> 8) & 0x03), GDC_PARAM);
+ /* VBP = 37 ; LFH */
+ outb_p(0x47, GDC_COMMAND); /* PITCH */
+ outb_p(0x50, GDC_PARAM);
+
+ outb_p(0x70, GDC_COMMAND); /* SCROLL */
+ outb_p(0x00, GDC_PARAM);
+ outb_p(0x00, GDC_PARAM);
+ outb_p((hdots << 4) & 0xf0, GDC_PARAM); /* SL1=592 (0x250) */
+ outb_p((hdots >> 4) & 0x3f, GDC_PARAM);
+
+ outb_p(0x0e, GGDC_COMMAND); /* SYNC, DE deny */
+ outb_p(0x00, GGDC_PARAM); /* CHR, F, I, D, G, S = 0 */
+ outb_p(0x4e, GGDC_PARAM); /* C/R = 78 (80 chars) */
+ outb_p(0x4b, GGDC_PARAM); /* VSL = 2(3) ; HS = 11 */
+ outb_p(0x0c, GGDC_PARAM); /* HFP = 3 ; VSH = 0(VS=2) */
+ outb_p(0x03, GGDC_PARAM); /* DS, PH = 0 ; HBP = 3 */
+ outb_p(0x06, GGDC_PARAM); /* VH, VL = 0 ; VFP = 6 */
+ outb_p(hdots & 0xff, GGDC_PARAM); /* LFL */
+ outb_p(0x94 | ((hdots >> 8) & 0x03), GGDC_PARAM);
+ /* VBP = 37 ; LFH */
+ } else {
+ outb_p(0x00, 0x9a8); /* 24.83 KHz */
+ outb_p(0x0e, GDC_COMMAND); /* SYNC, DE deny */
+ outb_p(0x00, GDC_PARAM); /* CHR, F, I, D, G, S = 0 */
+ outb_p(0x4e, GDC_PARAM); /* C/R = 78 (80 chars) */
+ outb_p(0x07, GDC_PARAM); /* VSL = 0(3) ; HS = 7 */
+ outb_p(0x25, GDC_PARAM); /* HFP = 9 ; VSH = 1(VS=8) */
+ outb_p(0x07, GDC_PARAM); /* DS, PH = 0 ; HBP = 7 */
+ outb_p(0x07, GDC_PARAM); /* VH, VL = 0 ; VFP = 7 */
+ outb_p(hdots & 0xff, GDC_PARAM); /* LFL */
+ outb_p(0x64 | ((hdots >> 8) & 0x03), GDC_PARAM);
+ /* VBP = 25 ; LFH */
+ outb_p(0x47, GDC_COMMAND); /* PITCH */
+ outb_p(0x50, GDC_PARAM);
+
+ outb_p(0x70, GDC_COMMAND); /* SCROLL */
+ outb_p(0x00, GDC_PARAM);
+ outb_p(0x00, GDC_PARAM);
+ outb_p((hdots << 4) & 0xf0, GDC_PARAM); /* SL1=592 (0x250) */
+ outb_p((hdots >> 4) & 0x3f, GDC_PARAM);
+
+ outb_p(0x0e, GGDC_COMMAND); /* SYNC */
+ outb_p(0x00, GGDC_PARAM);
+ outb_p(0x4e, GGDC_PARAM);
+ outb_p(0x07, GGDC_PARAM);
+ outb_p(0x25, GGDC_PARAM);
+ outb_p(0x07, GGDC_PARAM);
+ outb_p(0x07, GGDC_PARAM);
+ outb_p(hdots & 0xff, GGDC_PARAM); /* LFL */
+ outb_p(0x64 | ((hdots >> 8) & 0x03), GGDC_PARAM);
+ /* VBP = 25 ; LFH */
+ }
+
+ outb_p(0x47, GGDC_COMMAND); /* PITCH */
+ outb_p(0x28, GGDC_PARAM);
+
+ outb_p(0x0d, GDC_COMMAND); /* START */
+ outb_p(0x0d, GGDC_COMMAND); /* START */
+ spin_unlock_irq(&gdc_lock);
+
+ gdc_vram_base = (unsigned long)phys_to_virt(0xa0000);
+ /* Last few bytes of text VRAM area are for NVRAM. */
+ gdc_vram_end = gdc_vram_base + 0x1fe0;
+
+ if (!PC9800_HIGHRESO_P()) {
+ gdc_video_type = VIDEO_TYPE_98NORMAL;
+ display_desc = "NEC PC-9800 Normal";
+ } else {
+ gdc_video_type = VIDEO_TYPE_98HIRESO;
+ display_desc = "NEC PC-9800 High Resolution";
+ }
+
+ gdc_hardscroll_enabled = gdc_hardscroll_user_enable;
+
+ for (i = 0; i < GDC_CONSOLE_RESOURCES; i++)
+ request_resource(&ioport_resource, gdc_console_resources + i);
+
+ return display_desc;
+}
+
+static void gdccon_init(struct vc_data *c, int init)
+{
+ unsigned long p;
+
+ /* We cannot be loaded as a module, therefore init is always 1 */
+ c->vc_can_do_color = gdc_can_do_color;
+ c->vc_cols = gdc_video_num_columns;
+ c->vc_rows = gdc_video_num_lines;
+ c->vc_complement_mask = ATTR_REVERSE << 8;
+ p = *c->vc_uni_pagedir_loc;
+ if (c->vc_uni_pagedir_loc == &c->vc_uni_pagedir
+ || !--c->vc_uni_pagedir_loc[1])
+ con_free_unimap(c->vc_num);
+
+ c->vc_uni_pagedir_loc = gdccon_uni_pagedir;
+ gdccon_uni_pagedir[1]++;
+ if (!gdccon_uni_pagedir[0] && p)
+ con_set_default_unimap(c->vc_num);
+}
+
+static inline void gdc_set_mem_top(struct vc_data *c)
+{
+ unsigned long flags;
+ unsigned long origin = (c->vc_visible_origin - gdc_vram_base) / 2;
+
+ spin_lock_irqsave(&gdc_lock, flags);
+ while (!(inb_p(GDC_STAT) & GDC_FIFO_EMPTY));
+ __gdc_write_command(0x70); /* SCROLL */
+ __gdc_write_param(origin); /* SAD1 (L) */
+ __gdc_write_param((origin >> 8) & 0x1f); /* SAD1 (H) */
+ spin_unlock_irqrestore(&gdc_lock, flags);
+}
+
+static void gdccon_deinit(struct vc_data *c)
+{
+ /* When closing the last console, reset video origin */
+ if (!--gdccon_uni_pagedir[1]) {
+ c->vc_visible_origin = gdc_vram_base;
+ gdc_set_mem_top(c);
+ con_free_unimap(c->vc_num);
+ }
+
+ c->vc_uni_pagedir_loc = &c->vc_uni_pagedir;
+ con_set_default_unimap(c->vc_num);
+}
+
+#if 0
+/* Translate ANSI terminal color code to GDC color code. */
+#define BGR_TO_GRB(bgr) ((((bgr) & 4) >> 2) | (((bgr) & 3) << 1))
+#else
+#define RGB_TO_GRB(rgb) ((((rgb) & 4) >> 1) | (((rgb) & 2) << 1) | ((rgb) & 1))
+#endif
+
+static const u8 gdccon_color_table[] = {
+#define C(color) ((RGB_TO_GRB (color) << 5) | ATTR_NOSECRET)
+ C(0), C(1), C(2), C(3), C(4), C(5), C(6), C(7)
+#undef C
+};
+
+static u8 gdccon_build_attr(struct vc_data *c, u8 color, u8 intensity, u8 blink, u8 underline, u8 reverse)
+{
+ u8 attr = gdccon_color_table[color & 0x07];
+
+ if (!gdc_can_do_color)
+ attr = (intensity == 0 ? 0x61
+ : intensity == 2 ? 0xe1 : 0xa1);
+
+ if (underline)
+ attr |= 0x08;
+
+ /* ignore intensity */
+#if 0
+ if(intensity == 0)
+ ;
+ else if (intensity == 2)
+ attr |= 0x10; /* virtical line */
+#else
+ if (intensity == 0) {
+ if (attr == c->vc_def_attr)
+ attr = c->vc_half_attr;
+ else
+ attr |= c->vc_half_attr & AMASK_NOCOLOR;
+ } else if (intensity == 2) {
+ if (attr == c->vc_def_attr)
+ attr = c->vc_bold_attr;
+ else
+ attr |= c->vc_bold_attr & AMASK_NOCOLOR;
+ }
+#endif
+ if (reverse)
+ attr |= ATTR_REVERSE;
+
+ if ((color & 0x07) == 0) { /* foreground color == black */
+ /* Fake background color by reversed character
+ as GDC cannot set background color. */
+ attr |= gdccon_color_table[(color >> 4) & 0x07];
+ attr ^= ATTR_REVERSE;
+ }
+
+ if (blink)
+ attr |= ATTR_BLINK;
+
+ return attr;
+}
+
+static void gdccon_invert_region(struct vc_data *c, u16 *p, int count)
+{
+ while (count--) {
+ *((u16 *)(gdc_attr_offset(p))) ^= ATTR_REVERSE;
+ p++;
+ }
+}
+
+static u8 gdc_csrform_lr = 15; /* Lines/Row */
+static u16 gdc_csrform_bl_bd = ((12 << 6) /* BLinking Rate */
+ | (0 << 5)); /* Blinking Disable */
+
+static inline void gdc_hide_cursor(void)
+{
+ __gdc_write_command(0x4b); /* CSRFORM */
+ __gdc_write_param(gdc_csrform_lr); /* CS = 0, CE = 0, L/R = ? */
+}
+
+static inline void gdc_show_cursor(int cursor_start, int cursor_finish)
+{
+ __gdc_write_command(0x4b); /* CSRFORM */
+ __gdc_write_param(0x80 | gdc_csrform_lr); /* CS = 1 */
+ __gdc_write_param(cursor_start | gdc_csrform_bl_bd);
+ __gdc_write_param((cursor_finish << 3) | (gdc_csrform_bl_bd >> 8));
+}
+
+static void gdccon_cursor(struct vc_data *c, int mode)
+{
+ unsigned long flags;
+ u16 ead;
+
+ if (c->vc_origin != c->vc_visible_origin)
+ gdccon_scrolldelta(c, 0);
+
+ spin_lock_irqsave(&gdc_lock, flags);
+ while (!(inb_p(GDC_STAT) & GDC_FIFO_EMPTY));
+ spin_unlock_irqrestore(&gdc_lock, flags);
+ switch (mode) {
+ case CM_ERASE:
+ gdc_hide_cursor();
+ break;
+
+ case CM_MOVE:
+ case CM_DRAW:
+ switch (c->vc_cursor_type & 0x0f) {
+ case CUR_UNDERLINE:
+ gdc_show_cursor(14, 15); /* XXX font height */
+ break;
+
+ case CUR_TWO_THIRDS:
+ gdc_show_cursor(5, 15); /* XXX */
+ break;
+
+ case CUR_LOWER_THIRD:
+ gdc_show_cursor(11, 15); /* XXX */
+ break;
+
+ case CUR_LOWER_HALF:
+ gdc_show_cursor(8, 15); /* XXX */
+ break;
+
+ case CUR_NONE:
+ gdc_hide_cursor();
+ break;
+
+ default:
+ gdc_show_cursor(0, 15); /* XXX */
+ break;
+ }
+
+ spin_lock_irqsave(&gdc_lock, flags);
+ __gdc_write_command(0x49); /* CSRW */
+ ead = (c->vc_pos - gdc_vram_base) >> 1;
+ __gdc_write_param(ead);
+ __gdc_write_param((ead >> 8) & 0x1f);
+ spin_unlock_irqrestore(&gdc_lock, flags);
+ break;
+ }
+
+}
+
+static int gdccon_switch(struct vc_data *c)
+{
+ /*
+ * We need to save screen size here as it's the only way
+ * we can spot the screen has been resized and we need to
+ * set size of freshly allocated screens ourselves.
+ */
+ gdc_video_num_columns = c->vc_cols;
+ gdc_video_num_lines = c->vc_rows;
+ if (c->vc_origin != (unsigned long)c->vc_screenbuf
+ && gdc_vram_base <= c->vc_origin && c->vc_origin < gdc_vram_end) {
+ _scr_memcpyw_to((u16 *)c->vc_origin,
+ (u16 *)c->vc_screenbuf,
+ c->vc_screenbuf_size);
+ _scr_memcpyw_to((u16 *)gdc_attr_offset(c->vc_origin),
+ (u16 *)((char *)c->vc_screenbuf
+ + c->vc_screenbuf_size),
+ c->vc_screenbuf_size);
+ } else
+ printk(KERN_WARNING
+ "gdccon: switch (vc #%d) called on origin=%lx\n",
+ c->vc_num, c->vc_origin);
+
+ return 0; /* Redrawing not needed */
+}
+
+static int gdccon_set_palette(struct vc_data *c, unsigned char *table)
+{
+ return -EINVAL;
+}
+
+#define RELAY0 0x01
+#define RELAY0_GDC 0x00
+#define RELAY0_ACCEL 0x01
+#define RELAY1 0x02
+#define RELAY1_INTERNAL 0x00
+#define RELAY1_EXTERNAL 0x02
+#define IO_RELAY 0x0fac
+#define IO_DPMS 0x09a2
+static unsigned char relay_mode = RELAY0_GDC | RELAY1_INTERNAL;
+
+static void gdc_vesa_blank(int mode)
+{
+ unsigned char stat;
+
+ spin_lock_irq(&gdc_lock);
+
+ relay_mode = inb_p(IO_RELAY);
+ if ((relay_mode & (RELAY0 | RELAY1)) != (RELAY0_GDC | RELAY1_INTERNAL)) {
+#ifdef CONFIG_DONTTOUCHRELAY
+ spin_unlock_irq(&gdc_lock);
+ return;
+#else
+ outb_p((relay_mode & ~(RELAY0 | RELAY1)) |
+ RELAY0_GDC | RELAY1_INTERNAL , IO_RELAY);
+#endif
+ }
+
+ if (mode & VESA_VSYNC_SUSPEND) {
+ stat = inb_p(IO_DPMS);
+ outb_p(stat | 0x80, IO_DPMS);
+ }
+ if (mode & VESA_HSYNC_SUSPEND) {
+ stat = inb_p(IO_DPMS);
+ outb_p(stat | 0x40, IO_DPMS);
+ }
+
+ spin_unlock_irq(&gdc_lock);
+}
+
+static void gdc_vesa_unblank(void)
+{
+ unsigned char stat;
+
+#ifdef CONFIG_DONTTOUCHRELAY
+ if (relay_mode & (RELAY0 | RELAY1))
+ return;
+#endif
+
+ spin_lock_irq(&gdc_lock);
+
+ stat = inb_p(0x09a2);
+ outb_p(stat & ~0xc0, IO_DPMS);
+ if (relay_mode & (RELAY0 | RELAY1))
+ outb_p(relay_mode, IO_RELAY);
+
+ spin_unlock_irq(&gdc_lock);
+}
+
+static int gdccon_blank(struct vc_data *c, int blank)
+{
+ switch (blank) {
+ case 0: /* Unblank */
+ if (gdc_vesa_blanked) {
+ gdc_vesa_unblank();
+ gdc_vesa_blanked = 0;
+ }
+
+ outb(MODE_FF1_DISP_ENABLE | 1, MODE_FF1);
+
+ /* Tell console.c that it need not to restore the screen */
+ return 0;
+
+ case 1: /* Normal blanking */
+ /* Disable displaying */
+ outb(MODE_FF1_DISP_ENABLE | 0, MODE_FF1);
+
+ /* Tell console.c that it need not to reset origin */
+ return 0;
+
+ case -1: /* Entering graphic mode */
+ return 1;
+
+ default: /* VESA blanking */
+ if (gdc_video_type == VIDEO_TYPE_98NORMAL
+ || gdc_video_type == VIDEO_TYPE_9840
+ || gdc_video_type == VIDEO_TYPE_98HIRESO) {
+ gdc_vesa_blank(blank - 1);
+ gdc_vesa_blanked = blank;
+ }
+
+ return 0;
+ }
+}
+
+static int gdccon_font_op(struct vc_data *c, struct console_font_op *op)
+{
+ return -ENOSYS;
+}
+
+static int gdccon_scrolldelta(struct vc_data *c, int lines)
+{
+ if (!lines) /* Turn scrollback off */
+ c->vc_visible_origin = c->vc_origin;
+ else {
+ int vram_size = gdc_vram_end - gdc_vram_base;
+ int margin = c->vc_size_row /* * 4 */;
+ int ul, we, p, st;
+
+ if (gdc_rolled_over > c->vc_scr_end - gdc_vram_base + margin) {
+ ul = c->vc_scr_end - gdc_vram_base;
+ we = gdc_rolled_over + c->vc_size_row;
+ } else {
+ ul = 0;
+ we = vram_size;
+ }
+
+ p = (c->vc_visible_origin - gdc_vram_base - ul + we)
+ % we + lines * c->vc_size_row;
+ st = (c->vc_origin - gdc_vram_base - ul + we) % we;
+ if (p < margin)
+ p = 0;
+
+ if (p > st - margin)
+ p = st;
+ c->vc_visible_origin = gdc_vram_base + (p + ul) % we;
+ }
+
+ gdc_set_mem_top(c);
+ return 1;
+}
+
+static int gdccon_set_origin(struct vc_data *c)
+{
+ c->vc_origin = c->vc_visible_origin = gdc_vram_base;
+ gdc_set_mem_top(c);
+ gdc_rolled_over = 0;
+ return 1;
+}
+
+static void gdccon_save_screen(struct vc_data *c)
+{
+ static int gdc_bootup_console = 0;
+
+ if (!gdc_bootup_console) {
+ /* This is a gross hack, but here is the only place we can
+ * set bootup console parameters without messing up generic
+ * console initialization routines.
+ */
+ gdc_bootup_console = 1;
+ c->vc_x = ORIG_X;
+ c->vc_y = ORIG_Y;
+ }
+
+ _scr_memcpyw_from((u16 *)c->vc_screenbuf,
+ (u16 *)c->vc_origin, c->vc_screenbuf_size);
+ _scr_memcpyw_from((u16 *)((char *)c->vc_screenbuf + c->vc_screenbuf_size), (u16 *)gdc_attr_offset(c->vc_origin), c->vc_screenbuf_size);
+}
+
+static int gdccon_scroll(struct vc_data *c, int t, int b, int dir, int lines)
+{
+ unsigned long oldo;
+ unsigned int delta;
+
+ if (t || b != c->vc_rows)
+ return 0;
+
+ if (c->vc_origin != c->vc_visible_origin)
+ gdccon_scrolldelta(c, 0);
+
+ if (!gdc_hardscroll_enabled || lines >= c->vc_rows / 2)
+ return 0;
+
+ oldo = c->vc_origin;
+ delta = lines * c->vc_size_row;
+ if (dir == SM_UP) {
+ if (c->vc_scr_end + delta >= gdc_vram_end) {
+ _scr_memcpyw((u16 *)gdc_vram_base,
+ (u16 *)(oldo + delta),
+ c->vc_screenbuf_size - delta);
+ _scr_memcpyw((u16 *)gdc_attr_offset(gdc_vram_base),
+ (u16 *)gdc_attr_offset(oldo + delta),
+ c->vc_screenbuf_size - delta);
+ c->vc_origin = gdc_vram_base;
+ gdc_rolled_over = oldo - gdc_vram_base;
+ } else
+ c->vc_origin += delta;
+
+ _scr_memsetw((u16 *)(c->vc_origin + c->vc_screenbuf_size - delta), c->vc_video_erase_char & 0xff, delta);
+ _scr_memsetw((u16 *)gdc_attr_offset(c->vc_origin + c->vc_screenbuf_size - delta), c->vc_video_erase_char >> 8, delta);
+ } else {
+ if (oldo - delta < gdc_vram_base) {
+ _scr_memmovew((u16 *)(gdc_vram_end - c->vc_screenbuf_size + delta), (u16 *)oldo, c->vc_screenbuf_size - delta);
+ _scr_memmovew((u16 *)gdc_attr_offset(gdc_vram_end - c->vc_screenbuf_size + delta), (u16 *)gdc_attr_offset(oldo), c->vc_screenbuf_size - delta);
+ c->vc_origin = gdc_vram_end - c->vc_screenbuf_size;
+ gdc_rolled_over = 0;
+ } else
+ c->vc_origin -= delta;
+
+ c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size;
+ _scr_memsetw((u16 *)(c->vc_origin), c->vc_video_erase_char & 0xff, delta);
+ _scr_memsetw((u16 *)gdc_attr_offset(c->vc_origin), c->vc_video_erase_char >> 8, delta);
+ }
+
+ c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size;
+ c->vc_visible_origin = c->vc_origin;
+ gdc_set_mem_top(c);
+ c->vc_pos = (c->vc_pos - oldo) + c->vc_origin;
+ return 1;
+}
+
+static int gdccon_setterm_command(struct vc_data *c)
+{
+ switch (c->vc_par[0]) {
+ case 1: /* set attr for underline mode */
+ if (c->vc_npar < 2) {
+ if (c->vc_par[1] < 16)
+ c->vc_ul_attr = gdccon_color_table[color_table[c->vc_par[1]] & 7];
+ } else {
+ if (c->vc_par[2] < 256)
+ c->vc_ul_attr = c->vc_par[2];
+ }
+
+ if (c->vc_underline)
+ goto update_attr;
+
+ return 1;
+
+ case 2: /* set attr for half intensity mode */
+ if (c->vc_npar < 2) {
+ if (c->vc_par[1] < 16)
+ c->vc_half_attr = gdccon_color_table[color_table[c->vc_par[1]] & 7];
+ }
+ else {
+ if (c->vc_par[2] < 256)
+ c->vc_half_attr = c->vc_par[2];
+ }
+
+ if (c->vc_intensity == 0)
+ goto update_attr;
+
+ return 1;
+
+ case 3: /* set color for bold mode */
+ if (c->vc_npar < 2) {
+ if (c->vc_par[1] < 16)
+ c->vc_bold_attr = gdccon_color_table[color_table[c->vc_par[1]] & 7];
+ } else {
+ if (c->vc_par[2] < 256)
+ c->vc_bold_attr = c->vc_par[2];
+ }
+
+ if (c->vc_intensity == 2)
+ goto update_attr;
+
+ return 1;
+ }
+
+ return 0;
+
+update_attr:
+ c->vc_attr = gdccon_build_attr(c,
+ c->vc_color, c->vc_intensity,
+ c->vc_blink, c->vc_underline,
+ c->vc_reverse);
+ return 1;
+}
+
+/*
+ * The console `switch' structure for the GDC based console
+ */
+
+static int gdccon_dummy(struct vc_data *c)
+{
+ return 0;
+}
+
+#define DUMMY (void *) gdccon_dummy
+
+const struct consw gdc_con = {
+ .con_startup = gdccon_startup,
+ .con_init = gdccon_init,
+ .con_deinit = gdccon_deinit,
+ .con_clear = DUMMY,
+ .con_putc = DUMMY,
+ .con_putcs = DUMMY,
+ .con_cursor = gdccon_cursor,
+ .con_scroll = gdccon_scroll,
+ .con_bmove = DUMMY,
+ .con_switch = gdccon_switch,
+ .con_blank = gdccon_blank,
+ .con_font_op = gdccon_font_op,
+ .con_set_palette = gdccon_set_palette,
+ .con_scrolldelta = gdccon_scrolldelta,
+ .con_set_origin = gdccon_set_origin,
+ .con_save_screen = gdccon_save_screen,
+ .con_build_attr = gdccon_build_attr,
+ .con_invert_region = gdccon_invert_region,
+ .con_setterm_command = gdccon_setterm_command
+};
+
+static int __init gdc_setup(char *str)
+{
+ unsigned long tmp_ulong;
+ char *opt, *orig_opt, *endp;
+
+ while ((opt = strsep(&str, ",")) != NULL) {
+ int force = 0;
+
+ orig_opt = opt;
+ if (!strncmp(opt, "force", 5)) {
+ force = 1;
+ opt += 5;
+ }
+
+ if (!strcmp(opt, "mono"))
+ gdc_can_do_color = 0;
+ else if ((tmp_ulong = simple_strtoul(opt, &endp, 0)) > 0) {
+ if (!strcmp(endp, "lines")
+ || (!strcmp(endp, "linesforce") && (force == 1))) {
+ if (!force
+ && (tmp_ulong < 20
+ || (!PC9800_9821_P()
+ && 25 < tmp_ulong)
+ || 37 < tmp_ulong))
+ printk(KERN_ERR
+ "gdccon: %d is out of bound"
+ " for number of lines\n",
+ (int)tmp_ulong);
+ else
+ gdc_video_num_lines = tmp_ulong;
+ } else if (!strcmp(endp, "kHz")) {
+ if (tmp_ulong == 24 || tmp_ulong == 25)
+ gdc_disp_freq = DISP_FREQ_25k;
+ else
+ printk(KERN_ERR "gdccon: `%s' ignored\n",
+ orig_opt);
+ } else
+ printk(KERN_ERR "gdccon: unknown option `%s'\n",
+ orig_opt);
+ } else
+ printk(KERN_ERR "gdccon: unknown option `%s'\n",
+ orig_opt);
+ }
+
+ return 1;
+}
+
+__setup("gdccon=", gdc_setup);
+
+/*
+ * We will follow Linus's indenting style...
+ *
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */

2003-03-21 04:00:46

by Jeff Garzik

[permalink] [raw]
Subject: Re: [PATCH 2.5.65-ac1] Support PC-9800 subarchitecture (9/14) NIC

Thank you for your patience and tenacity, and for listening to comments
from Linux kernel developers.

Looks good, patch applied.

2003-03-21 04:25:36

by Osamu Tomita

[permalink] [raw]
Subject: Re: [PATCH 2.5.65-ac1] Support PC-9800 subarchitecture (9/14) NIC

Jeff Garzik wrote:
>
> Thank you for your patience and tenacity, and for listening to comments
> from Linux kernel developers.
>
> Looks good, patch applied.
Thank you very much.
We are happy. I've been receiving many cheering mail from
PC-98 peoples.

--
Osamu tomita