2003-03-16 00:06:20

by Osamu Tomita

[permalink] [raw]
Subject: Complete support PC-9800 for 2.5.64-ac4 (0/11) summary

This is the patchset to support NEC PC-9800 subarchitecture
against 2.5.64-ac4.

Thanks for many advices and merging.
PC-9800 works fine with this patchset.
I put archived patchset URL bellow.
http://downloads.sourceforge.jp/linux98/2638/linux98-2.5.64-ac4.patch.tar.bz2

Comments and test reports are wellcome.

Description:
o console.patch (1/11)
PC98 Standard console support (without japanese kanji character).

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

o core-misc.patch (2/11)
Small patches for PC98 support core.

include/asm-i386/io.h | 6 ++++++
include/asm-i386/irq.h | 4 ++++
include/asm-i386/pc9800.h | 27 +++++++++++++++++++++++++++
include/linux/kernel.h | 6 ++++++
4 files changed, 43 insertions(+)

o dma.patch (3/11)
DMA support for PC98.

include/asm-i386/dma.h | 7 +
include/asm-i386/pc9800_dma.h | 238 +++++++++++++++++++++++++++++++++++++++++
include/asm-i386/scatterlist.h | 6 +
kernel/dma.c | 3
4 files changed, 254 insertions(+)

o ide.patch (4/11)
PC98 standard IDE I/F support.

drivers/ide/ide-disk.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++
drivers/ide/ide.c | 9 +++++-
drivers/ide/ide-probe.c | 16 +++++++++--
include/linux/hdreg.h | 19 +++++++++++++
4 files changed, 107 insertions(+), 4 deletions(-)

o kanji.patch (5/11)
japanese kanji character support for PC98 console.

drivers/char/console_macros.h | 10 +
drivers/char/vt.c | 393 +++++++++++++++++++++++++++++++++++------
drivers/video/console/Kconfig | 4
include/linux/console_struct.h | 12 +
include/linux/consolemap.h | 1
5 files changed, 369 insertions(+), 51 deletions(-)

o kconfig.patch (6/11)
Add selection for CONFIG_X86_PC9800.

arch/i386/Kconfig | 10 ++++++++--
1 files changed, 8 insertions(+), 2 deletions(-)

o network_card.patch (7/11)
C-bus(PC98's legacy bus like ISA) network cards support.

drivers/net/8390.h | 3
drivers/net/Makefile.lib | 1
drivers/net/ne2k_cbus.h | 481 +++++++++++++++++++++++++
drivers/net/Kconfig | 55 ++
drivers/net/Space.c | 2
drivers/net/3c509.c | 44 +-
drivers/net/Makefile | 1
drivers/net/at1700.c | 120 +++++-
drivers/net/ne2k_cbus.c | 879 +++++++++++++++++++++++++++++++++++++++++++++++
9 files changed, 1557 insertions(+), 29 deletions(-)

o parport.patch (8/11)
Parallel port support.

drivers/parport/parport_pc.c | 28 +++++++++++++++++++++++++++-
1 files changed, 27 insertions(+), 1 deletion(-)

o pci.patch (9/11)
Small changes for PCI support.

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

o pcmcia.patch (10/11)
Small change for PCMCIA (16bits) support.

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

o scsi.patch (11/11)
SCSI host adapter support.

drivers/scsi/Kconfig | 5
drivers/scsi/Makefile | 1
drivers/scsi/pc980155.c | 299 +++++++++++++++++++++++++++++++++++++++++++++++
drivers/scsi/pc980155.h | 52 ++++++++
drivers/scsi/scsi_pc98.c | 2
drivers/scsi/sd.c | 9 +
drivers/scsi/wd33c93.c | 49 +++----
drivers/scsi/wd33c93.h | 7 -
8 files changed, 398 insertions(+), 26 deletions(-)


Osamu Tomita <[email protected]>


2003-03-16 00:52:36

by Osamu Tomita

[permalink] [raw]
Subject: Complete support PC-9800 for 2.5.64-ac4 (1/11) console

This is the patch to support NEC PC-9800 subarchitecture
against 2.5.64-ac4. (1/11)

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.

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.64-ac1/drivers/char/vt.c linux98-2.5.64-ac1/drivers/char/vt.c
--- linux-2.5.64-ac1/drivers/char/vt.c 2003-03-07 08:52:02.000000000 +0900
+++ linux98-2.5.64-ac1/drivers/char/vt.c 2003-03-07 11:00:07.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;
@@ -736,7 +751,7 @@
if (err)
return err;

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

@@ -1261,6 +1276,10 @@
/* console_sem is held */
static void setterm_command(int currcons)
{
+ if (sw->con_setterm_command
+ && sw->con_setterm_command(vc_cons[currcons].d))
+ return;
+
switch(par[0]) {
case 1: /* set color for underline mode */
if (can_do_color && par[1] < 16) {
@@ -2427,9 +2446,17 @@
vc_cons[currcons].d->vc_palette[k++] = default_grn[j] ;
vc_cons[currcons].d->vc_palette[k++] = default_blu[j] ;
}
- def_color = 0x07; /* white */
- ulcolor = 0x0f; /* bold white */
- halfcolor = 0x08; /* grey */
+ if (pc98) {
+ def_color = 0x07; /* white */
+ def_attr = 0xE1;
+ ul_attr = 0x08; /* underline */
+ half_attr = 0x00; /* ignore half color */
+ bold_attr = 0xC1; /* yellow */
+ } else {
+ def_color = 0x07; /* white */
+ ulcolor = 0x0f; /* bold white */
+ halfcolor = 0x08; /* grey */
+ }
init_waitqueue_head(&vt_cons[currcons]->paste_wait);
reset_terminal(currcons, do_clear);
}
@@ -2470,7 +2497,12 @@
vt_cons[currcons] = (struct vt_struct *)
alloc_bootmem(sizeof(struct vt_struct));
visual_init(currcons, 1);
+#if defined(CONFIG_X86_PC9800) || defined(CONFIG_FB)
+ screenbuf
+ = (unsigned short *) alloc_bootmem(screenbuf_size * 2);
+#else
screenbuf = (unsigned short *) alloc_bootmem(screenbuf_size);
+#endif
kmalloced = 0;
vc_init(currcons, video_num_lines, video_num_columns,
currcons || !sw->con_save_screen);
@@ -2973,9 +3005,12 @@
/* used by selection */
u16 screen_glyph(int currcons, int offset)
{
- u16 w = scr_readw(screenpos(currcons, offset, 1));
+ vram_char_t w = scr_readw(screenpos(currcons, offset, 1));
u16 c = w & 0xff;

+ if (pc98)
+ return ((u16)(w >> 16) & 0xff00) | c;
+
if (w & hi_font_mask)
c |= 0x100;
return c;
@@ -3037,8 +3072,10 @@
EXPORT_SYMBOL(default_red);
EXPORT_SYMBOL(default_grn);
EXPORT_SYMBOL(default_blu);
+#ifndef CONFIG_X86_PC9800
EXPORT_SYMBOL(video_font_height);
EXPORT_SYMBOL(video_scan_lines);
+#endif
EXPORT_SYMBOL(vc_cons_allocated);
EXPORT_SYMBOL(update_region);
EXPORT_SYMBOL(redraw_screen);
diff -Nru linux/drivers/char/vt_ioctl.c linux98/drivers/char/vt_ioctl.c
--- linux/drivers/char/vt_ioctl.c 2002-12-10 11:46:13.000000000 +0900
+++ linux98/drivers/char/vt_ioctl.c 2002-12-16 13:15:34.000000000 +0900
@@ -63,9 +63,11 @@
asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int on);
#endif

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

2003-03-16 00:54:12

by Osamu Tomita

[permalink] [raw]
Subject: Complete support PC-9800 for 2.5.64-ac4 (3/11) DMA

This is the patch to support NEC PC-9800 subarchitecture
against 2.5.64-ac4. (3/11)

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

diff -Nru linux/include/asm-i386/dma.h linux98/include/asm-i386/dma.h
--- linux/include/asm-i386/dma.h 2002-07-21 04:52:59.000000000 +0900
+++ linux98/include/asm-i386/dma.h 2002-08-17 22:15:06.000000000 +0900
@@ -10,6 +10,9 @@

#include <linux/config.h>
#include <linux/spinlock.h> /* And spinlocks */
+#ifdef CONFIG_X86_PC9800
+#include <asm/pc9800_dma.h>
+#else /* !CONFIG_X86_PC9800 */
#include <asm/io.h> /* need byte IO */
#include <linux/delay.h>

@@ -72,8 +75,10 @@

#define MAX_DMA_CHANNELS 8

+#ifndef CONFIG_X86_PC9800
/* The maximum address that we can perform a DMA transfer to on this platform */
#define MAX_DMA_ADDRESS (PAGE_OFFSET+0x1000000)
+#endif

/* 8237 DMA controllers */
#define IO_DMA1_BASE 0x00 /* 8 bit slave DMA, channels 0..3 */
@@ -295,4 +300,6 @@
#define isa_dma_bridge_buggy (0)
#endif

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

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

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

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


2003-03-16 00:55:02

by Osamu Tomita

[permalink] [raw]
Subject: Complete support PC-9800 for 2.5.64-ac4 (4/11) IDE

This is the patch to support NEC PC-9800 subarchitecture
against 2.5.64-ac4. (4/11)

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.

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.64-ac4/drivers/ide/ide-probe.c linux98-2.5.64-ac4/drivers/ide/ide-probe.c
--- linux-2.5.64-ac4/drivers/ide/ide-probe.c 2003-03-15 01:15:41.000000000 +0900
+++ linux98-2.5.64-ac4/drivers/ide/ide-probe.c 2003-03-15 01:42:31.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) {
@@ -1158,7 +1163,7 @@
/* all CPUs; safe now that hwif->hwgroup is set up */
spin_unlock_irqrestore(&ide_lock, flags);

-#if !defined(__mc68000__) && !defined(CONFIG_APUS) && !defined(__sparc__)
+#if !defined(__mc68000__) && !defined(CONFIG_APUS) && !defined(__sparc__) && !defined(CONFIG_X86_PC9800)
printk("%s at 0x%03lx-0x%03lx,0x%03lx on irq %d", hwif->name,
hwif->io_ports[IDE_DATA_OFFSET],
hwif->io_ports[IDE_DATA_OFFSET]+7,
@@ -1168,6 +1173,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.64-ac3/drivers/ide/ide.c linux98-2.5.64-ac3/drivers/ide/ide.c
--- linux-2.5.64-ac3/drivers/ide/ide.c 2003-03-08 12:13:46.000000000 +0900
+++ linux98-2.5.64-ac3/drivers/ide/ide.c 2003-03-08 12:29:29.000000000 +0900
@@ -549,7 +549,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);
}
}
}
@@ -2089,6 +2090,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-16 00:53:16

by Osamu Tomita

[permalink] [raw]
Subject: Complete support PC-9800 for 2.5.64-ac4 (2/11) misc core

This is the patch to support NEC PC-9800 subarchitecture
against 2.5.64-ac4. (2/11)

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.

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/include/linux/kernel.h linux98/include/linux/kernel.h
--- linux/include/linux/kernel.h 2003-01-14 14:58:03.000000000 +0900
+++ linux98/include/linux/kernel.h 2003-01-14 23:11:42.000000000 +0900
@@ -224,4 +224,10 @@
#define __FUNCTION__ (__func__)
#endif

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

2003-03-16 00:57:21

by Osamu Tomita

[permalink] [raw]
Subject: Complete support PC-9800 for 2.5.64-ac4 (6/11) Kconfig

This is the patch to support NEC PC-9800 subarchitecture
against 2.5.64-ac4. (6/11)

Add selection CONFIG_X86_PC9800.

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-16 01:01:57

by Osamu Tomita

[permalink] [raw]
Subject: Complete support PC-9800 for 2.5.64-ac4 (7/11) NIC

This is the patch to support NEC PC-9800 subarchitecture
against 2.5.64-ac4. (7/11)

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

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-16 00:56:47

by Osamu Tomita

[permalink] [raw]
Subject: Complete support PC-9800 for 2.5.64-ac4 (5/11) kanji

This is the patch to support NEC PC-9800 subarchitecture
against 2.5.64-ac4. (5/11)

Add japanese kanji character support to PC98 console.

diff -Nru linux/drivers/char/console_macros.h linux98/drivers/char/console_macros.h
--- linux/drivers/char/console_macros.h 2003-03-14 14:13:59.000000000 +0900
+++ linux98/drivers/char/console_macros.h 2003-03-14 14:15:10.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-14 14:13:59.000000000 +0900
+++ linux98/drivers/char/vt.c 2003-03-14 14:15:10.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)
{
@@ -1100,6 +1123,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;
@@ -1108,6 +1134,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;
@@ -1116,6 +1145,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;
@@ -1329,6 +1361,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 */
}
}

@@ -1406,8 +1454,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()) */
@@ -1417,9 +1483,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;
@@ -1461,6 +1536,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)
@@ -1503,11 +1584,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:
@@ -1564,6 +1651,11 @@
case ')':
vc_state = ESsetG1;
return;
+#ifdef CONFIG_KANJI
+ case '$':
+ vc_state = ESsetJIS;
+ return;
+#endif
case '#':
vc_state = EShash;
return;
@@ -1813,8 +1905,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:
@@ -1826,10 +1935,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;
}
@@ -1861,7 +2011,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;
@@ -1918,48 +2068,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
@@ -1976,43 +2229,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;
@@ -2020,6 +2301,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/drivers/video/console/Kconfig linux98/drivers/video/console/Kconfig
--- linux/drivers/video/console/Kconfig 2003-03-14 14:13:59.000000000 +0900
+++ linux98/drivers/video/console/Kconfig 2003-03-14 14:15:10.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-14 14:13:59.000000000 +0900
+++ linux98/include/linux/console_struct.h 2003-03-14 14:15:10.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-16 01:02:29

by Osamu Tomita

[permalink] [raw]
Subject: Complete support PC-9800 for 2.5.64-ac4 (8/11) parport

This is the patch to support NEC PC-9800 subarchitecture
against 2.5.64-ac4. (8/11)

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

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-16 01:06:32

by Osamu Tomita

[permalink] [raw]
Subject: Complete support PC-9800 for 2.5.64-ac4 (11/11) SCSI

This is the patch to support NEC PC-9800 subarchitecture
against 2.5.64-ac4. (11/11)

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.

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/drivers/scsi/sd.c linux98/drivers/scsi/sd.c
--- linux/drivers/scsi/sd.c 2003-03-05 12:29:32.000000000 +0900
+++ linux98/drivers/scsi/sd.c 2003-03-08 11:13:28.000000000 +0900
@@ -485,6 +485,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-16 01:03:25

by Osamu Tomita

[permalink] [raw]
Subject: Complete support PC-9800 for 2.5.64-ac4 (9/11) PCI

This is the patch to support NEC PC-9800 subarchitecture
against 2.5.64-ac4. (9/11)

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

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

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

static struct irq_routing_table *pirq_table;

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

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

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

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

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

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

void pcibios_config_init(void);

2003-03-16 01:04:16

by Osamu Tomita

[permalink] [raw]
Subject: Complete support PC-9800 for 2.5.64-ac4 (10/11) PCMCIA

This is the patch to support NEC PC-9800 subarchitecture
against 2.5.64-ac4. (10/11)

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

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-16 17:36:37

by James Bottomley

[permalink] [raw]
Subject: Re: Complete support PC-9800 for 2.5.64-ac4 (11/11) SCSI

On Sat, 2003-03-15 at 19:15, Osamu Tomita wrote:
> This is the patch to support NEC PC-9800 subarchitecture
> against 2.5.64-ac4. (11/11)
>
> 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.

I suppose the first thing to point out is that it would be helpful if
you could send this to [email protected]. Although most SCSI
people also read linux-kernel, it is easy to lose things in the noise.

> diff -Nru linux/drivers/scsi/sd.c linux98/drivers/scsi/sd.c
> --- linux/drivers/scsi/sd.c 2003-03-05 12:29:32.000000000 +0900
> +++ linux98/drivers/scsi/sd.c 2003-03-08 11:13:28.000000000 +0900
> @@ -485,6 +485,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))

You already have the pc98_bios_param as part of your local driver. Why
do you need this in addition?

[...]
> 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);
> }
>
[...]
> /* 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;
>

This really doesn't look right. For non PIO (which is all drivers apart
from yours), they expect to dereference SASR to get the port number (as
an unsigned char). If you remove the dereference, don't they all break?

Perhaps the better thing to do is to make your driver use an unsigned
int *, so the dereference works in all cases.

James

2003-03-16 18:25:49

by Geert Uytterhoeven

[permalink] [raw]
Subject: Re: Complete support PC-9800 for 2.5.64-ac4 (11/11) SCSI

On 16 Mar 2003, James Bottomley wrote:
> On Sat, 2003-03-15 at 19:15, Osamu Tomita wrote:
> > /* 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;
> >
>
> This really doesn't look right. For non PIO (which is all drivers apart
> from yours), they expect to dereference SASR to get the port number (as
> an unsigned char). If you remove the dereference, don't they all break?

On m68k and MIPS, we do not derefence SASR to get the port number, SASR _is_
the MMIO pointer to the 8-bit SASR register. Hence you access the register by
dereferencing the pointer.

> Perhaps the better thing to do is to make your driver use an unsigned
> int *, so the dereference works in all cases.

Actually, it was my suggestion to remove the dereference for PIO accesses. In
that case SASR contains the I/O port register.

Gr{oetje,eeting}s,

Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- [email protected]

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds

2003-03-16 18:44:08

by James Bottomley

[permalink] [raw]
Subject: Re: Complete support PC-9800 for 2.5.64-ac4 (11/11) SCSI

On Sun, 2003-03-16 at 12:36, Geert Uytterhoeven wrote:
> Actually, it was my suggestion to remove the dereference for PIO accesses. In
> that case SASR contains the I/O port register.

There's still something wrong with the implementation in this patch.
For non PIO SASR is defined as volatile unsigned char *SASR. Its access
has gone from being outb(n, *regs.SASR) to outb(n, regs.SASR). What
expansion can outb have on m68k and MIPS that makes this change
idempotent?

James


2003-03-16 19:49:26

by Geert Uytterhoeven

[permalink] [raw]
Subject: Re: Complete support PC-9800 for 2.5.64-ac4 (11/11) SCSI

On 16 Mar 2003, James Bottomley wrote:
> On Sun, 2003-03-16 at 12:36, Geert Uytterhoeven wrote:
> > Actually, it was my suggestion to remove the dereference for PIO accesses. In
> > that case SASR contains the I/O port register.
>
> There's still something wrong with the implementation in this patch.
> For non PIO SASR is defined as volatile unsigned char *SASR. Its access
> has gone from being outb(n, *regs.SASR) to outb(n, regs.SASR). What
> expansion can outb have on m68k and MIPS that makes this change
> idempotent?

outb() and friends are only used if CONFIG_WD33C93_PIO is set. In all other
cases, it uses the old implementation, e.g. `*regs.SASR = reg_num'.

Gr{oetje,eeting}s,

Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- [email protected]

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds

2003-03-16 22:16:01

by James Bottomley

[permalink] [raw]
Subject: Re: Complete support PC-9800 for 2.5.64-ac4 (11/11) SCSI

On Sun, 2003-03-16 at 14:00, Geert Uytterhoeven wrote:
> On 16 Mar 2003, James Bottomley wrote:
> > On Sun, 2003-03-16 at 12:36, Geert Uytterhoeven wrote:
> > > Actually, it was my suggestion to remove the dereference for PIO accesses. In
> > > that case SASR contains the I/O port register.
> >
> > There's still something wrong with the implementation in this patch.
> > For non PIO SASR is defined as volatile unsigned char *SASR. Its access
> > has gone from being outb(n, *regs.SASR) to outb(n, regs.SASR). What
> > expansion can outb have on m68k and MIPS that makes this change
> > idempotent?
>
> outb() and friends are only used if CONFIG_WD33C93_PIO is set. In all other
> cases, it uses the old implementation, e.g. `*regs.SASR = reg_num'.

Ah, OK, I see what it's doing. Instead of having a single redefine of
wd33c93_outb to be either outb or readb etc, it has a whole chunk of
code in wd33c93.c that #ifdef's for this.

Perhaps, while you're cleaning this up, you'd like to move this into the
header? Shouldn't it also be using readb/writeb instead of just direct
memory accesses?

James


2003-03-17 01:11:50

by Osamu Tomita

[permalink] [raw]
Subject: RE: Complete support PC-9800 for 2.5.64-ac4 (11/11) SCSI

Thanks for the comments.

-----Original Message-----
From: James Bottomley
To: Osamu Tomita
Cc: Linux Kernel Mailing List; Alan Cox; Christoph Hellwig; Geert
Uytterhoeven
Sent: 2003/03/17 2:47
Subject: Re: Complete support PC-9800 for 2.5.64-ac4 (11/11) SCSI

> On Sat, 2003-03-15 at 19:15, Osamu Tomita wrote:
> > This is the patch to support NEC PC-9800 subarchitecture
> > against 2.5.64-ac4. (11/11)
>
> > 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.
>
> I suppose the first thing to point out is that it would be helpful if
> you could send this to [email protected]. Although most SCSI
> people also read linux-kernel, it is easy to lose things in the noise.
I see.

> > diff -Nru linux/drivers/scsi/sd.c linux98/drivers/scsi/sd.c
> > --- linux/drivers/scsi/sd.c 2003-03-05 12:29:32.000000000 +0900
> > +++ linux98/drivers/scsi/sd.c 2003-03-08 11:13:28.000000000 +0900
> > @@ -485,6 +485,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))
>
> You already have the pc98_bios_param as part of your local driver. Why
> do you need this in addition?
We need this for other SCSI cards not only wd33c93. For example, we
have cards for PC98 that use aha152x, aic7xxx, advansys and sym53c8xx
drivers.
PC98 architecture has own boot selector and can boot any of 16 partitions
per 1 drive. The partition table conatins C/H/S geometry. And we can
assign non zero head or sector. Boot selector reads the partition table
and call BIOS by C/H/S parameters on boottime. If geometry is not mach
to BIOS, cannot boot from the partition created on linux.

> [...]
> > 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);
> > }
> >
> [...]
> > /* 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;
> >
>
> This really doesn't look right. For non PIO (which is all drivers apart
> from yours), they expect to dereference SASR to get the port number (as
> an unsigned char). If you remove the dereference, don't they all break?
>
> Perhaps the better thing to do is to make your driver use an unsigned
> int *, so the dereference works in all cases.
>
> James
I supposed, I use this patch with "#ifdef CONFIG_WD33C93_PIO" in
wd33c98.c.

Regards,
Osamu Tomita

2003-03-17 10:15:25

by Geert Uytterhoeven

[permalink] [raw]
Subject: Re: Complete support PC-9800 for 2.5.64-ac4 (11/11) SCSI

On 16 Mar 2003, James Bottomley wrote:
> On Sun, 2003-03-16 at 14:00, Geert Uytterhoeven wrote:
> > On 16 Mar 2003, James Bottomley wrote:
> > > On Sun, 2003-03-16 at 12:36, Geert Uytterhoeven wrote:
> > > > Actually, it was my suggestion to remove the dereference for PIO accesses. In
> > > > that case SASR contains the I/O port register.
> > >
> > > There's still something wrong with the implementation in this patch.
> > > For non PIO SASR is defined as volatile unsigned char *SASR. Its access
> > > has gone from being outb(n, *regs.SASR) to outb(n, regs.SASR). What
> > > expansion can outb have on m68k and MIPS that makes this change
> > > idempotent?
> >
> > outb() and friends are only used if CONFIG_WD33C93_PIO is set. In all other
> > cases, it uses the old implementation, e.g. `*regs.SASR = reg_num'.
>
> Ah, OK, I see what it's doing. Instead of having a single redefine of
> wd33c93_outb to be either outb or readb etc, it has a whole chunk of
> code in wd33c93.c that #ifdef's for this.
>
> Perhaps, while you're cleaning this up, you'd like to move this into the
> header? Shouldn't it also be using readb/writeb instead of just direct
> memory accesses?

No, readb() and friends are not defined on machines that don't have PCI. None
of the MMIO wd33c93 drivers are PCI.

However, it's fine for me to use in_8(addr) and out_8(addr,b) (cfr.
include/asm-m68k/raw_io.h) inside #if defined(__mc68000__) ||
defined(CONFIG_APUS).

On MIPS, it looks like you can use readb() and writeb(), since MIPS is less
picky than m68k about not defining PCI access primitives on machines without
PCI.

Gr{oetje,eeting}s,

Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- [email protected]

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds