Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
b1d53f0c
Commit
b1d53f0c
authored
Jun 17, 2004
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
This removes the files orphaned by the earlier PC9800 removal
parent
bffc8f71
Changes
46
Show whitespace changes
Inline
Side-by-side
Showing
46 changed files
with
0 additions
and
14234 deletions
+0
-14234
arch/i386/boot98/Makefile
arch/i386/boot98/Makefile
+0
-102
arch/i386/boot98/bootsect.S
arch/i386/boot98/bootsect.S
+0
-397
arch/i386/boot98/install.sh
arch/i386/boot98/install.sh
+0
-40
arch/i386/boot98/mtools.conf.in
arch/i386/boot98/mtools.conf.in
+0
-17
arch/i386/boot98/setup.S
arch/i386/boot98/setup.S
+0
-876
arch/i386/boot98/video.S
arch/i386/boot98/video.S
+0
-262
arch/i386/mach-pc9800/Makefile
arch/i386/mach-pc9800/Makefile
+0
-5
arch/i386/mach-pc9800/setup.c
arch/i386/mach-pc9800/setup.c
+0
-117
arch/i386/mach-pc9800/std_resources.c
arch/i386/mach-pc9800/std_resources.c
+0
-195
arch/i386/mach-pc9800/topology.c
arch/i386/mach-pc9800/topology.c
+0
-44
drivers/block/floppy98.c
drivers/block/floppy98.c
+0
-4682
drivers/char/lp_old98.c
drivers/char/lp_old98.c
+0
-537
drivers/char/upd4990a.c
drivers/char/upd4990a.c
+0
-432
drivers/ide/legacy/hd98.c
drivers/ide/legacy/hd98.c
+0
-883
drivers/ide/legacy/pc9800.c
drivers/ide/legacy/pc9800.c
+0
-84
drivers/input/keyboard/98kbd.c
drivers/input/keyboard/98kbd.c
+0
-391
drivers/input/misc/98spkr.c
drivers/input/misc/98spkr.c
+0
-96
drivers/input/mouse/98busmouse.c
drivers/input/mouse/98busmouse.c
+0
-197
drivers/input/serio/98kbd-io.c
drivers/input/serio/98kbd-io.c
+0
-179
drivers/net/ne2k_cbus.c
drivers/net/ne2k_cbus.c
+0
-887
drivers/net/ne2k_cbus.h
drivers/net/ne2k_cbus.h
+0
-481
drivers/scsi/pc980155.c
drivers/scsi/pc980155.c
+0
-299
drivers/scsi/pc980155.h
drivers/scsi/pc980155.h
+0
-52
drivers/scsi/scsi_pc98.c
drivers/scsi/scsi_pc98.c
+0
-69
drivers/serial/serial98.c
drivers/serial/serial98.c
+0
-1120
fs/partitions/nec98.c
fs/partitions/nec98.c
+0
-188
fs/partitions/nec98.h
fs/partitions/nec98.h
+0
-10
include/asm-i386/mach-pc9800/apm.h
include/asm-i386/mach-pc9800/apm.h
+0
-82
include/asm-i386/mach-pc9800/bios_ebda.h
include/asm-i386/mach-pc9800/bios_ebda.h
+0
-14
include/asm-i386/mach-pc9800/do_timer.h
include/asm-i386/mach-pc9800/do_timer.h
+0
-82
include/asm-i386/mach-pc9800/io_ports.h
include/asm-i386/mach-pc9800/io_ports.h
+0
-30
include/asm-i386/mach-pc9800/irq_vectors.h
include/asm-i386/mach-pc9800/irq_vectors.h
+0
-99
include/asm-i386/mach-pc9800/mach_reboot.h
include/asm-i386/mach-pc9800/mach_reboot.h
+0
-21
include/asm-i386/mach-pc9800/mach_time.h
include/asm-i386/mach-pc9800/mach_time.h
+0
-100
include/asm-i386/mach-pc9800/mach_timer.h
include/asm-i386/mach-pc9800/mach_timer.h
+0
-31
include/asm-i386/mach-pc9800/mach_traps.h
include/asm-i386/mach-pc9800/mach_traps.h
+0
-27
include/asm-i386/mach-pc9800/mach_wakecpu.h
include/asm-i386/mach-pc9800/mach_wakecpu.h
+0
-45
include/asm-i386/mach-pc9800/pci-functions.h
include/asm-i386/mach-pc9800/pci-functions.h
+0
-20
include/asm-i386/mach-pc9800/setup_arch_post.h
include/asm-i386/mach-pc9800/setup_arch_post.h
+0
-29
include/asm-i386/mach-pc9800/setup_arch_pre.h
include/asm-i386/mach-pc9800/setup_arch_pre.h
+0
-36
include/asm-i386/mach-pc9800/smpboot_hooks.h
include/asm-i386/mach-pc9800/smpboot_hooks.h
+0
-52
include/asm-i386/pc9800.h
include/asm-i386/pc9800.h
+0
-27
include/asm-i386/pc9800_sca.h
include/asm-i386/pc9800_sca.h
+0
-25
sound/isa/cs423x/pc98.c
sound/isa/cs423x/pc98.c
+0
-438
sound/isa/cs423x/pc9801_118_magic.h
sound/isa/cs423x/pc9801_118_magic.h
+0
-411
sound/isa/cs423x/sound_pc9800.h
sound/isa/cs423x/sound_pc9800.h
+0
-23
No files found.
arch/i386/boot98/Makefile
deleted
100644 → 0
View file @
bffc8f71
#
# arch/i386/boot/Makefile
#
# This file is subject to the terms and conditions of the GNU General Public
# License. See the file "COPYING" in the main directory of this archive
# for more details.
#
# Copyright (C) 1994 by Linus Torvalds
#
# ROOT_DEV specifies the default root-device when making the image.
# This can be either FLOPPY, CURRENT, /dev/xxxx or empty, in which case
# the default of FLOPPY is used by 'build'.
ROOT_DEV
:=
CURRENT
# If you want to preset the SVGA mode, uncomment the next line and
# set SVGA_MODE to whatever number you want.
# Set it to -DSVGA_MODE=NORMAL_VGA if you just want the EGA/VGA mode.
# The number is the same as you would ordinarily press at bootup.
SVGA_MODE
:=
-DSVGA_MODE
=
NORMAL_VGA
# If you want the RAM disk device, define this to be the size in blocks.
#RAMDISK := -DRAMDISK=512
targets
:=
vmlinux.bin bootsect bootsect.o setup setup.o
\
zImage bzImage
subdir-
:=
compressed
host-progs
:=
tools/build
# ---------------------------------------------------------------------------
$(obj)/zImage
:
IMAGE_OFFSET := 0x1000
$(obj)/zImage
:
EXTRA_AFLAGS := -traditional $(SVGA_MODE) $(RAMDISK)
$(obj)/bzImage
:
IMAGE_OFFSET := 0x100000
$(obj)/bzImage
:
EXTRA_AFLAGS := -traditional $(SVGA_MODE) $(RAMDISK) -D__BIG_KERNEL__
$(obj)/bzImage
:
BUILDFLAGS := -b
quiet_cmd_image
=
BUILD
$@
cmd_image
=
$(obj)
/tools/build
$(BUILDFLAGS)
$(obj)
/bootsect
$(obj)
/setup
\
$(obj)
/vmlinux.bin
$(ROOT_DEV)
>
$@
$(obj)/zImage $(obj)/bzImage
:
$(obj)/bootsect $(obj)/setup
\
$(obj)/vmlinux.bin $(obj)/tools/build FORCE
$(
call
if_changed,image
)
@
echo
'Kernel: $@ is ready'
$(obj)/vmlinux.bin
:
$(obj)/compressed/vmlinux FORCE
$(
call
if_changed,objcopy
)
LDFLAGS_bootsect
:=
-Ttext
0x0
-s
--oformat
binary
LDFLAGS_setup
:=
-Ttext
0x0
-s
--oformat
binary
-e
begtext
$(obj)/setup $(obj)/bootsect
:
%: %.o FORCE
$(
call
if_changed,ld
)
$(obj)/compressed/vmlinux
:
FORCE
$(Q)$(MAKE)
$(build)
=
$(obj)
/compressed
IMAGE_OFFSET
=
$(IMAGE_OFFSET)
$@
# Set this if you want to pass append arguments to the zdisk/fdimage kernel
FDARGS
=
$(obj)/mtools.conf
:
$(src)/mtools.conf.in
sed
-e
's|@OBJ@|
$(obj)
|g'
<
$<
>
$@
# This requires write access to /dev/fd0
zdisk
:
$(BOOTIMAGE) $(obj)/mtools.conf
MTOOLSRC
=
$(obj)
/mtools.conf mformat a:
;
sync
syslinux /dev/fd0
;
sync
echo
'default linux
$(FDARGS)
'
|
\
MTOOLSRC
=
$(src)
/mtools.conf mcopy - a:syslinux.cfg
MTOOLSRC
=
$(obj)
/mtools.conf mcopy
$(BOOTIMAGE)
a:linux
;
sync
# These require being root or having syslinux 2.02 or higher installed
fdimage fdimage144
:
$(BOOTIMAGE) $(obj)/mtools.conf
dd
if
=
/dev/zero
of
=
$(obj)
/fdimage
bs
=
1024
count
=
1440
MTOOLSRC
=
$(obj)
/mtools.conf mformat v:
;
sync
syslinux
$(obj)
/fdimage
;
sync
echo
'default linux
$(FDARGS)
'
|
\
MTOOLSRC
=
$(obj)
/mtools.conf mcopy - v:syslinux.cfg
MTOOLSRC
=
$(obj)
/mtools.conf mcopy
$(BOOTIMAGE)
v:linux
;
sync
fdimage288
:
$(BOOTIMAGE) $(obj)/mtools.conf
dd
if
=
/dev/zero
of
=
$(obj)
/fdimage
bs
=
1024
count
=
2880
MTOOLSRC
=
$(obj)
/mtools.conf mformat w:
;
sync
syslinux
$(obj)
/fdimage
;
sync
echo
'default linux
$(FDARGS)
'
|
\
MTOOLSRC
=
$(obj)
/mtools.conf mcopy - w:syslinux.cfg
MTOOLSRC
=
$(obj)
/mtools.conf mcopy
$(BOOTIMAGE)
w:linux
;
sync
zlilo
:
$(BOOTIMAGE)
if
[
-f
$(INSTALL_PATH)
/vmlinuz
]
;
then
mv
$(INSTALL_PATH)
/vmlinuz
$(INSTALL_PATH)
/vmlinuz.old
;
fi
if
[
-f
$(INSTALL_PATH)
/System.map
]
;
then
mv
$(INSTALL_PATH)
/System.map
$(INSTALL_PATH)
/System.old
;
fi
cat
$(BOOTIMAGE)
>
$(INSTALL_PATH)
/vmlinuz
cp
System.map
$(INSTALL_PATH)
/
if
[
-x
/sbin/lilo
]
;
then
/sbin/lilo
;
else
/etc/lilo/install
;
fi
install
:
$(BOOTIMAGE)
sh
$(src)
/install.sh
$(KERNELRELEASE)
$(BOOTIMAGE)
System.map
"
$(INSTALL_PATH)
"
arch/i386/boot98/bootsect.S
deleted
100644 → 0
View file @
bffc8f71
/*
*
bootsect
.
S
-
boot
sector
for
NEC
PC
-
9800
series
*
*
Linux
/
98
project
at
Kyoto
University
Microcomputer
Club
(
KMC
)
*
FUJITA
Norimasa
,
TAKAI
Kousuke
1997
-
1998
*
rewritten
by
TAKAI
Kousuke
(
as86
->
gas
),
Nov
1999
*
*
Based
on
:
*
bootsect
.
S
Copyright
(
C
)
1991
,
1992
Linus
Torvalds
*
modified
by
Drew
Eckhardt
*
modified
by
Bruce
Evans
(
bde
)
*
*
bootsect
.
S
is
loaded
at
0x1FC00
or
0x1FE00
by
the
bios
-
startup
routines
,
*
and
moves
itself
out
of
the
way
to
address
0x90000
,
and
jumps
there
.
*
*
It
then
loads
'setup'
directly
after
itself
(
0x90200
),
and
the
system
*
at
0x10000
,
using
BIOS
interrupts
.
*
*
NOTE
!
currently
system
is
at
most
(
8
*
65536
-
4096
)
bytes
long
.
This
should
*
be
no
problem
,
even
in
the
future
.
I
want
to
keep
it
simple
.
This
508
kB
*
kernel
size
should
be
enough
,
especially
as
this
doesn
't contain the
*
buffer
cache
as
in
minix
(
and
especially
now
that
the
kernel
is
*
compressed
:
-)
*
*
The
loader
has
been
made
as
simple
as
possible
,
and
continuous
*
read
errors
will
result
in
a
unbreakable
loop
.
Reboot
by
hand
.
It
*
loads
pretty
fast
by
getting
whole
tracks
at
a
time
whenever
possible
.
*/
#include <linux/config.h> /* for CONFIG_ROOT_RDONLY */
#include <asm/boot.h>
SETUPSECTS
=
4
/*
default
nr
of
setup
-
sectors
*/
BOOTSEG
=
0x1FC0
/*
original
address
of
boot
-
sector
*/
INITSEG
=
DEF_INITSEG
/*
we
move
boot
here
-
out
of
the
way
*/
SETUPSEG
=
DEF_SETUPSEG
/*
setup
starts
here
*/
SYSSEG
=
DEF_SYSSEG
/*
system
loaded
at
0x10000
(
65536
)
*/
SYSSIZE
=
DEF_SYSSIZE
/*
system
size
:
#
of
16
-
byte
clicks
*/
/
*
to
be
loaded
*/
ROOT_DEV
=
0
/*
ROOT_DEV
is
now
written
by
"build"
*/
SWAP_DEV
=
0
/*
SWAP_DEV
is
now
written
by
"build"
*/
#ifndef SVGA_MODE
#define SVGA_MODE ASK_VGA
#endif
#ifndef RAMDISK
#define RAMDISK 0
#endif
#ifndef ROOT_RDONLY
#define ROOT_RDONLY 1
#endif
/*
normal
/
hireso
text
VRAM
segments
*/
#define NORMAL_TEXT 0xa000
#define HIRESO_TEXT 0xe000
/*
bios
work
area
addresses
*/
#define EXPMMSZ 0x0401
#define BIOS_FLAG 0x0501
#define DISK_BOOT 0x0584
.
code16
.
text
.
global
_start
_start
:
#if 0 /* hook for debugger, harmless unless BIOS is fussy (old HP) */
int
$
0x3
#endif
jmp
real_start
.
ascii
"Linux 98"
.
word
0
real_start
:
xorw
%
di
,
%
di
/*
%
di
=
0
*/
movw
%
di
,
%
ss
/*
%
ss
=
0
*/
movw
$
0x03F0
,
%
sp
pushw
%
cx
/*
for
hint
*/
movw
$
0x0A00
,
%
ax
/*
normal
mode
defaults
(
80
x25
)
*/
testb
$
0x08
,
%
ss
:
BIOS_FLAG
/*
check
hi
-
reso
bit
*/
jnz
set_crt_mode
/*
*
Hi
-
Reso
(
high
-
resolution
)
machine
.
*
*
Some
hi
-
reso
machines
have
no
RAMs
on
bank
8
/
A
(
0x080000
-
0x0BFFFF
)
.
*
On
such
machines
we
get
two
RAM
banks
from
top
of
protect
menory
and
*
map
them
on
bank
8
/
A
.
*
These
work
-
around
must
be
done
before
moving
myself
on
INITSEG
(
0x090000
-)
.
*/
movw
$
(
HIRESO_TEXT
>>
8
),
%
cs
:
(
vram
+
1
)
/*
text
VRAM
segment
*/
/
*
set
memory
window
*/
movb
$
0x08
,
%
al
outb
%
al
,
$
0x91
/*
map
native
RAM
(
if
any
)
*/
movb
$
0x0A
,
%
al
outb
%
al
,
$
0x93
/
*
check
bank
ram
A
*/
pushw
$
0xA500
popw
%
ds
movw
(%
di
),
%
cx
/*
%
si
==
0
from
entry
*/
notw
%
cx
movw
%
cx
,
(%
di
)
movw
$
0x43F
,
%
dx
/*
cache
flush
for
486
and
up
.
*/
movb
$
0xA0
,
%
al
outb
%
al
,
%
dx
cmpw
%
cx
,
(%
di
)
je
hireso_done
/
*
*
Write
test
failed
; we have no native RAM on 080000h - 0BFFFFh.
*
Take
256
KB
of
RAM
from
top
of
protected
memory
.
*/
movb
%
ss
:
EXPMMSZ
,
%
al
subb
$
2
,
%
al
/*
reduce
2
x
128
KB
*/
movb
%
al
,
%
ss
:
EXPMMSZ
addb
%
al
,
%
al
addb
$
0x10
,
%
al
outb
%
al
,
$
0x91
addb
$
2
,
%
al
outb
%
al
,
$
0x93
hireso_done
:
movb
$
0x10
,
%
al
/*
CRT
mode
80
x31
,
%
ah
still
0
Ah
*/
set_crt_mode
:
int
$
0x18
/*
set
CRT
mode
*/
movb
$
0x0C
,
%
ah
/*
turn
on
text
displaying
*/
int
$
0x18
xorw
%
dx
,
%
dx
/*
position
cursor
to
home
*/
movb
$
0x13
,
%
ah
int
$
0x18
movb
$
0x11
,
%
ah
/*
turn
cursor
displaying
on
*/
int
$
0x18
/
*
move
1
kilobytes
from
[
BOOTSEG
:
0000
h
]
to
[
INITSEG
:
0000
h
]
*/
cld
xorw
%
si
,
%
si
pushw
$INITSEG
popw
%
es
movw
$
512
,
%
cx
/*
%
di
==
0
from
entry
*/
rep
cs
movsw
ljmp
$INITSEG
,
$go
go
:
pushw
%
cs
popw
%
ds
/*
%
ds
=
%
cs
*/
popw
%
dx
/*
%
dh
=
saved
%
ch
passed
from
BIOS
*/
movb
%
ss
:
DISK_BOOT
,
%
al
andb
$
0xf0
,
%
al
/*
%
al
=
Device
Address
*/
movb
$
18
,
%
ch
/*
18
secs
/
track
,
512
b
/
sec
(
1440
KB
)
*/
cmpb
$
0x30
,
%
al
je
try512
cmpb
$
0x90
,
%
al
/*
1
MB
I
/
F
,
1
MB
floppy
*/
je
try1
.2
M
cmpb
$
0xf0
,
%
al
/*
640
KB
I
/
F
,
1
MB
floppy
*/
je
try1
.2
M
movb
$
9
,
%
ch
/*
9
secs
/
track
,
512
b
/
sec
(
720
KB
)
*/
cmpb
$
0x10
,
%
al
/*
1
MB
I
/
F
,
640
KB
floppy
*/
je
try512
cmpb
$
0x70
,
%
al
/*
640
KB
I
/
F
,
640
KB
floppy
*/
jne
error
/*
unknown
device
?
*/
/
*
XXX
:
Does
it
make
sense
to
support
8
secs
/
track
,
512
b
/
sec
(640
KB
)
floppy
?
*/
try512
:
movb
$
2
,
%
cl
/*
512
b
/
sec
*/
lasttry
:
call
tryload
/*
*
Display
error
message
and
halt
*/
error
:
movw
$error_msg
,
%
si
call
print
wait_reboot
:
movb
$
0x0
,
%
ah
int
$
0x18
/*
wait
keyboard
input
*/
1
:
movb
$
0
,
%
al
outb
%
al
,
$
0xF0
/*
reset
CPU
*/
jmp
1
b
/*
just
in
case
...
*/
try1
.
2M
:
cmpb
$2,
%
dh
je
try2HC
movw
$
0x0803
,
%
cx
/*
8
secs
/
track
,
1024
b
/
sec
(
1232
KB
)
*/
call
tryload
movb
$
15
,
%
ch
/*
15
secs
/
track
,
512
b
/
sec
(
1200
KB
)
*/
jmp
try512
try2HC
:
movw
$
0x0F02
,
%
cx
/*
15
secs
/
track
,
512
b
/
sec
(
1200
KB
)
*/
call
tryload
movw
$
0x0803
,
%
cx
/*
8
secs
/
track
,
1024
b
/
sec
(
1232
KB
)
*/
jmp
lasttry
/*
*
Try
to
load
SETUP
and
SYSTEM
provided
geometry
information
in
%
cx
.
*
This
routine
*
will
not
*
return
on
successful
load
...
*/
tryload
:
movw
%
cx
,
sectlen
movb
%
ss
:
DISK_BOOT
,
%
al
movb
$
0x7
,
%
ah
/*
recalibrate
the
drive
*/
int
$
0x1b
jc
error
/*
recalibration
should
succeed
*/
/
*
*
Load
SETUP
into
memory
.
It
is
assumed
that
SETUP
fits
into
*
first
cylinder
(
2
tracks
,
9
KB
on
2
DD
,
15
-
18
KB
on
2
HD
)
.
*/
movb
$
0
,
%
bl
movb
setup_sects
,
%
bh
incb
%
bh
shlw
%
bx
/*
%
bx
=
(
setup_sects
+
1
)
*
512
*/
movw
$
128
,
%
bp
shlw
%
cl
,
%
bp
/*
%
bp
=
<
sector
size
>
*/
subw
%
bp
,
%
bx
/*
length
to
load
*/
movw
$
0x0002
,
%
dx
/*
head
0
,
sector
2
*/
movb
%
cl
,
%
ch
/*
`
N
' for sector address */
movb
$
0
,
%
cl
/*
cylinder
0
*/
pushw
%
cs
popw
%
es
/*
%
es
=
%
cs
(=
INITSEG
)
*/
movb
$
0xd6
,
%
ah
/*
read
,
multi
-
track
,
MFM
*/
int
$
0x1b
/*
load
it
!
*/
jc
read_error
movw
$loading_msg
,
%
si
call
print
movw
$SYSSEG
,
%
ax
movw
%
ax
,
%
es
/*
%
es
=
SYSSEG
*/
/*
*
This
routine
loads
the
system
at
address
0x10000
,
making
sure
*
no
64
kB
boundaries
are
crossed
.
We
try
to
load
it
as
fast
as
*
possible
,
loading
whole
tracks
whenever
we
can
.
*
*
in
:
es
-
starting
address
segment
(
normally
0x1000
)
*/
movb
%
ch
,
%
cl
addb
$
7
,
%
cl
/*
%
cl
=
log2
<
sector_size
>
*/
shrw
%
cl
,
%
bx
/*
%
bx
=
#
of
phys
.
sectors
in
SETUP
*/
addb
%
bl
,
%
dl
/*
%
dl
=
start
sector
#
of
SYSTEM
*/
decb
%
dl
/*
%
dl
is
0
-
based
in
below
loop
*/
rp_read_newseg
:
xorw
%
bp
,
%
bp
/*
=
starting
address
within
segment
*/
#ifdef __BIG_KERNEL__
bootsect_kludge
=
0x220
/*
0x200
(
size
of
bootsector
)
+
0x20
(
offset
*/
lcall
*
bootsect_kludge
/*
of
bootsect_kludge
in
setup
.
S
*/
#else
movw
%
es
,
%
ax
subw
$SYSSEG
,
%
ax
#endif
cmpw
syssize
,
%
ax
ja
boot
/*
done
!
*/
rp_read
:
movb
sectors
,
%
al
addb
%
al
,
%
al
movb
%
al
,
%
ch
/*
#
of
sectors
on
both
surface
*/
subb
%
dl
,
%
al
/*
#
of
sectors
left
on
this
track
*/
movb
$
0
,
%
ah
shlw
%
cl
,
%
ax
/*
#
of
bytes
left
on
this
track
*/
movw
%
ax
,
%
bx
/*
transfer
length
*/
addw
%
bp
,
%
ax
/*
cross
64
K
boundary
?
*/
jnc
1
f
/*
ok
.
*/
jz
1
f
/*
also
ok
.
*/
/
*
*
Oops
,
we
are
crossing
64
K
boundary
...
*
Adjust
transfer
length
to
make
transfer
fit
in
the
boundary
.
*
*
Note
:
sector
size
is
assumed
to
be
a
measure
of
65536
.
*/
xorw
%
bx
,
%
bx
subw
%
bp
,
%
bx
1
:
pushw
%
dx
movw
$dot_msg
,
%
si
/*
give
progress
message
*/
call
print
xchgw
%
ax
,
%
dx
movb
$
0
,
%
ah
divb
sectors
xchgb
%
al
,
%
ah
xchgw
%
ax
,
%
dx
/*
%
dh
=
head
#
/
%
dl
=
sector
#
*/
incb
%
dl
/*
fix
%
dl
to
1
-
based
*/
pushw
%
cx
movw
cylinder
,
%
cx
movb
$
0xd6
,
%
ah
/*
read
,
multi
-
track
,
seek
,
MFM
*/
movb
%
ss
:
DISK_BOOT
,
%
al
int
$
0x1b
popw
%
cx
popw
%
dx
jc
read_error
movw
%
bx
,
%
ax
/*
#
of
bytes
just
read
*/
shrw
%
cl
,
%
ax
/*
%
ax
=
#
of
sectors
just
read
*/
addb
%
al
,
%
dl
/*
advance
sector
#
*/
cmpb
%
ch
,
%
dl
/*
%
ch
=
#
of
sectors
/
cylinder
*/
jb
2
f
incb
cylinder
/*
next
cylinder
*/
xorb
%
dl
,
%
dl
/*
sector
0
*/
2
:
addw
%
bx
,
%
bp
/*
advance
offset
pointer
*/
jnc
rp_read
/
*
offset
pointer
wrapped
; advance segment pointer. */
movw
%
es
,
%
ax
addw
$
0x1000
,
%
ax
movw
%
ax
,
%
es
jmp
rp_read_newseg
read_error
:
ret
boot
:
movw
%
cs
,
%
ax
/*
=
INITSEG
*/
/
*
movw
%
ax
,
%
ds
*/
movw
%
ax
,
%
ss
movw
$
0x4000
,
%
sp
/*
0x4000
is
arbitrary
value
>=
*
length
of
bootsect
+
length
of
*
setup
+
room
for
stack
;
*
PC
-
9800
never
have
BIOS
workareas
*
on
high
memory
.
*/
/*
*
After
that
we
check
which
root
-
device
to
use
.
If
the
device
is
*
not
defined
,
/
dev
/
fd0
(
2
,
0
)
will
be
used
.
*/
cmpw
$
0
,
root_dev
jne
3
f
movb
$
2
,
root_dev
+
1
3
:
/*
*
After
that
(
everything
loaded
),
we
jump
to
the
setup
-
routine
*
loaded
directly
after
the
bootblock
:
*/
ljmp
$SETUPSEG
,
$
0
/*
*
Subroutine
for
print
string
on
console
.
*
%
cs
:
%
si
-
pointer
to
message
*/
print
:
pushaw
pushw
%
ds
pushw
%
es
pushw
%
cs
popw
%
ds
lesw
curpos
,
%
di
/*
%
es
:
%
di
=
current
text
VRAM
addr
.
*/
1
:
xorw
%
ax
,
%
ax
lodsb
testb
%
al
,
%
al
jz
2
f
/*
end
of
string
*/
stosw
/*
character
code
*/
movb
$
0xE1
,
%
es
:
0x2000
-
2
(%
di
)
/*
character
attribute
*/
jmp
1
b
2
:
movw
%
di
,
%
dx
movb
$
0x13
,
%
ah
int
$
0x18
/*
move
cursor
to
current
point
*/
popw
%
es
popw
%
ds
popaw
ret
loading_msg
:
.
string
"Loading"
dot_msg
:
.
string
"."
error_msg
:
.
string
"Read Error!"
.
org
490
curpos
:
.
word
160
/*
current
cursor
position
*/
vram
:
.
word
NORMAL_TEXT
/*
text
VRAM
segment
*/
cylinder
:
.
byte
0
/*
current
cylinder
(
lower
byte
)
*/
sectlen
:
.
byte
0
/*
(
log2
of
<
sector
size
>)
-
7
*/
sectors
:
.
byte
0x0F
/*
default
is
2
HD
(
15
sector
/
track
)
*/
#
XXX
:
This
is
a
fairly
snug
fit
.
.
org
497
setup_sects
:
.
byte
SETUPSECTS
root_flags
:
.
word
ROOT_RDONLY
syssize
:
.
word
SYSSIZE
swap_dev
:
.
word
SWAP_DEV
ram_size
:
.
word
RAMDISK
vid_mode
:
.
word
SVGA_MODE
root_dev
:
.
word
ROOT_DEV
boot_flag
:
.
word
0xAA55
arch/i386/boot98/install.sh
deleted
100644 → 0
View file @
bffc8f71
#!/bin/sh
#
# arch/i386/boot/install.sh
#
# This file is subject to the terms and conditions of the GNU General Public
# License. See the file "COPYING" in the main directory of this archive
# for more details.
#
# Copyright (C) 1995 by Linus Torvalds
#
# Adapted from code in arch/i386/boot/Makefile by H. Peter Anvin
#
# "make install" script for i386 architecture
#
# Arguments:
# $1 - kernel version
# $2 - kernel image file
# $3 - kernel map file
# $4 - default install path (blank if root directory)
#
# User may have a custom install script
if
[
-x
~/bin/installkernel
]
;
then
exec
~/bin/installkernel
"
$@
"
;
fi
if
[
-x
/sbin/installkernel
]
;
then
exec
/sbin/installkernel
"
$@
"
;
fi
# Default install - same as make zlilo
if
[
-f
$4
/vmlinuz
]
;
then
mv
$4
/vmlinuz
$4
/vmlinuz.old
fi
if
[
-f
$4
/System.map
]
;
then
mv
$4
/System.map
$4
/System.old
fi
cat
$2
>
$4
/vmlinuz
cp
$3
$4
/System.map
if
[
-x
/sbin/lilo
]
;
then
/sbin/lilo
;
else
/etc/lilo/install
;
fi
arch/i386/boot98/mtools.conf.in
deleted
100644 → 0
View file @
bffc8f71
#
# mtools configuration file for "make (b)zdisk"
#
# Actual floppy drive
drive a:
file="/dev/fd0"
# 1.44 MB floppy disk image
drive v:
file="@OBJ@/fdimage" cylinders=80 heads=2 sectors=18 filter
# 2.88 MB floppy disk image (mostly for virtual uses)
drive w:
file="@OBJ@/fdimage" cylinders=80 heads=2 sectors=36 filter
arch/i386/boot98/setup.S
deleted
100644 → 0
View file @
bffc8f71
/*
*
setup
.
S
Copyright
(
C
)
1991
,
1992
Linus
Torvalds
*
*
setup
.
s
is
responsible
for
getting
the
system
data
from
the
BIOS
,
*
and
putting
them
into
the
appropriate
places
in
system
memory
.
*
both
setup
.
s
and
system
has
been
loaded
by
the
bootblock
.
*
*
This
code
asks
the
bios
for
memory
/
disk
/
other
parameters
,
and
*
puts
them
in
a
"safe"
place
:
0x90000
-
0x901FF
,
ie
where
the
*
boot
-
block
used
to
be
.
It
is
then
up
to
the
protected
mode
*
system
to
read
them
from
there
before
the
area
is
overwritten
*
for
buffer
-
blocks
.
*
*
Move
PS
/
2
aux
init
code
to
psaux
.
c
*
(
troyer
@
saifr00
.
cfsat
.
Honeywell
.
COM
)
03
Oct92
*
*
some
changes
and
additional
features
by
Christoph
Niemann
,
*
March
1993
/
June
1994
(
Christoph
.
Niemann
@
linux
.
org
)
*
*
add
APM
BIOS
checking
by
Stephen
Rothwell
,
May
1994
*
(
sfr
@
canb
.
auug
.
org
.
au
)
*
*
High
load
stuff
,
initrd
support
and
position
independency
*
by
Hans
Lermen
&
Werner
Almesberger
,
February
1996
*
<
lermen
@
elserv
.
ffm
.
fgan
.
de
>,
<
almesber
@
lrc
.
epfl
.
ch
>
*
*
Video
handling
moved
to
video
.
S
by
Martin
Mares
,
March
1996
*
<
mj
@
k332
.
feld
.
cvut
.
cz
>
*
*
Extended
memory
detection
scheme
retwiddled
by
orc
@
pell
.
chi
.
il
.
us
(
david
*
parsons
)
to
avoid
loadlin
confusion
,
July
1997
*
*
Transcribed
from
Intel
(
as86
)
->
AT
&
T
(
gas
)
by
Chris
Noe
,
May
1999
.
*
<
stiker
@
northlink
.
com
>
*
*
Fix
to
work
around
buggy
BIOSes
which
dont
use
carry
bit
correctly
*
and
/
or
report
extended
memory
in
CX
/
DX
for
e801h
memory
size
detection
*
call
.
As
a
result
the
kernel
got
wrong
figures
.
The
int15
/
e801h
docs
*
from
Ralf
Brown
interrupt
list
seem
to
indicate
AX
/
BX
should
be
used
*
anyway
.
So
to
avoid
breaking
many
machines
(
presumably
there
was
a
reason
*
to
orginally
use
CX
/
DX
instead
of
AX
/
BX
),
we
do
a
kludge
to
see
*
if
CX
/
DX
have
been
changed
in
the
e801
call
and
if
so
use
AX
/
BX
.
*
Michael
Miller
,
April
2001
<
michaelm
@
mjmm
.
org
>
*
*
New
A20
code
ported
from
SYSLINUX
by
H
.
Peter
Anvin
.
AMD
Elan
bugfixes
*
by
Robert
Schwebel
,
December
2001
<
robert
@
schwebel
.
de
>
*
*
Heavily
modified
for
NEC
PC
-
9800
series
by
Kyoto
University
Microcomputer
*
Club
(
KMC
)
Linux
/
98
project
<
seraphim
@
kmc
.
kyoto
-
u
.
ac
.
jp
>,
1997
-
1999
*/
#include <linux/config.h>
#include <asm/segment.h>
#include <linux/version.h>
#include <linux/compile.h>
#include <asm/boot.h>
#include <asm/e820.h>
#include <asm/page.h>
/*
Signature
words
to
ensure
LILO
loaded
us
right
*/
#define SIG1 0xAA55
#define SIG2 0x5A5A
#define HIRESO_TEXT 0xe000
#define NORMAL_TEXT 0xa000
#define BIOS_FLAG2 0x0400
#define BIOS_FLAG5 0x0458
#define RDISK_EQUIP 0x0488
#define BIOS_FLAG 0x0501
#define KB_SHFT_STS 0x053a
#define DISK_EQUIP 0x055c
INITSEG
=
DEF_INITSEG
#
0x9000
,
we
move
boot
here
,
out
of
the
way
SYSSEG
=
DEF_SYSSEG
#
0x1000
,
system
loaded
at
0x10000
(
65536
)
.
SETUPSEG
=
DEF_SETUPSEG
#
0x9020
,
this
is
the
current
segment
#
...
and
the
former
contents
of
CS
DELTA_INITSEG
=
SETUPSEG
-
INITSEG
#
0x0020
.
code16
.
globl
begtext
,
begdata
,
begbss
,
endtext
,
enddata
,
endbss
.
text
begtext
:
.
data
begdata
:
.
bss
begbss
:
.
text
start
:
jmp
trampoline
#
This
is
the
setup
header
,
and
it
must
start
at
%
cs
:
2
(
old
0x9020
:
2
)
.
ascii
"HdrS"
#
header
signature
.
word
0x0203
#
header
version
number
(>=
0x0105
)
#
or
else
old
loadlin
-
1
.5
will
fail
)
realmode_swtch
:
.
word
0
,
0
#
default_switch
,
SETUPSEG
start_sys_seg
:
.
word
SYSSEG
.
word
kernel_version
#
pointing
to
kernel
version
string
#
above
section
of
header
is
compatible
#
with
loadlin
-
1
.5
(
header
v1
.5
)
.
Don
't
#
change
it
.
type_of_loader
:
.
byte
0
#
=
0
,
old
one
(
LILO
,
Loadlin
,
#
Bootlin
,
SYSLX
,
bootsect
...
)
#
See
Documentation
/
i386
/
boot
.
txt
for
#
assigned
ids
#
flags
,
unused
bits
must
be
zero
(
RFU
)
bit
within
loadflags
loadflags
:
LOADED_HIGH
=
1
#
If
set
,
the
kernel
is
loaded
high
CAN_USE_HEAP
=
0x80
#
If
set
,
the
loader
also
has
set
#
heap_end_ptr
to
tell
how
much
#
space
behind
setup
.
S
can
be
used
for
#
heap
purposes
.
#
Only
the
loader
knows
what
is
free
#ifndef __BIG_KERNEL__
.
byte
0
#else
.
byte
LOADED_HIGH
#endif
setup_move_size
:
.
word
0x8000
#
size
to
move
,
when
setup
is
not
#
loaded
at
0x90000
.
We
will
move
setup
#
to
0x90000
then
just
before
jumping
#
into
the
kernel
.
However
,
only
the
#
loader
knows
how
much
data
behind
#
us
also
needs
to
be
loaded
.
code32_start
:
#
here
loaders
can
put
a
different
#
start
address
for
32
-
bit
code
.
#ifndef __BIG_KERNEL__
.
long
0x1000
#
0x1000
=
default
for
zImage
#else
.
long
0x100000
#
0x100000
=
default
for
big
kernel
#endif
ramdisk_image
:
.
long
0
#
address
of
loaded
ramdisk
image
#
Here
the
loader
puts
the
32
-
bit
#
address
where
it
loaded
the
image
.
#
This
only
will
be
read
by
the
kernel
.
ramdisk_size
:
.
long
0
#
its
size
in
bytes
bootsect_kludge
:
.
long
0
#
obsolete
heap_end_ptr
:
.
word
modelist
+
1024
#
(
Header
version
0x0201
or
later
)
#
space
from
here
(
exclusive
)
down
to
#
end
of
setup
code
can
be
used
by
setup
#
for
local
heap
purposes
.
pad1
:
.
word
0
cmd_line_ptr
:
.
long
0
#
(
Header
version
0x0202
or
later
)
#
If
nonzero
,
a
32
-
bit
pointer
#
to
the
kernel
command
line
.
#
The
command
line
should
be
#
located
between
the
start
of
#
setup
and
the
end
of
low
#
memory
(
0xa0000
),
or
it
may
#
get
overwritten
before
it
#
gets
read
.
If
this
field
is
#
used
,
there
is
no
longer
#
anything
magical
about
the
#
0x90000
segment
; the setup
#
can
be
located
anywhere
in
#
low
memory
0x10000
or
higher
.
ramdisk_max
:
.
long
MAXMEM
-
1
#
(
Header
version
0x0203
or
later
)
#
The
highest
safe
address
for
#
the
contents
of
an
initrd
trampoline
:
call
start_of_setup
.
space
1024
#
End
of
setup
header
#####################################################
start_of_setup
:
#
Set
%
ds
=
%
cs
,
we
know
that
SETUPSEG
=
%
cs
at
this
point
movw
%
cs
,
%
ax
#
aka
SETUPSEG
movw
%
ax
,
%
ds
#
Check
signature
at
end
of
setup
cmpw
$SIG1
,
setup_sig1
jne
bad_sig
cmpw
$SIG2
,
setup_sig2
jne
bad_sig
jmp
good_sig1
#
Routine
to
print
asciiz
string
at
ds
:
si
prtstr
:
lodsb
andb
%
al
,
%
al
jz
fin
call
prtchr
jmp
prtstr
fin
:
ret
no_sig_mess
:
.
string
"No setup signature found ..."
good_sig1
:
jmp
good_sig
#
We
now
have
to
find
the
rest
of
the
setup
code
/
data
bad_sig
:
movw
%
cs
,
%
ax
#
SETUPSEG
subw
$DELTA_INITSEG
,
%
ax
#
INITSEG
movw
%
ax
,
%
ds
xorb
%
bh
,
%
bh
movb
(
497
),
%
bl
#
get
setup
sect
from
bootsect
subw
$
4
,
%
bx
#
LILO
loads
4
sectors
of
setup
shlw
$
8
,
%
bx
#
convert
to
words
(
1
sect
=
2
^
8
words
)
movw
%
bx
,
%
cx
shrw
$
3
,
%
bx
#
convert
to
segment
addw
$SYSSEG
,
%
bx
movw
%
bx
,
%
cs
:
start_sys_seg
#
Move
rest
of
setup
code
/
data
to
here
movw
$
2048
,
%
di
#
four
sectors
loaded
by
LILO
subw
%
si
,
%
si
pushw
%
cs
popw
%
es
movw
$SYSSEG
,
%
ax
movw
%
ax
,
%
ds
rep
movsw
movw
%
cs
,
%
ax
#
aka
SETUPSEG
movw
%
ax
,
%
ds
cmpw
$SIG1
,
setup_sig1
jne
no_sig
cmpw
$SIG2
,
setup_sig2
jne
no_sig
jmp
good_sig
no_sig
:
lea
no_sig_mess
,
%
si
call
prtstr
no_sig_loop
:
hlt
jmp
no_sig_loop
good_sig
:
movw
%
cs
,
%
ax
#
aka
SETUPSEG
subw
$DELTA_INITSEG
,
%
ax
#
aka
INITSEG
movw
%
ax
,
%
ds
#
Check
if
an
old
loader
tries
to
load
a
big
-
kernel
testb
$LOADED_HIGH
,
%
cs
:
loadflags
#
Do
we
have
a
big
kernel
?
jz
loader_ok
#
No
,
no
danger
for
old
loaders
.
cmpb
$
0
,
%
cs
:
type_of_loader
#
Do
we
have
a
loader
that
#
can
deal
with
us
?
jnz
loader_ok
#
Yes
,
continue
.
pushw
%
cs
#
No
,
we
have
an
old
loader
,
popw
%
ds
#
die
.
lea
loader_panic_mess
,
%
si
call
prtstr
jmp
no_sig_loop
loader_panic_mess
:
.
string
"Wrong loader, giving up..."
loader_ok
:
#
Get
memory
size
(
extended
mem
,
kB
)
#
On
PC
-
9800
,
memory
size
detection
is
done
completely
in
32
-
bit
#
kernel
initialize
code
(
kernel
/
setup
.
c
)
.
pushw
%
es
xorl
%
eax
,
%
eax
movw
%
ax
,
%
es
movb
%
al
,
(
E820NR
)
#
PC
-
9800
has
no
E820
movb
%
es
:
(
0x401
),
%
al
shll
$
7
,
%
eax
addw
$
1024
,
%
ax
movw
%
ax
,
(
2
)
movl
%
eax
,
(
0x1e0
)
movw
%
es
:
(
0x594
),
%
ax
shll
$
10
,
%
eax
addl
%
eax
,
(
0x1e0
)
popw
%
es
#
Check
for
video
adapter
and
its
parameters
and
allow
the
#
user
to
browse
video
modes
.
call
video
#
NOTE
:
we
need
%
ds
pointing
#
to
bootsector
#
Get
text
video
mode
movb
$
0x0B
,
%
ah
int
$
0x18
#
CRT
mode
sense
movw
$
(
20
<<
8
)
+
40
,
%
cx
testb
$
0x10
,
%
al
jnz
3
f
movb
$
20
,
%
ch
testb
$
0x01
,
%
al
jnz
1
f
movb
$
25
,
%
ch
jmp
1
f
3
:
#
If
bit
4
was
1
,
it
means
either
1
)
31
lines
for
hi
-
reso
mode
,
#
or
2
)
30
lines
for
PC
-
9821
.
movb
$
31
,
%
ch
#
hireso
mode
value
pushw
$
0
popw
%
es
testb
$
0x08
,
%
es
:
BIOS_FLAG
jnz
1
f
movb
$
30
,
%
ch
1
:
#
Now
we
got
#
of
rows
in
%
ch
movb
%
ch
,
(
14
)
testb
$
0x02
,
%
al
jnz
2
f
movb
$
80
,
%
cl
2
:
#
Now
we
got
#
of
columns
in
%
cl
movb
%
cl
,
(
7
)
#
Next
,
get
horizontal
frequency
if
supported
movw
$
0x3100
,
%
ax
int
$
0x18
#
Call
CRT
bios
movb
%
al
,
(
6
)
#
If
31
h
is
unsupported
,
%
al
remains
0
#
Get
hd0
-
3
data
...
pushw
%
ds
#
aka
INITSEG
popw
%
es
xorw
%
ax
,
%
ax
movw
%
ax
,
%
ds
cld
movw
$
0x0080
,
%
di
movb
DISK_EQUIP
+
1
,
%
ah
movb
$
0x80
,
%
al
get_hd_info
:
shrb
%
ah
pushw
%
ax
jnc
1
f
movb
$
0x84
,
%
ah
int
$
0x1b
jnc
2
f
#
Success
1
:
xorw
%
cx
,
%
cx
#
`
0
cylinders
' means no drive
2
:
#
Attention
!
Work
area
(
drive_info
)
is
arranged
for
PC
-
9800
.
movw
%
cx
,
%
ax
#
#
of
cylinders
stosw
movw
%
dx
,
%
ax
#
#
of
sectors
/
#
of
heads
stosw
movw
%
bx
,
%
ax
#
sector
size
in
bytes
stosw
popw
%
ax
incb
%
al
cmpb
$
0x84
,
%
al
jb
get_hd_info
#
Get
fd
data
...
movw
DISK_EQUIP
,
%
ax
andw
$
0xf00f
,
%
ax
orb
%
al
,
%
ah
movb
RDISK_EQUIP
,
%
al
notb
%
al
andb
%
al
,
%
ah
#
ignore
all
`
RAM
drive
'
movb
$
0x30
,
%
al
get_fd_info
:
shrb
%
ah
pushw
%
ax
jnc
1
f
movb
$
0xc4
,
%
ah
int
$
0x1b
movb
%
ah
,
%
al
andb
$
4
,
%
al
#
1
.44
MB
support
flag
shrb
%
al
addb
$
2
,
%
al
#
%
al
=
2
(
1
.2
MB
)
or
4
(
1
.44
MB
)
jmp
2
f
1
:
movb
$
0
,
%
al
#
no
drive
2
:
stosb
popw
%
ax
incb
%
al
testb
$
0x04
,
%
al
jz
get_fd_info
addb
$
(
0xb0
-
0x34
),
%
al
jnc
get_fd_info
#
check
FDs
on
640
KB
I
/
F
pushw
%
es
popw
%
ds
#
%
ds
got
bootsector
again
#if 0
mov
$
0
,
(
0x1ff
)
#
default
is
no
pointing
device
#endif
#if defined(CONFIG_APM) || defined(CONFIG_APM_MODULE)
#
Then
check
for
an
APM
BIOS
...
#
%
ds
points
to
the
bootsector
movw
$
0
,
0x40
#
version
=
0
means
no
APM
BIOS
movw
$
0x09a00
,
%
ax
#
APM
BIOS
installation
check
xorw
%
bx
,
%
bx
int
$
0x1f
jc
done_apm_bios
#
Nope
,
no
APM
BIOS
cmpw
$
0x0504d
,
%
bx
#
Check
for
"PM"
signature
jne
done_apm_bios
#
No
signature
,
no
APM
BIOS
testb
$
0x02
,
%
cl
#
Is
32
bit
supported
?
je
done_apm_bios
#
No
32
-
bit
,
no
(
good
)
APM
BIOS
movw
$
0x09a04
,
%
ax
#
Disconnect
first
just
in
case
xorw
%
bx
,
%
bx
int
$
0x1f
#
ignore
return
code
movw
$
0x09a03
,
%
ax
#
32
bit
connect
xorl
%
ebx
,
%
ebx
int
$
0x1f
jc
no_32_apm_bios
#
Ack
,
error
.
movw
%
ax
,
(
66
)
#
BIOS
code
segment
movl
%
ebx
,
(
68
)
#
BIOS
entry
point
offset
movw
%
cx
,
(
72
)
#
BIOS
16
bit
code
segment
movw
%
dx
,
(
74
)
#
BIOS
data
segment
movl
%
esi
,
(
78
)
#
BIOS
code
segment
length
movw
%
di
,
(
82
)
#
BIOS
data
segment
length
#
Redo
the
installation
check
as
the
32
bit
connect
#
modifies
the
flags
returned
on
some
BIOSs
movw
$
0x09a00
,
%
ax
#
APM
BIOS
installation
check
xorw
%
bx
,
%
bx
int
$
0x1f
jc
apm_disconnect
#
error
->
shouldn
't happen
cmpw
$
0x0504d
,
%
bx
#
check
for
"PM"
signature
jne
apm_disconnect
#
no
sig
->
shouldn
't happen
movw
%
ax
,
(
64
)
#
record
the
APM
BIOS
version
movw
%
cx
,
(
76
)
#
and
flags
jmp
done_apm_bios
apm_disconnect
:
#
Tidy
up
movw
$
0x09a04
,
%
ax
#
Disconnect
xorw
%
bx
,
%
bx
int
$
0x1f
#
ignore
return
code
jmp
done_apm_bios
no_32_apm_bios
:
andw
$
0xfffd
,
(
76
)
#
remove
32
bit
support
bit
done_apm_bios
:
#endif
#
Pass
cursor
position
to
kernel
...
movw
%
cs
:
cursor_address
,
%
ax
shrw
%
ax
#
cursor_address
is
2
bytes
unit
movb
$
80
,
%
cl
divb
%
cl
xchgb
%
al
,
%
ah
#
(
0
)
=
%
al
=
X
,
(
1
)
=
%
ah
=
Y
movw
%
ax
,
(
0
)
#if 0
movw
$msg_cpos
,
%
si
call
prtstr_cs
call
prthex
call
prtstr_cs
movw
%
ds
,
%
ax
call
prthex
call
prtstr_cs
movb
$
0x11
,
%
ah
int
$
0x18
movb
$
0
,
%
ah
int
$
0x18
.
section
.
rodata
,
"a"
msg_cpos
:
.
string
"Cursor position: 0x"
.
string
", %ds:0x"
.
string
"\r\n"
.
previous
#endif
#
Now
we
want
to
move
to
protected
mode
...
cmpw
$
0
,
%
cs
:
realmode_swtch
jz
rmodeswtch_normal
lcall
*%
cs
:
realmode_swtch
jmp
rmodeswtch_end
rmodeswtch_normal
:
pushw
%
cs
call
default_switch
rmodeswtch_end
:
#
we
get
the
code32
start
address
and
modify
the
below
'jmpi'
#
(
loader
may
have
changed
it
)
movl
%
cs
:
code32_start
,
%
eax
movl
%
eax
,
%
cs
:
code32
#
Now
we
move
the
system
to
its
rightful
place
...
but
we
check
if
we
have
a
#
big
-
kernel
.
In
that
case
we
*
must
*
not
move
it
...
testb
$LOADED_HIGH
,
%
cs
:
loadflags
jz
do_move0
#
..
then
we
have
a
normal
low
#
loaded
zImage
#
..
or
else
we
have
a
high
#
loaded
bzImage
jmp
end_move
#
...
and
we
skip
moving
do_move0
:
movw
$
0x100
,
%
ax
#
start
of
destination
segment
movw
%
cs
,
%
bp
#
aka
SETUPSEG
subw
$DELTA_INITSEG
,
%
bp
#
aka
INITSEG
movw
%
cs
:
start_sys_seg
,
%
bx
#
start
of
source
segment
cld
do_move
:
movw
%
ax
,
%
es
#
destination
segment
incb
%
ah
#
instead
of
add
ax
,#
0x100
movw
%
bx
,
%
ds
#
source
segment
addw
$
0x100
,
%
bx
subw
%
di
,
%
di
subw
%
si
,
%
si
movw
$
0x800
,
%
cx
rep
movsw
cmpw
%
bp
,
%
bx
#
assume
start_sys_seg
>
0x200
,
#
so
we
will
perhaps
read
one
#
page
more
than
needed
,
but
#
never
overwrite
INITSEG
#
because
destination
is
a
#
minimum
one
page
below
source
jb
do_move
end_move
:
#
then
we
load
the
segment
descriptors
movw
%
cs
,
%
ax
#
aka
SETUPSEG
movw
%
ax
,
%
ds
#
Check
whether
we
need
to
be
downward
compatible
with
version
<=
201
cmpl
$
0
,
cmd_line_ptr
jne
end_move_self
#
loader
uses
version
>=
202
features
cmpb
$
0x20
,
type_of_loader
je
end_move_self
#
bootsect
loader
,
we
know
of
it
#
Boot
loader
does
not
support
boot
protocol
version
2
.02.
#
If
we
have
our
code
not
at
0x90000
,
we
need
to
move
it
there
now
.
#
We
also
then
need
to
move
the
params
behind
it
(
commandline
)
#
Because
we
would
overwrite
the
code
on
the
current
IP
,
we
move
#
it
in
two
steps
,
jumping
high
after
the
first
one
.
movw
%
cs
,
%
ax
cmpw
$SETUPSEG
,
%
ax
je
end_move_self
cli
#
make
sure
we
really
have
#
interrupts
disabled
!
#
because
after
this
the
stack
#
should
not
be
used
subw
$DELTA_INITSEG
,
%
ax
#
aka
INITSEG
movw
%
ss
,
%
dx
cmpw
%
ax
,
%
dx
jb
move_self_1
addw
$INITSEG
,
%
dx
subw
%
ax
,
%
dx
#
this
will
go
into
%
ss
after
#
the
move
move_self_1
:
movw
%
ax
,
%
ds
movw
$INITSEG
,
%
ax
#
real
INITSEG
movw
%
ax
,
%
es
movw
%
cs
:
setup_move_size
,
%
cx
std
#
we
have
to
move
up
,
so
we
use
#
direction
down
because
the
#
areas
may
overlap
movw
%
cx
,
%
di
decw
%
di
movw
%
di
,
%
si
subw
$move_self_here
+
0x200
,
%
cx
rep
movsb
ljmp
$SETUPSEG
,
$move_self_here
move_self_here
:
movw
$move_self_here
+
0x200
,
%
cx
rep
movsb
movw
$SETUPSEG
,
%
ax
movw
%
ax
,
%
ds
movw
%
dx
,
%
ss
end_move_self
:
#
now
we
are
at
the
right
place
lidt
idt_48
#
load
idt
with
0
,
0
xorl
%
eax
,
%
eax
#
Compute
gdt_base
movw
%
ds
,
%
ax
#
(
Convert
%
ds
:
gdt
to
a
linear
ptr
)
shll
$
4
,
%
eax
addl
$gdt
,
%
eax
movl
%
eax
,
(
gdt_48
+
2
)
lgdt
gdt_48
#
load
gdt
with
whatever
is
#
appropriate
#
that
was
painless
,
now
we
enable
A20
outb
%
al
,
$
0xf2
#
A20
on
movb
$
0x02
,
%
al
outb
%
al
,
$
0xf6
#
also
A20
on
; making ITF's
#
way
our
model
#
PC
-
9800
seems
to
enable
A20
at
the
moment
of
`
outb
';
#
so
we
don
't wait unlike IBM PCs (see ../setup.S).
#
enable
DMA
to
access
memory
over
0x100000
(
1
MB
)
.
movw
$
0x439
,
%
dx
inb
%
dx
,
%
al
andb
$
(
~
4
),
%
al
outb
%
al
,
%
dx
#
Set
DMA
to
increment
its
bank
address
automatically
at
16
MB
boundary
.
#
Initial
setting
is
64
KB
boundary
mode
so
that
we
can
't run DMA crossing
#
physical
address
0
xXXXXFFFF
.
movb
$
0x0c
,
%
al
outb
%
al
,
$
0x29
#
ch
.
0
movb
$
0x0d
,
%
al
outb
%
al
,
$
0x29
#
ch
.
1
movb
$
0x0e
,
%
al
outb
%
al
,
$
0x29
#
ch
.
2
movb
$
0x0f
,
%
al
outb
%
al
,
$
0x29
#
ch
.
3
movb
$
0x50
,
%
al
outb
%
al
,
$
0x11
#
reinitialize
DMAC
#
make
sure
any
possible
coprocessor
is
properly
reset
..
movb
$
0
,
%
al
outb
%
al
,
$
0xf8
outb
%
al
,
$
0x5f
#
delay
#
well
,
that
went
ok
,
I
hope
.
Now
we
mask
all
interrupts
-
the
rest
#
is
done
in
init_IRQ
()
.
movb
$
0xFF
,
%
al
#
mask
all
interrupts
for
now
outb
%
al
,
$
0x0A
outb
%
al
,
$
0x5f
#
delay
movb
$
0x7F
,
%
al
#
mask
all
irq
's but irq7 which
outb
%
al
,
$
0x02
#
is
cascaded
#
Well
,
that
certainly
wasn
't fun :-(. Hopefully it works, and we don'
t
#
need
no
steenking
BIOS
anyway
(
except
for
the
initial
loading
:
-)
.
#
The
BIOS
-
routine
wants
lots
of
unnecessary
data
,
and
it
's less
#
"
interesting
"
anyway
.
This
is
how
REAL
programmers
do
it
.
#
#
Well
,
now
's the time to actually move into protected mode. To make
#
things
as
simple
as
possible
,
we
do
no
register
set
-
up
or
anything
,
#
we
let
the
gnu
-
compiled
32
-
bit
programs
do
that
.
We
just
jump
to
#
absolute
address
0x1000
(
or
the
loader
supplied
one
),
#
in
32
-
bit
protected
mode
.
#
#
Note
that
the
short
jump
isn
't strictly needed, although there are
#
reasons
why
it
might
be
a
good
idea
.
It
won
't hurt in any case.
movw
$
1
,
%
ax
#
protected
mode
(
PE
)
bit
lmsw
%
ax
#
This
is
it
!
jmp
flush_instr
flush_instr
:
xorw
%
bx
,
%
bx
#
Flag
to
indicate
a
boot
xorl
%
esi
,
%
esi
#
Pointer
to
real
-
mode
code
movw
%
cs
,
%
si
subw
$DELTA_INITSEG
,
%
si
shll
$
4
,
%
esi
#
Convert
to
32
-
bit
pointer
#
NOTE
:
For
high
loaded
big
kernels
we
need
a
#
jmpi
0x100000
,
__BOOT_CS
#
#
but
we
yet
haven
't reloaded the CS register, so the default size
#
of
the
target
offset
still
is
16
bit
.
#
However
,
using
an
operand
prefix
(
0x66
),
the
CPU
will
properly
#
take
our
48
bit
far
pointer
.
(
INTeL
80386
Programmer
's Reference
#
Manual
,
Mixing
16
-
bit
and
32
-
bit
code
,
page
16
-
6
)
.
byte
0x66
,
0xea
#
prefix
+
jmpi
-
opcode
code32
:
.
long
0x1000
#
will
be
set
to
0x100000
#
for
big
kernels
.
word
__BOOT_CS
#
Here
'
s
a
bunch
of
information
about
your
current
kernel
..
kernel_version
:
.
ascii
UTS_RELEASE
.
ascii
" ("
.
ascii
LINUX_COMPILE_BY
.
ascii
"@"
.
ascii
LINUX_COMPILE_HOST
.
ascii
") "
.
ascii
UTS_VERSION
.
byte
0
#
This
is
the
default
real
mode
switch
routine
.
#
to
be
called
just
before
protected
mode
transition
default_switch
:
cli
#
no
interrupts
allowed
!
outb
%
al
,
$
0x50
#
disable
NMI
for
bootup
#
sequence
lret
#
This
routine
prints
one
character
(
in
%
al
)
on
console
.
#
PC
-9800
doesn
't have BIOS-function to do it like IBM PC'
s
INT
10
h
-
0
Eh
,
#
so
we
hardcode
`
prtchr
' subroutine here.
prtchr
:
pushaw
pushw
%
es
cmpb
$
0
,
%
cs
:
prtchr_initialized
jnz
prtchr_ok
xorw
%
cx
,
%
cx
movw
%
cx
,
%
es
testb
$
0x8
,
%
es
:
BIOS_FLAG
jz
1
f
movb
$
(
HIRESO_TEXT
>>
8
),
%
cs
:
cursor_address
+
3
movw
$
(
80
*
31
*
2
),
%
cs
:
max_cursor_offset
1
:
pushw
%
ax
call
get_cursor_position
movw
%
ax
,
%
cs
:
cursor_address
popw
%
ax
movb
$
1
,
%
cs
:
prtchr_initialized
prtchr_ok
:
lesw
%
cs
:
cursor_address
,
%
di
movw
$
160
,
%
bx
movb
$
0
,
%
ah
cmpb
$
13
,
%
al
je
do_cr
cmpb
$
10
,
%
al
je
do_lf
#
normal
(
printable
)
character
stosw
movb
$
0xe1
,
%
es
:
0x2000
-
2
(%
di
)
jmp
1
f
do_cr
:
movw
%
di
,
%
ax
divb
%
bl
#
%
al
=
Y
,
%
ah
=
X
*
2
mulb
%
bl
movw
%
ax
,
%
dx
jmp
2
f
do_lf
:
addw
%
bx
,
%
di
1
:
movw
%
cs
:
max_cursor_offset
,
%
cx
cmpw
%
cx
,
%
di
movw
%
di
,
%
dx
jb
2
f
#
cursor
reaches
bottom
of
screen
; scroll it
subw
%
bx
,
%
dx
xorw
%
di
,
%
di
movw
%
bx
,
%
si
cld
subw
%
bx
,
%
cx
shrw
%
cx
pushw
%
cx
rep
; es; movsw
movb
$
32
,
%
al
#
clear
bottom
line
characters
movb
$
80
,
%
cl
rep
; stosw
movw
$
0x2000
,
%
di
popw
%
cx
leaw
(%
bx
,%
di
),
%
si
rep
; es; movsw
movb
$
0xe1
,
%
al
#
clear
bottom
line
attributes
movb
$
80
,
%
cl
rep
; stosw
2
:
movw
%
dx
,
%
cs
:
cursor_address
movb
$
0x13
,
%
ah
#
move
cursor
to
right
position
int
$
0x18
popw
%
es
popaw
ret
cursor_address
:
.
word
0
.
word
NORMAL_TEXT
max_cursor_offset
:
.
word
80
*
25
*
2
#
for
normal
80
x25
mode
#
putstr
may
called
without
running
through
start_of_setup
(
via
bootsect_panic
)
#
so
we
should
initialize
ourselves
on
demand
.
prtchr_initialized
:
.
byte
0
#
This
routine
queries
GDC
(
graphic
display
controller
)
for
current
cursor
#
position
.
Cursor
position
is
returned
in
%
ax
(
CPU
offset
address
)
.
get_cursor_position
:
1
:
inb
$
0x60
,
%
al
outb
%
al
,
$
0x5f
#
delay
outb
%
al
,
$
0x5f
#
delay
testb
$
0x04
,
%
al
#
Is
FIFO
empty
?
jz
1
b
#
no
->
wait
until
empty
movb
$
0xe0
,
%
al
#
CSRR
command
outb
%
al
,
$
0x62
#
command
write
outb
%
al
,
$
0x5f
#
delay
outb
%
al
,
$
0x5f
#
delay
2
:
inb
$
0x60
,
%
al
outb
%
al
,
$
0x5f
#
delay
outb
%
al
,
$
0x5f
#
delay
testb
$
0x01
,
%
al
#
Is
DATA
READY
?
jz
2
b
#
no
->
wait
until
ready
inb
$
0x62
,
%
al
#
read
xAD
(
L
)
outb
%
al
,
$
0x5f
#
delay
outb
%
al
,
$
0x5f
#
delay
movb
%
al
,
%
ah
inb
$
0x62
,
%
al
#
read
xAD
(
H
)
outb
%
al
,
$
0x5f
#
delay
outb
%
al
,
$
0x5f
#
delay
xchgb
%
al
,
%
ah
#
correct
byte
order
pushw
%
ax
inb
$
0x62
,
%
al
#
read
yAD
(
L
)
outb
%
al
,
$
0x5f
#
delay
outb
%
al
,
$
0x5f
#
delay
inb
$
0x62
,
%
al
#
read
yAD
(
M
)
outb
%
al
,
$
0x5f
#
delay
outb
%
al
,
$
0x5f
#
delay
inb
$
0x62
,
%
al
#
read
yAD
(
H
)
#
yAD
is
not
our
interest
,
#
so
discard
it
.
popw
%
ax
addw
%
ax
,
%
ax
#
convert
to
CPU
address
ret
#
Descriptor
tables
#
#
NOTE
:
The
intel
manual
says
gdt
should
be
sixteen
bytes
aligned
for
#
efficiency
reasons
.
However
,
there
are
machines
which
are
known
not
#
to
boot
with
misaligned
GDTs
,
so
alter
this
at
your
peril
!
If
you
alter
#
GDT_ENTRY_BOOT_CS
(
in
asm
/
segment
.
h
)
remember
to
leave
at
least
two
#
empty
GDT
entries
(
one
for
NULL
and
one
reserved
)
.
#
#
NOTE
:
On
some
CPUs
,
the
GDT
must
be
8
byte
aligned
.
This
is
#
true
for
the
Voyager
Quad
CPU
card
which
will
not
boot
without
#
This
directive
.
16
byte
aligment
is
recommended
by
intel
.
#
.
align
16
gdt
:
.
fill
GDT_ENTRY_BOOT_CS
,
8
,
0
.
word
0xFFFF
#
4
Gb
-
(
0x100000
*
0x1000
=
4
Gb
)
.
word
0
#
base
address
=
0
.
word
0x9A00
#
code
read
/
exec
.
word
0x00CF
#
granularity
=
4096
,
386
#
(+
5
th
nibble
of
limit
)
.
word
0xFFFF
#
4
Gb
-
(
0x100000
*
0x1000
=
4
Gb
)
.
word
0
#
base
address
=
0
.
word
0x9200
#
data
read
/
write
.
word
0x00CF
#
granularity
=
4096
,
386
#
(+
5
th
nibble
of
limit
)
gdt_end
:
.
align
4
.
word
0
#
alignment
byte
idt_48
:
.
word
0
#
idt
limit
=
0
.
word
0
,
0
#
idt
base
=
0
L
.
word
0
#
alignment
byte
gdt_48
:
.
word
gdt_end
-
gdt
-
1
#
gdt
limit
.
word
0
,
0
#
gdt
base
(
filled
in
later
)
#
Include
video
setup
&
detection
code
#include "video.S"
#
Setup
signature
--
must
be
last
setup_sig1
:
.
word
SIG1
setup_sig2
:
.
word
SIG2
#
After
this
point
,
there
is
some
free
space
which
is
used
by
the
video
mode
#
handling
code
to
store
the
temporary
mode
table
(
not
used
by
the
kernel
)
.
modelist
:
.
text
endtext
:
.
data
enddata
:
.
bss
endbss
:
arch/i386/boot98/video.S
deleted
100644 → 0
View file @
bffc8f71
/*
video.S
*
*
Video
mode
setup
,
etc
.
for
NEC
PC
-
9800
series
.
*
*
Copyright
(
C
)
1997
,
98
,
99
Linux
/
98
project
<
seraphim
@
kmc
.
kyoto
-
u
.
ac
.
jp
>
*
*
Based
on
the
video
.
S
for
IBM
PC
:
*
copyright
(
C
)
Martin
Mares
<
mj
@
atrey
.
karlin
.
mff
.
cuni
.
cz
>
*/
/*
Positions
of
various
video
parameters
passed
to
the
kernel
*/
/*
(
see
also
include
/
linux
/
tty
.
h
)
*/
#define PARAM_CURSOR_POS 0x00
#define PARAM_VIDEO_PAGE 0x04
#define PARAM_VIDEO_MODE 0x06
#define PARAM_VIDEO_COLS 0x07
#define PARAM_VIDEO_EGA_BX 0x0a
#define PARAM_VIDEO_LINES 0x0e
#define PARAM_HAVE_VGA 0x0f
#define PARAM_FONT_POINTS 0x10
#define PARAM_VIDEO98_COMPAT 0x0a
#define PARAM_VIDEO98_HIRESO 0x0b
#define PARAM_VIDEO98_MACHTYPE 0x0c
#define PARAM_VIDEO98_LINES 0x0e
#define PARAM_VIDEO98_COLS 0x0f
#
PARAM_LFB_
*
and
PARAM_VESAPM_
*
are
unused
on
PC
-
9800
.
#
This
is
the
main
entry
point
called
by
setup
.
S
#
%
ds
*
must
*
be
pointing
to
the
bootsector
video
:
xorw
%
ax
,
%
ax
movw
%
ax
,
%
es
#
%
es
=
0
movb
%
es
:
BIOS_FLAG
,
%
al
movb
%
al
,
PARAM_VIDEO_MODE
movb
$
0
,
PARAM_VIDEO98_HIRESO
#
0
=
normal
movw
$NORMAL_TEXT
,
PARAM_VIDEO_PAGE
testb
$
0x8
,
%
al
movw
$
(
80
*
256
+
25
),
%
ax
jz
1
f
#
hireso
machine
.
movb
$
1
,
PARAM_VIDEO98_HIRESO
#
!
0
=
hi
-
reso
movb
$
(
HIRESO_TEXT
>>
8
),
PARAM_VIDEO_PAGE
+
1
movw
$
(
80
*
256
+
31
),
%
ax
1
:
movw
%
ax
,
PARAM_VIDEO98_LINES
#
also
sets
VIDEO98_COLS
movb
$
0xc0
,
%
ch
#
400
-
line
graphic
mode
movb
$
0x42
,
%
ah
int
$
0x18
movw
$
80
,
PARAM_VIDEO_COLS
movw
$msg_probing
,
%
si
call
prtstr_cs
#
Check
vendor
from
font
pattern
of
`
A
'...
1
:
inb
$
0x60
,
%
al
#
wait
V
-
sync
testb
$
0x20
,
%
al
jnz
1
b
2
:
inb
$
0x60
,
%
al
testb
$
0x20
,
%
al
jz
2
b
movb
$
0x00
,
%
al
#
select
font
of
`
A
'
outb
%
al
,
$
0xa1
movb
$
0x41
,
%
al
outb
%
al
,
$
0xa3
movw
$
8
,
%
cx
movw
PARAM_VIDEO_PAGE
,
%
ax
cmpw
$NORMAL_TEXT
,
%
ax
je
3
f
movb
$
24
,
%
cl
#
for
hi
-
reso
machine
3
:
addw
$
0x400
,
%
ax
#
%
ax
=
CG
window
segment
pushw
%
ds
movw
%
ax
,
%
ds
xorw
%
dx
,
%
dx
#
get
sum
of
`
A
' pattern...
xorw
%
si
,
%
si
4
:
lodsw
addw
%
ax
,
%
dx
loop
4
b
popw
%
ds
movw
%
dx
,
%
ax
movw
$msg_nec
,
%
si
xorw
%
bx
,
%
bx
#
vendor
info
will
go
into
%
bx
testb
$
8
,
%
es
:
BIOS_FLAG
jnz
check_hireso_vendor
cmpw
$
0xc7f8
,
%
ax
je
5
f
jmp
6
f
check_hireso_vendor
:
cmpw
$
0x9639
,
%
ax
#
XXX
:
NOT
VERIFIED
!!!
je
5
f
6
:
incw
%
bx
#
compatible
machine
movw
$msg_compat
,
%
si
5
:
movb
%
bl
,
PARAM_VIDEO98_COMPAT
call
prtstr_cs
movw
$msg_fontdata
,
%
si
call
prtstr_cs
#
" (CG sum of A = 0x"
movw
%
dx
,
%
ax
call
prthex
call
prtstr_cs
#
") PC-98"
movb
$
'0'
,
%
al
pushw
%
ds
pushw
$
0xf8e8
popw
%
ds
cmpw
$
0x2198
,
(
0
)
popw
%
ds
jne
7
f
movb
$
'2'
,
%
al
7
:
call
prtchr
call
prtstr_cs
#
"1 "
movb
$
0
,
PARAM_VIDEO98_MACHTYPE
#if 0 /* XXX - This check is bogus? [0000:BIOS_FLAG2]-bit7 does NOT
indicate
whether
it
is
a
note
machine
,
but
merely
indicates
whether
it
has
``
RAM
drive
''
.
*/
#
check
note
machine
testb
$
0x80
,
%
es
:
BIOS_FLAG2
jnz
is_note
pushw
%
ds
pushw
$
0xfd80
popw
%
ds
movb
(
4
),
%
al
popw
%
ds
cmpb
$
0x20
,
%
al
#
EPSON
note
A
je
epson_note
cmpb
$
0x22
,
%
al
#
EPSON
note
W
je
epson_note
cmpb
$
0x27
,
%
al
#
EPSON
note
AE
je
epson_note
cmpb
$
0x2a
,
%
al
#
EPSON
note
WR
jne
note_done
epson_note
:
movb
$
1
,
PARAM_VIDEO98_MACHTYPE
movw
$msg_note
,
%
si
call
prtstr_cs
note_done
:
#endif
#
print
h98
?
(
only
NEC
)
cmpb
$
0
,
PARAM_VIDEO98_COMPAT
jnz
8
f
#
not
NEC
->
not
H98
testb
$
0x80
,
%
es
:
BIOS_FLAG5
jz
8
f
#
have
NESA
bus
->
H98
movw
$msg_h98
,
%
si
call
prtstr_cs
orb
$
2
,
PARAM_VIDEO98_MACHTYPE
8
:
testb
$
0x40
,
%
es
:
BIOS_FLAG5
jz
9
f
movw
$msg_gs
,
%
si
call
prtstr_cs
#
only
prints
it
:
-)
9
:
movw
$msg_normal
,
%
si
#
"normal"
testb
$
0x8
,
%
es
:
BIOS_FLAG
jz
1
f
movw
$msg_hireso
,
%
si
1
:
call
prtstr_cs
movw
$msg_sysclk
,
%
si
call
prtstr_cs
movb
$
'5'
,
%
al
testb
$
0x80
,
%
es
:
BIOS_FLAG
jz
2
f
movb
$
'8'
,
%
al
2
:
call
prtchr
call
prtstr_cs
#if 0
testb
$
0x40
,
%
es
:
(
0x45c
)
jz
no_30line
#
no
30
-
line
support
movb
%
es
:
KB_SHFT_STS
,
%
al
testb
$
0x01
,
%
al
#
is
SHIFT
key
pressed
?
jz
no_30line
testb
$
0x10
,
%
al
#
is
CTRL
key
pressed
?
jnz
line40
#
switch
to
30
-
line
mode
movb
$
30
,
PARAM_VIDEO98_LINES
movw
$msg_30line
,
%
si
jmp
3
f
line40
:
movb
$
37
,
PARAM_VIDEO98_LINES
movw
$
40
,
PARAM_VIDEO_LINES
movw
$msg_40line
,
%
si
3
:
call
prtstr_cs
movb
$
0x32
,
%
bh
movw
$
0x300c
,
%
ax
int
$
0x18
#
switch
video
mode
movb
$
0x0c
,
%
ah
int
$
0x18
#
turn
on
text
plane
movw
%
cs
:
cursor_address
,
%
dx
movb
$
0x13
,
%
ah
int
$
0x18
#
move
cursor
to
correct
place
mov
$
0x11
,
%
ah
int
$
0x18
#
turn
on
text
plane
call
prtstr_cs
#
"Ok.\r\n"
no_30line
:
#endif
ret
prtstr_cs
:
pushw
%
ds
pushw
%
cs
popw
%
ds
call
prtstr
popw
%
ds
ret
#
prthex
is
for
debugging
purposes
,
and
prints
%
ax
in
hexadecimal
.
prthex
:
pushw
%
cx
movw
$
4
,
%
cx
1
:
rolw
$
4
,
%
ax
pushw
%
ax
andb
$
0xf
,
%
al
cmpb
$
10
,
%
al
sbbb
$
0x69
,
%
al
das
call
prtchr
popw
%
ax
loop
1
b
popw
%
cx
ret
msg_probing
:
.
string
"Probing machine: "
msg_nec
:
.
string
"NEC"
msg_compat
:
.
string
"compatible"
msg_fontdata
:
.
string
" (CG sum of A = 0x"
.
string
") PC-98"
.
string
"1 "
msg_gs
:
.
string
"(GS) "
msg_h98
:
.
string
"(H98) "
msg_normal
:
.
string
"normal"
msg_hireso
:
.
string
"Hi-reso"
msg_sysclk
:
.
string
" mode, system clock "
.
string
"MHz\r\n"
#if 0
msg_40line
:
#
cpp
will
concat
following
lines
,
so
the
assembler
can
deal
.
.
ascii
"\
Video
mode
will
be
adjusted
to
37
-
line
(
so
-
called
``
40
-
line
''
)
mode
later
.
\
r
\
n
\
THIS
MODE
MAY
DAMAGE
YOUR
MONITOR
PHYSICALLY
.
USE
AT
YOUR
OWN
RISK
.
\
r
\
n
"
msg_30line
:
.
string
"Switching video mode to 30-line (640x480) mode... "
.
string
"Ok.\r\n"
#endif
arch/i386/mach-pc9800/Makefile
deleted
100644 → 0
View file @
bffc8f71
#
# Makefile for the linux kernel.
#
obj-y
:=
setup.o topology.o std_resources.o
arch/i386/mach-pc9800/setup.c
deleted
100644 → 0
View file @
bffc8f71
/*
* Machine specific setup for pc9800
*/
#include <linux/config.h>
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/apm_bios.h>
#include <asm/setup.h>
#include <asm/arch_hooks.h>
struct
sys_desc_table_struct
{
unsigned
short
length
;
unsigned
char
table
[
0
];
};
/**
* pre_intr_init_hook - initialisation prior to setting up interrupt vectors
*
* Description:
* Perform any necessary interrupt initialisation prior to setting up
* the "ordinary" interrupt call gates. For legacy reasons, the ISA
* interrupts should be initialised here if the machine emulates a PC
* in any way.
**/
void
__init
pre_intr_init_hook
(
void
)
{
init_ISA_irqs
();
}
/*
* IRQ7 is cascade interrupt to second interrupt controller
*/
static
struct
irqaction
irq7
=
{
no_action
,
0
,
0
,
"cascade"
,
NULL
,
NULL
};
/**
* intr_init_hook - post gate setup interrupt initialisation
*
* Description:
* Fill in any interrupts that may have been left out by the general
* init_IRQ() routine. interrupts having to do with the machine rather
* than the devices on the I/O bus (like APIC interrupts in intel MP
* systems) are started here.
**/
void
__init
intr_init_hook
(
void
)
{
#ifdef CONFIG_X86_LOCAL_APIC
apic_intr_init
();
#endif
setup_irq
(
7
,
&
irq7
);
}
/**
* pre_setup_arch_hook - hook called prior to any setup_arch() execution
*
* Description:
* generally used to activate any machine specific identification
* routines that may be needed before setup_arch() runs. On VISWS
* this is used to get the board revision and type.
**/
void
__init
pre_setup_arch_hook
(
void
)
{
SYS_DESC_TABLE
.
length
=
0
;
MCA_bus
=
0
;
/* In PC-9800, APM BIOS version is written in BCD...?? */
APM_BIOS_INFO
.
version
=
(
APM_BIOS_INFO
.
version
&
0xff00
)
|
((
APM_BIOS_INFO
.
version
&
0x00f0
)
>>
4
);
}
/**
* trap_init_hook - initialise system specific traps
*
* Description:
* Called as the final act of trap_init(). Used in VISWS to initialise
* the various board specific APIC traps.
**/
void
__init
trap_init_hook
(
void
)
{
}
static
struct
irqaction
irq0
=
{
timer_interrupt
,
SA_INTERRUPT
,
0
,
"timer"
,
NULL
,
NULL
};
/**
* time_init_hook - do any specific initialisations for the system timer.
*
* Description:
* Must plug the system timer interrupt source at HZ into the IRQ listed
* in irq_vectors.h:TIMER_IRQ
**/
void
__init
time_init_hook
(
void
)
{
setup_irq
(
0
,
&
irq0
);
}
#ifdef CONFIG_MCA
/**
* mca_nmi_hook - hook into MCA specific NMI chain
*
* Description:
* The MCA (Microchannel Architecture) has an NMI chain for NMI sources
* along the MCA bus. Use this to hook into that chain if you will need
* it.
**/
void
__init
mca_nmi_hook
(
void
)
{
/* If I recall correctly, there's a whole bunch of other things that
* we can do to check for NMI problems, but that's all I know about
* at the moment.
*/
printk
(
"NMI generated from unknown source!
\n
"
);
}
#endif
arch/i386/mach-pc9800/std_resources.c
deleted
100644 → 0
View file @
bffc8f71
/*
* Machine specific resource allocation for PC-9800.
* Written by Osamu Tomita <tomita@cinet.co.jp>
*/
#include <linux/ioport.h>
#include <asm/io.h>
#include <asm/std_resources.h>
static
char
str_pic1
[]
=
"pic1"
;
static
char
str_dma
[]
=
"dma"
;
static
char
str_pic2
[]
=
"pic2"
;
static
char
str_calender_clock
[]
=
"calender clock"
;
static
char
str_system
[]
=
"system"
;
static
char
str_nmi_control
[]
=
"nmi control"
;
static
char
str_kanji_rom
[]
=
"kanji rom"
;
static
char
str_keyboard
[]
=
"keyboard"
;
static
char
str_text_gdc
[]
=
"text gdc"
;
static
char
str_crtc
[]
=
"crtc"
;
static
char
str_timer
[]
=
"timer"
;
static
char
str_graphic_gdc
[]
=
"graphic gdc"
;
static
char
str_dma_ex_bank
[]
=
"dma ex. bank"
;
static
char
str_beep_freq
[]
=
"beep freq."
;
static
char
str_mouse_pio
[]
=
"mouse pio"
;
struct
resource
standard_io_resources
[]
=
{
{
str_pic1
,
0x00
,
0x00
,
IORESOURCE_BUSY
},
{
str_dma
,
0x01
,
0x01
,
IORESOURCE_BUSY
},
{
str_pic1
,
0x02
,
0x02
,
IORESOURCE_BUSY
},
{
str_dma
,
0x03
,
0x03
,
IORESOURCE_BUSY
},
{
str_dma
,
0x05
,
0x05
,
IORESOURCE_BUSY
},
{
str_dma
,
0x07
,
0x07
,
IORESOURCE_BUSY
},
{
str_pic2
,
0x08
,
0x08
,
IORESOURCE_BUSY
},
{
str_dma
,
0x09
,
0x09
,
IORESOURCE_BUSY
},
{
str_pic2
,
0x0a
,
0x0a
,
IORESOURCE_BUSY
},
{
str_dma
,
0x0b
,
0x0b
,
IORESOURCE_BUSY
},
{
str_dma
,
0x0d
,
0x0d
,
IORESOURCE_BUSY
},
{
str_dma
,
0x0f
,
0x0f
,
IORESOURCE_BUSY
},
{
str_dma
,
0x11
,
0x11
,
IORESOURCE_BUSY
},
{
str_dma
,
0x13
,
0x13
,
IORESOURCE_BUSY
},
{
str_dma
,
0x15
,
0x15
,
IORESOURCE_BUSY
},
{
str_dma
,
0x17
,
0x17
,
IORESOURCE_BUSY
},
{
str_dma
,
0x19
,
0x19
,
IORESOURCE_BUSY
},
{
str_dma
,
0x1b
,
0x1b
,
IORESOURCE_BUSY
},
{
str_dma
,
0x1d
,
0x1d
,
IORESOURCE_BUSY
},
{
str_dma
,
0x1f
,
0x1f
,
IORESOURCE_BUSY
},
{
str_calender_clock
,
0x20
,
0x20
,
0
},
{
str_dma
,
0x21
,
0x21
,
IORESOURCE_BUSY
},
{
str_calender_clock
,
0x22
,
0x22
,
0
},
{
str_dma
,
0x23
,
0x23
,
IORESOURCE_BUSY
},
{
str_dma
,
0x25
,
0x25
,
IORESOURCE_BUSY
},
{
str_dma
,
0x27
,
0x27
,
IORESOURCE_BUSY
},
{
str_dma
,
0x29
,
0x29
,
IORESOURCE_BUSY
},
{
str_dma
,
0x2b
,
0x2b
,
IORESOURCE_BUSY
},
{
str_dma
,
0x2d
,
0x2d
,
IORESOURCE_BUSY
},
{
str_system
,
0x31
,
0x31
,
IORESOURCE_BUSY
},
{
str_system
,
0x33
,
0x33
,
IORESOURCE_BUSY
},
{
str_system
,
0x35
,
0x35
,
IORESOURCE_BUSY
},
{
str_system
,
0x37
,
0x37
,
IORESOURCE_BUSY
},
{
str_nmi_control
,
0x50
,
0x50
,
IORESOURCE_BUSY
},
{
str_nmi_control
,
0x52
,
0x52
,
IORESOURCE_BUSY
},
{
"time stamp"
,
0x5c
,
0x5f
,
IORESOURCE_BUSY
},
{
str_kanji_rom
,
0xa1
,
0xa1
,
IORESOURCE_BUSY
},
{
str_kanji_rom
,
0xa3
,
0xa3
,
IORESOURCE_BUSY
},
{
str_kanji_rom
,
0xa5
,
0xa5
,
IORESOURCE_BUSY
},
{
str_kanji_rom
,
0xa7
,
0xa7
,
IORESOURCE_BUSY
},
{
str_kanji_rom
,
0xa9
,
0xa9
,
IORESOURCE_BUSY
},
{
str_keyboard
,
0x41
,
0x41
,
IORESOURCE_BUSY
},
{
str_keyboard
,
0x43
,
0x43
,
IORESOURCE_BUSY
},
{
str_text_gdc
,
0x60
,
0x60
,
IORESOURCE_BUSY
},
{
str_text_gdc
,
0x62
,
0x62
,
IORESOURCE_BUSY
},
{
str_text_gdc
,
0x64
,
0x64
,
IORESOURCE_BUSY
},
{
str_text_gdc
,
0x66
,
0x66
,
IORESOURCE_BUSY
},
{
str_text_gdc
,
0x68
,
0x68
,
IORESOURCE_BUSY
},
{
str_text_gdc
,
0x6a
,
0x6a
,
IORESOURCE_BUSY
},
{
str_text_gdc
,
0x6c
,
0x6c
,
IORESOURCE_BUSY
},
{
str_text_gdc
,
0x6e
,
0x6e
,
IORESOURCE_BUSY
},
{
str_crtc
,
0x70
,
0x70
,
IORESOURCE_BUSY
},
{
str_crtc
,
0x72
,
0x72
,
IORESOURCE_BUSY
},
{
str_crtc
,
0x74
,
0x74
,
IORESOURCE_BUSY
},
{
str_crtc
,
0x74
,
0x74
,
IORESOURCE_BUSY
},
{
str_crtc
,
0x76
,
0x76
,
IORESOURCE_BUSY
},
{
str_crtc
,
0x78
,
0x78
,
IORESOURCE_BUSY
},
{
str_crtc
,
0x7a
,
0x7a
,
IORESOURCE_BUSY
},
{
str_timer
,
0x71
,
0x71
,
IORESOURCE_BUSY
},
{
str_timer
,
0x73
,
0x73
,
IORESOURCE_BUSY
},
{
str_timer
,
0x75
,
0x75
,
IORESOURCE_BUSY
},
{
str_timer
,
0x77
,
0x77
,
IORESOURCE_BUSY
},
{
str_graphic_gdc
,
0xa0
,
0xa0
,
IORESOURCE_BUSY
},
{
str_graphic_gdc
,
0xa2
,
0xa2
,
IORESOURCE_BUSY
},
{
str_graphic_gdc
,
0xa4
,
0xa4
,
IORESOURCE_BUSY
},
{
str_graphic_gdc
,
0xa6
,
0xa6
,
IORESOURCE_BUSY
},
{
"cpu"
,
0xf0
,
0xf7
,
IORESOURCE_BUSY
},
{
"fpu"
,
0xf8
,
0xff
,
IORESOURCE_BUSY
},
{
str_dma_ex_bank
,
0x0e05
,
0x0e05
,
0
},
{
str_dma_ex_bank
,
0x0e07
,
0x0e07
,
0
},
{
str_dma_ex_bank
,
0x0e09
,
0x0e09
,
0
},
{
str_dma_ex_bank
,
0x0e0b
,
0x0e0b
,
0
},
{
str_beep_freq
,
0x3fd9
,
0x3fd9
,
IORESOURCE_BUSY
},
{
str_beep_freq
,
0x3fdb
,
0x3fdb
,
IORESOURCE_BUSY
},
{
str_beep_freq
,
0x3fdd
,
0x3fdd
,
IORESOURCE_BUSY
},
{
str_beep_freq
,
0x3fdf
,
0x3fdf
,
IORESOURCE_BUSY
},
/* All PC-9800 have (exactly) one mouse interface. */
{
str_mouse_pio
,
0x7fd9
,
0x7fd9
,
0
},
{
str_mouse_pio
,
0x7fdb
,
0x7fdb
,
0
},
{
str_mouse_pio
,
0x7fdd
,
0x7fdd
,
0
},
{
str_mouse_pio
,
0x7fdf
,
0x7fdf
,
0
},
{
"mouse timer"
,
0xbfdb
,
0xbfdb
,
0
},
{
"mouse irq"
,
0x98d7
,
0x98d7
,
0
},
};
#define STANDARD_IO_RESOURCES (sizeof(standard_io_resources)/sizeof(struct resource))
static
struct
resource
tvram_resource
=
{
"Text VRAM/CG window"
,
0xa0000
,
0xa4fff
,
IORESOURCE_BUSY
};
static
struct
resource
gvram_brg_resource
=
{
"Graphic VRAM (B/R/G)"
,
0xa8000
,
0xbffff
,
IORESOURCE_BUSY
};
static
struct
resource
gvram_e_resource
=
{
"Graphic VRAM (E)"
,
0xe0000
,
0xe7fff
,
IORESOURCE_BUSY
};
/* System ROM resources */
#define MAXROMS 6
static
struct
resource
rom_resources
[
MAXROMS
]
=
{
{
"System ROM"
,
0xe8000
,
0xfffff
,
IORESOURCE_BUSY
}
};
void
__init
probe_roms
(
void
)
{
int
i
;
__u8
*
xrom_id
;
int
roms
=
1
;
request_resource
(
&
iomem_resource
,
rom_resources
+
0
);
xrom_id
=
(
__u8
*
)
isa_bus_to_virt
(
PC9800SCA_XROM_ID
+
0x10
);
for
(
i
=
0
;
i
<
16
;
i
++
)
{
if
(
xrom_id
[
i
]
&
0x80
)
{
int
j
;
for
(
j
=
i
+
1
;
j
<
16
&&
(
xrom_id
[
j
]
&
0x80
);
j
++
)
;
rom_resources
[
roms
].
start
=
0x0d0000
+
i
*
0x001000
;
rom_resources
[
roms
].
end
=
0x0d0000
+
j
*
0x001000
-
1
;
rom_resources
[
roms
].
name
=
"Extension ROM"
;
rom_resources
[
roms
].
flags
=
IORESOURCE_BUSY
;
request_resource
(
&
iomem_resource
,
rom_resources
+
roms
);
if
(
++
roms
>=
MAXROMS
)
return
;
}
}
}
void
__init
request_graphics_resource
(
void
)
{
int
i
;
if
(
PC9800_HIGHRESO_P
())
{
tvram_resource
.
start
=
0xe0000
;
tvram_resource
.
end
=
0xe4fff
;
gvram_brg_resource
.
name
=
"Graphic VRAM"
;
gvram_brg_resource
.
start
=
0xc0000
;
gvram_brg_resource
.
end
=
0xdffff
;
}
request_resource
(
&
iomem_resource
,
&
tvram_resource
);
request_resource
(
&
iomem_resource
,
&
gvram_brg_resource
);
if
(
!
PC9800_HIGHRESO_P
())
request_resource
(
&
iomem_resource
,
&
gvram_e_resource
);
if
(
PC9800_HIGHRESO_P
()
||
PC9800_9821_P
())
{
static
char
graphics
[]
=
"graphics"
;
static
struct
resource
graphics_resources
[]
=
{
{
graphics
,
0x9a0
,
0x9a0
,
0
},
{
graphics
,
0x9a2
,
0x9a2
,
0
},
{
graphics
,
0x9a4
,
0x9a4
,
0
},
{
graphics
,
0x9a6
,
0x9a6
,
0
},
{
graphics
,
0x9a8
,
0x9a8
,
0
},
{
graphics
,
0x9aa
,
0x9aa
,
0
},
{
graphics
,
0x9ac
,
0x9ac
,
0
},
{
graphics
,
0x9ae
,
0x9ae
,
0
},
};
#define GRAPHICS_RESOURCES (sizeof(graphics_resources)/sizeof(struct resource))
for
(
i
=
0
;
i
<
GRAPHICS_RESOURCES
;
i
++
)
request_resource
(
&
ioport_resource
,
graphics_resources
+
i
);
}
}
void
__init
request_standard_io_resources
(
void
)
{
int
i
;
for
(
i
=
0
;
i
<
STANDARD_IO_RESOURCES
;
i
++
)
request_resource
(
&
ioport_resource
,
standard_io_resources
+
i
);
}
arch/i386/mach-pc9800/topology.c
deleted
100644 → 0
View file @
bffc8f71
/*
* arch/i386/mach-pc9800/topology.c - Populate driverfs with topology information
*
* Written by: Matthew Dobson, IBM Corporation
* Original Code: Paul Dorwin, IBM Corporation, Patrick Mochel, OSDL
*
* Copyright (C) 2002, IBM Corp.
*
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
* NON INFRINGEMENT. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* Modify for PC-9800 by Osamu Tomita <tomita@cinet.co.jp>
*
*/
#include <linux/init.h>
#include <linux/smp.h>
#include <asm/cpu.h>
struct
i386_cpu
cpu_devices
[
NR_CPUS
];
static
int
__init
topology_init
(
void
)
{
int
i
;
for
(
i
=
0
;
i
<
NR_CPUS
;
i
++
)
if
(
cpu_possible
(
i
))
arch_register_cpu
(
i
);
return
0
;
}
subsys_initcall
(
topology_init
);
drivers/block/floppy98.c
deleted
100644 → 0
View file @
bffc8f71
This source diff could not be displayed because it is too large. You can
view the blob
instead.
drivers/char/lp_old98.c
deleted
100644 → 0
View file @
bffc8f71
/*
* linux/drivers/char/lp_old98.c
*
* printer port driver for ancient PC-9800s with no bidirectional port support
*
* Copyright (C) 1998,99 Kousuke Takai <tak@kmc.kyoto-u.ac.jp>,
* Kyoto University Microcomputer Club
*
* This driver is based on and has compatibility with `lp.c',
* generic PC printer port driver.
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/config.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/ioport.h>
#include <linux/fcntl.h>
#include <linux/delay.h>
#include <linux/console.h>
#include <linux/fs.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/system.h>
#include <linux/lp.h>
/*
* I/O port numbers
*/
#define LP_PORT_DATA 0x40
#define LP_PORT_STATUS (LP_PORT_DATA + 2)
#define LP_PORT_STROBE (LP_PORT_DATA + 4)
#define LP_PORT_CONTROL (LP_PORT_DATA + 6)
#define LP_PORT_H98MODE 0x0448
#define LP_PORT_EXTMODE 0x0149
/*
* bit mask for I/O
*/
#define LP_MASK_nBUSY (1 << 2)
#define LP_MASK_nSTROBE (1 << 7)
#define LP_CONTROL_ASSERT_STROBE (0x0e)
#define LP_CONTROL_NEGATE_STROBE (0x0f)
/*
* Acceptable maximum value for non-privileged user for LPCHARS ioctl.
*/
#define LP_CHARS_NOPRIV_MAX 65535
#define DC1 '\x11'
#define DC3 '\x13'
/* PC-9800s have at least and at most one old-style printer port. */
static
struct
lp_struct
lp
=
{
.
flags
=
LP_EXIST
|
LP_ABORTOPEN
,
.
chars
=
LP_INIT_CHAR
,
.
time
=
LP_INIT_TIME
,
.
wait
=
LP_INIT_WAIT
,
};
static
int
dc1_check
;
static
spinlock_t
lp_old98_lock
=
SPIN_LOCK_UNLOCKED
;
#undef LP_OLD98_DEBUG
#ifdef CONFIG_PC9800_OLDLP_CONSOLE
static
struct
console
lp_old98_console
;
/* defined later */
static
short
saved_console_flags
;
#endif
static
DECLARE_WAIT_QUEUE_HEAD
(
lp_old98_waitq
);
static
void
lp_old98_timer_function
(
unsigned
long
data
)
{
if
(
inb
(
LP_PORT_STATUS
)
&
LP_MASK_nBUSY
)
wake_up_interruptible
(
&
lp_old98_waitq
);
else
{
struct
timer_list
*
t
=
(
struct
timer_list
*
)
data
;
t
->
expires
=
jiffies
+
1
;
add_timer
(
t
);
}
}
static
inline
int
lp_old98_wait_ready
(
void
)
{
struct
timer_list
timer
;
init_timer
(
&
timer
);
timer
.
function
=
lp_old98_timer_function
;
timer
.
expires
=
jiffies
+
1
;
timer
.
data
=
(
unsigned
long
)
&
timer
;
add_timer
(
&
timer
);
interruptible_sleep_on
(
&
lp_old98_waitq
);
del_timer
(
&
timer
);
return
signal_pending
(
current
);
}
static
inline
int
lp_old98_char
(
char
lpchar
)
{
unsigned
long
count
=
0
;
#ifdef LP_STATS
int
tmp
;
#endif
while
(
!
(
inb
(
LP_PORT_STATUS
)
&
LP_MASK_nBUSY
))
{
count
++
;
if
(
count
>=
lp
.
chars
)
return
0
;
}
outb
(
lpchar
,
LP_PORT_DATA
);
#ifdef LP_STATS
/*
* Update lp statsistics here (and between next two outb()'s).
* Time to compute it is part of storobe delay.
*/
if
(
count
>
lp
.
stats
.
maxwait
)
{
#ifdef LP_OLD98_DEBUG
printk
(
KERN_DEBUG
"lp_old98: success after %d counts.
\n
"
,
count
);
#endif
lp
.
stats
.
maxwait
=
count
;
}
count
*=
256
;
tmp
=
count
-
lp
.
stats
.
meanwait
;
if
(
tmp
<
0
)
tmp
=
-
tmp
;
#endif
ndelay
(
lp
.
wait
);
/* negate PSTB# (activate strobe) */
outb
(
LP_CONTROL_ASSERT_STROBE
,
LP_PORT_CONTROL
);
#ifdef LP_STATS
lp
.
stats
.
meanwait
=
(
255
*
lp
.
stats
.
meanwait
+
count
+
128
)
/
256
;
lp
.
stats
.
mdev
=
(
127
*
lp
.
stats
.
mdev
+
tmp
+
64
)
/
128
;
lp
.
stats
.
chars
++
;
#endif
ndelay
(
lp
.
wait
);
/* assert PSTB# (deactivate strobe) */
outb
(
LP_CONTROL_NEGATE_STROBE
,
LP_PORT_CONTROL
);
return
1
;
}
static
ssize_t
lp_old98_write
(
struct
file
*
file
,
const
char
*
buf
,
size_t
count
,
loff_t
*
dummy
)
{
unsigned
long
total_bytes_written
=
0
;
if
(
!
access_ok
(
VERIFY_READ
,
buf
,
count
))
return
-
EFAULT
;
#ifdef LP_STATS
if
(
jiffies
-
lp
.
lastcall
>
lp
.
time
)
lp
.
runchars
=
0
;
lp
.
lastcall
=
jiffies
;
#endif
do
{
unsigned
long
bytes_written
=
0
;
unsigned
long
copy_size
=
(
count
<
LP_BUFFER_SIZE
?
count
:
LP_BUFFER_SIZE
);
if
(
__copy_from_user
(
lp
.
lp_buffer
,
buf
,
copy_size
))
return
-
EFAULT
;
while
(
bytes_written
<
copy_size
)
{
if
(
lp_old98_char
(
lp
.
lp_buffer
[
bytes_written
]))
bytes_written
++
;
else
{
#ifdef LP_STATS
int
rc
=
lp
.
runchars
+
bytes_written
;
if
(
rc
>
lp
.
stats
.
maxrun
)
lp
.
stats
.
maxrun
=
rc
;
lp
.
stats
.
sleeps
++
;
#endif
#ifdef LP_OLD98_DEBUG
printk
(
KERN_DEBUG
"lp_old98: sleeping at %d characters"
" for %d jiffies
\n
"
,
lp
.
runchars
,
lp
.
time
);
lp
.
runchars
=
0
;
#endif
if
(
lp_old98_wait_ready
())
return
((
total_bytes_written
+
bytes_written
)
?
:
-
EINTR
);
}
}
total_bytes_written
+=
bytes_written
;
buf
+=
bytes_written
;
#ifdef LP_STATS
lp
.
runchars
+=
bytes_written
;
#endif
count
-=
bytes_written
;
}
while
(
count
>
0
);
return
total_bytes_written
;
}
static
int
lp_old98_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
if
(
iminor
(
inode
)
!=
0
)
return
-
ENXIO
;
if
(
lp
.
flags
&
LP_BUSY
)
return
-
EBUSY
;
if
(
dc1_check
&&
(
lp
.
flags
&
LP_ABORTOPEN
)
&&
!
(
file
->
f_flags
&
O_NONBLOCK
))
{
/*
* Check whether printer is on-line.
* PC-9800's old style port have only BUSY# as status input,
* so that it is impossible to distinguish that the printer is
* ready and that the printer is off-line or not connected
* (in both case BUSY# is in the same state). So:
*
* (1) output DC1 (0x11) to printer port and do strobe.
* (2) watch BUSY# line for a while. If BUSY# is pulled
* down, the printer will be ready. Otherwise,
* it will be off-line (or not connected, or power-off,
* ...).
*
* The source of this procedure:
* Terumasa KODAKA, Kazufumi SHIMIZU, Yu HAYAMI:
* `PC-9801 Super Technique', Ascii, 1992.
*/
int
count
;
unsigned
long
flags
;
/* interrupts while check is fairly bad */
spin_lock_irqsave
(
&
lp_old98_lock
,
flags
);
if
(
!
lp_old98_char
(
DC1
))
{
spin_unlock_irqrestore
(
&
lp_old98_lock
,
flags
);
return
-
EBUSY
;
}
count
=
(
unsigned
int
)
dc1_check
>
10000
?
10000
:
dc1_check
;
while
(
inb
(
LP_PORT_STATUS
)
&
LP_MASK_nBUSY
)
{
if
(
--
count
==
0
)
{
spin_unlock_irqrestore
(
&
lp_old98_lock
,
flags
);
return
-
ENODEV
;
}
}
spin_unlock_irqrestore
(
&
lp_old98_lock
,
flags
);
}
if
((
lp
.
lp_buffer
=
kmalloc
(
LP_BUFFER_SIZE
,
GFP_KERNEL
))
==
NULL
)
return
-
ENOMEM
;
lp
.
flags
|=
LP_BUSY
;
#ifdef CONFIG_PC9800_OLDLP_CONSOLE
saved_console_flags
=
lp_old98_console
.
flags
;
lp_old98_console
.
flags
&=
~
CON_ENABLED
;
#endif
return
0
;
}
static
int
lp_old98_release
(
struct
inode
*
inode
,
struct
file
*
file
)
{
kfree
(
lp
.
lp_buffer
);
lp
.
lp_buffer
=
NULL
;
lp
.
flags
&=
~
LP_BUSY
;
#ifdef CONFIG_PC9800_OLDLP_CONSOLE
lp_old98_console
.
flags
=
saved_console_flags
;
#endif
return
0
;
}
static
int
lp_old98_init_device
(
void
)
{
unsigned
char
data
;
if
((
data
=
inb
(
LP_PORT_EXTMODE
))
!=
0xFF
&&
(
data
&
0x10
))
{
printk
(
KERN_INFO
"lp_old98: shutting down extended parallel port mode...
\n
"
);
outb
(
data
&
~
0x10
,
LP_PORT_EXTMODE
);
}
#ifdef PC98_HW_H98
if
((
pc98_hw_flags
&
PC98_HW_H98
)
&&
((
data
=
inb
(
LP_PORT_H98MODE
))
&
0x01
))
{
printk
(
KERN_INFO
"lp_old98: shutting down H98 full centronics mode...
\n
"
);
outb
(
data
&
~
0x01
,
LP_PORT_H98MODE
);
}
#endif
return
0
;
}
static
int
lp_old98_ioctl
(
struct
inode
*
inode
,
struct
file
*
file
,
unsigned
int
command
,
unsigned
long
arg
)
{
int
retval
=
0
;
switch
(
command
)
{
case
LPTIME
:
lp
.
time
=
arg
*
HZ
/
100
;
break
;
case
LPCHAR
:
lp
.
chars
=
arg
;
break
;
case
LPABORT
:
if
(
arg
)
lp
.
flags
|=
LP_ABORT
;
else
lp
.
flags
&=
~
LP_ABORT
;
break
;
case
LPABORTOPEN
:
if
(
arg
)
lp
.
flags
|=
LP_ABORTOPEN
;
else
lp
.
flags
&=
~
LP_ABORTOPEN
;
break
;
case
LPCAREFUL
:
/* do nothing */
break
;
case
LPWAIT
:
lp
.
wait
=
arg
;
break
;
case
LPGETIRQ
:
retval
=
put_user
(
0
,
(
int
*
)
arg
);
break
;
case
LPGETSTATUS
:
/*
* convert PC-9800's status to IBM PC's one, so that tunelp(8)
* works in the same way on this driver.
*/
retval
=
put_user
((
inb
(
LP_PORT_STATUS
)
&
LP_MASK_nBUSY
)
?
(
LP_PBUSY
|
LP_PERRORP
)
:
LP_PERRORP
,
(
int
*
)
arg
);
break
;
case
LPRESET
:
retval
=
lp_old98_init_device
();
break
;
#ifdef LP_STATS
case
LPGETSTATS
:
if
(
copy_to_user
((
struct
lp_stats
*
)
arg
,
&
lp
.
stats
,
sizeof
(
struct
lp_stats
)))
retval
=
-
EFAULT
;
else
if
(
suser
())
memset
(
&
lp
.
stats
,
0
,
sizeof
(
struct
lp_stats
));
break
;
#endif
case
LPGETFLAGS
:
retval
=
put_user
(
lp
.
flags
,
(
int
*
)
arg
);
break
;
case
LPSETIRQ
:
default:
retval
=
-
EINVAL
;
}
return
retval
;
}
static
struct
file_operations
lp_old98_fops
=
{
.
owner
=
THIS_MODULE
,
.
write
=
lp_old98_write
,
.
ioctl
=
lp_old98_ioctl
,
.
open
=
lp_old98_open
,
.
release
=
lp_old98_release
,
};
/*
* Support for console on lp_old98
*/
#ifdef CONFIG_PC9800_OLDLP_CONSOLE
static
inline
void
io_delay
(
void
)
{
unsigned
char
dummy
;
/* actually not output */
asm
volatile
(
"out%B0 %0,%1"
:
"=a"
(
dummy
)
:
"N"
(
0x5f
));
}
static
void
lp_old98_console_write
(
struct
console
*
console
,
const
char
*
s
,
unsigned
int
count
)
{
int
i
;
static
unsigned
int
timeout_run
=
0
;
while
(
count
)
{
/* wait approx 1.2 seconds */
for
(
i
=
2000000
;
!
(
inb
(
LP_PORT_STATUS
)
&
LP_MASK_nBUSY
);
io_delay
())
if
(
!--
i
)
{
if
(
++
timeout_run
>=
10
)
/* disable forever... */
console
->
flags
&=
~
CON_ENABLED
;
return
;
}
timeout_run
=
0
;
if
(
*
s
==
'\n'
)
{
outb
(
'\r'
,
LP_PORT_DATA
);
io_delay
();
io_delay
();
outb
(
LP_CONTROL_ASSERT_STROBE
,
LP_PORT_CONTROL
);
io_delay
();
io_delay
();
outb
(
LP_CONTROL_NEGATE_STROBE
,
LP_PORT_CONTROL
);
io_delay
();
io_delay
();
for
(
i
=
1000000
;
!
(
inb
(
LP_PORT_STATUS
)
&
LP_MASK_nBUSY
);
io_delay
())
if
(
!--
i
)
return
;
}
outb
(
*
s
++
,
LP_PORT_DATA
);
io_delay
();
io_delay
();
outb
(
LP_CONTROL_ASSERT_STROBE
,
LP_PORT_CONTROL
);
io_delay
();
io_delay
();
outb
(
LP_CONTROL_NEGATE_STROBE
,
LP_PORT_CONTROL
);
io_delay
();
io_delay
();
--
count
;
}
}
static
struct
console
lp_old98_console
=
{
.
name
=
"lp_old98"
,
.
write
=
lp_old98_console_write
,
.
flags
=
CON_PRINTBUFFER
,
.
index
=
-
1
,
};
#endif
/* console on lp_old98 */
static
int
__init
lp_old98_init
(
void
)
{
char
*
errmsg
=
"I/O ports already occupied, giving up."
;
#ifdef PC98_HW_H98
if
(
pc98_hw_flags
&
PC98_HW_H98
)
if
(
!
request_region
(
LP_PORT_H98MODE
,
1
,
"lp_old98"
)
goto
err1
;
#endif
if
(
!
request_region
(
LP_PORT_DATA
,
1
,
"lp_old98"
))
goto
err2
;
if
(
!
request_region
(
LP_PORT_STATUS
,
1
,
"lp_old98"
))
goto
err3
;
if
(
!
request_region
(
LP_PORT_STROBE
,
1
,
"lp_old98"
))
goto
err4
;
if
(
!
request_region
(
LP_PORT_EXTMODE
,
1
,
"lp_old98"
))
goto
err5
;
if
(
!
register_chrdev
(
LP_MAJOR
,
"lp"
,
&
lp_old98_fops
))
{
#ifdef CONFIG_PC9800_OLDLP_CONSOLE
register_console
(
&
lp_old98_console
);
printk
(
KERN_INFO
"lp_old98: console ready
\n
"
);
#endif
/*
* rest are not needed by this driver,
* but for locking out other printer drivers...
*/
lp_old98_init_device
();
return
0
;
}
else
errmsg
=
"unable to register device"
;
release_region
(
LP_PORT_EXTMODE
,
1
);
err5:
release_region
(
LP_PORT_STROBE
,
1
);
err4:
release_region
(
LP_PORT_STATUS
,
1
);
err3:
release_region
(
LP_PORT_DATA
,
1
);
err2:
#ifdef PC98_HW_H98
if
(
pc98_hw_flags
&
PC98_HW_H98
)
release_region
(
LP_PORT_H98MODE
,
1
);
err1:
#endif
printk
(
KERN_ERR
"lp_old98: %s
\n
"
,
errmsg
);
return
-
EBUSY
;
}
static
void
__exit
lp_old98_exit
(
void
)
{
#ifdef CONFIG_PC9800_OLDLP_CONSOLE
unregister_console
(
&
lp_old98_console
);
#endif
unregister_chrdev
(
LP_MAJOR
,
"lp"
);
release_region
(
LP_PORT_DATA
,
1
);
release_region
(
LP_PORT_STATUS
,
1
);
release_region
(
LP_PORT_STROBE
,
1
);
#ifdef PC98_HW_H98
if
(
pc98_hw_flags
&
PC98_HW_H98
)
release_region
(
LP_PORT_H98MODE
,
1
);
#endif
release_region
(
LP_PORT_EXTMODE
,
1
);
}
#ifndef MODULE
static
int
__init
lp_old98_setup
(
char
*
str
)
{
int
ints
[
4
];
str
=
get_options
(
str
,
ARRAY_SIZE
(
ints
),
ints
);
if
(
ints
[
0
]
>
0
)
dc1_check
=
ints
[
1
];
return
1
;
}
__setup
(
"lp_old98_dc1_check="
,
lp_old98_setup
);
#endif
MODULE_PARM
(
dc1_check
,
"i"
);
MODULE_AUTHOR
(
"Kousuke Takai <tak@kmc.kyoto-u.ac.jp>"
);
MODULE_DESCRIPTION
(
"PC-9800 old printer port driver"
);
MODULE_LICENSE
(
"GPL"
);
module_init
(
lp_old98_init
);
module_exit
(
lp_old98_exit
);
drivers/char/upd4990a.c
deleted
100644 → 0
View file @
bffc8f71
/*
* NEC PC-9800 Real Time Clock interface for Linux
*
* Copyright (C) 1997-2001 Linux/98 project,
* Kyoto University Microcomputer Club.
*
* Based on:
* drivers/char/rtc.c by Paul Gortmaker
*
* Changes:
* 2001-02-09 Call check_region on rtc_init and do not request I/O 0033h.
* Call del_timer and release_region on rtc_exit. -- tak
* 2001-07-14 Rewrite <linux/upd4990a.h> and split to <linux/upd4990a.h>
* and <asm-i386/upd4990a.h>.
* Introduce a lot of spin_lock/unlock (&rtc_lock).
*/
#define RTC98_VERSION "1.2"
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/miscdevice.h>
#include <linux/ioport.h>
#include <linux/fcntl.h>
#include <linux/rtc.h>
#include <linux/bcd.h>
#include <linux/upd4990a.h>
#include <linux/init.h>
#include <linux/poll.h>
#include <linux/proc_fs.h>
#include <linux/spinlock.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/system.h>
/*
* We sponge a minor off of the misc major. No need slurping
* up another valuable major dev number for this. If you add
* an ioctl, make sure you don't conflict with SPARC's RTC
* ioctls.
*/
static
struct
fasync_struct
*
rtc_async_queue
;
static
DECLARE_WAIT_QUEUE_HEAD
(
rtc_wait
);
static
struct
timer_list
rtc_uie_timer
;
static
u8
old_refclk
;
static
int
rtc_ioctl
(
struct
inode
*
inode
,
struct
file
*
file
,
unsigned
int
cmd
,
unsigned
long
arg
);
static
int
rtc_read_proc
(
char
*
page
,
char
**
start
,
off_t
off
,
int
count
,
int
*
eof
,
void
*
data
);
/*
* Bits in rtc_status. (5 bits of room for future expansion)
*/
#define RTC_IS_OPEN 0x01
/* means /dev/rtc is in use */
#define RTC_TIMER_ON 0x02
/* not used */
#define RTC_UIE_TIMER_ON 0x04
/* UIE emulation timer is active */
/*
* rtc_status is never changed by rtc_interrupt, and ioctl/open/close is
* protected by the big kernel lock. However, ioctl can still disable the timer
* in rtc_status and then with del_timer after the interrupt has read
* rtc_status but before mod_timer is called, which would then reenable the
* timer (but you would need to have an awful timing before you'd trip on it)
*/
static
unsigned
char
rtc_status
;
/* bitmapped status byte. */
static
unsigned
long
rtc_irq_data
;
/* our output to the world */
static
const
unsigned
char
days_in_mo
[]
=
{
31
,
28
,
31
,
30
,
31
,
30
,
31
,
31
,
30
,
31
,
30
,
31
};
extern
spinlock_t
rtc_lock
;
/* defined in arch/i386/kernel/time.c */
static
void
rtc_uie_intr
(
unsigned
long
data
)
{
u8
refclk
,
tmp
;
/* Kernel timer does del_timer internally before calling
each timer entry, so this is unnecessary.
del_timer(&rtc_uie_timer); */
spin_lock
(
&
rtc_lock
);
/* Detect rising edge of 1Hz reference clock. */
refclk
=
UPD4990A_READ_DATA
();
tmp
=
old_refclk
&
refclk
;
old_refclk
=
~
refclk
;
if
(
!
(
tmp
&
1
))
rtc_irq_data
+=
0x100
;
spin_unlock
(
&
rtc_lock
);
if
(
!
(
tmp
&
1
))
{
/* Now do the rest of the actions */
wake_up_interruptible
(
&
rtc_wait
);
kill_fasync
(
&
rtc_async_queue
,
SIGIO
,
POLL_IN
);
}
rtc_uie_timer
.
expires
=
jiffies
+
1
;
add_timer
(
&
rtc_uie_timer
);
}
/*
* Now all the various file operations that we export.
*/
static
ssize_t
rtc_read
(
struct
file
*
file
,
char
*
buf
,
size_t
count
,
loff_t
*
ppos
)
{
DECLARE_WAITQUEUE
(
wait
,
current
);
unsigned
long
data
;
ssize_t
retval
=
0
;
if
(
count
<
sizeof
(
unsigned
long
))
return
-
EINVAL
;
add_wait_queue
(
&
rtc_wait
,
&
wait
);
set_current_state
(
TASK_INTERRUPTIBLE
);
do
{
/* First make it right. Then make it fast. Putting this whole
* block within the parentheses of a while would be too
* confusing. And no, xchg() is not the answer. */
spin_lock_irq
(
&
rtc_lock
);
data
=
rtc_irq_data
;
rtc_irq_data
=
0
;
spin_unlock_irq
(
&
rtc_lock
);
if
(
data
!=
0
)
break
;
if
(
file
->
f_flags
&
O_NONBLOCK
)
{
retval
=
-
EAGAIN
;
goto
out
;
}
if
(
signal_pending
(
current
))
{
retval
=
-
ERESTARTSYS
;
goto
out
;
}
schedule
();
}
while
(
1
);
retval
=
put_user
(
data
,
(
unsigned
long
*
)
buf
);
if
(
!
retval
)
retval
=
sizeof
(
unsigned
long
);
out:
set_current_state
(
TASK_RUNNING
);
remove_wait_queue
(
&
rtc_wait
,
&
wait
);
return
retval
;
}
static
int
rtc_ioctl
(
struct
inode
*
inode
,
struct
file
*
file
,
unsigned
int
cmd
,
unsigned
long
arg
)
{
struct
rtc_time
wtime
;
struct
upd4990a_raw_data
raw
;
switch
(
cmd
)
{
case
RTC_UIE_OFF
:
/* Mask ints from RTC updates. */
spin_lock_irq
(
&
rtc_lock
);
if
(
rtc_status
&
RTC_UIE_TIMER_ON
)
{
rtc_status
&=
~
RTC_UIE_TIMER_ON
;
del_timer
(
&
rtc_uie_timer
);
}
spin_unlock_irq
(
&
rtc_lock
);
return
0
;
case
RTC_UIE_ON
:
/* Allow ints for RTC updates. */
spin_lock_irq
(
&
rtc_lock
);
rtc_irq_data
=
0
;
if
(
!
(
rtc_status
&
RTC_UIE_TIMER_ON
))
{
rtc_status
|=
RTC_UIE_TIMER_ON
;
rtc_uie_timer
.
expires
=
jiffies
+
1
;
add_timer
(
&
rtc_uie_timer
);
}
/* Just in case... */
upd4990a_serial_command
(
UPD4990A_REGISTER_HOLD
);
old_refclk
=
~
UPD4990A_READ_DATA
();
spin_unlock_irq
(
&
rtc_lock
);
return
0
;
case
RTC_RD_TIME
:
/* Read the time/date from RTC */
spin_lock_irq
(
&
rtc_lock
);
upd4990a_get_time
(
&
raw
,
0
);
spin_unlock_irq
(
&
rtc_lock
);
wtime
.
tm_sec
=
BCD2BIN
(
raw
.
sec
);
wtime
.
tm_min
=
BCD2BIN
(
raw
.
min
);
wtime
.
tm_hour
=
BCD2BIN
(
raw
.
hour
);
wtime
.
tm_mday
=
BCD2BIN
(
raw
.
mday
);
wtime
.
tm_mon
=
raw
.
mon
-
1
;
/* convert to 0-base */
wtime
.
tm_wday
=
raw
.
wday
;
/*
* Account for differences between how the RTC uses the values
* and how they are defined in a struct rtc_time;
*/
if
((
wtime
.
tm_year
=
BCD2BIN
(
raw
.
year
))
<
95
)
wtime
.
tm_year
+=
100
;
wtime
.
tm_isdst
=
0
;
break
;
case
RTC_SET_TIME
:
/* Set the RTC */
{
int
leap_yr
;
if
(
!
capable
(
CAP_SYS_TIME
))
return
-
EACCES
;
if
(
copy_from_user
(
&
wtime
,
(
struct
rtc_time
*
)
arg
,
sizeof
(
struct
rtc_time
)))
return
-
EFAULT
;
/* Valid year is 1995 - 2094, inclusive. */
if
(
wtime
.
tm_year
<
95
||
wtime
.
tm_year
>
194
)
return
-
EINVAL
;
if
(
wtime
.
tm_mon
>
11
||
wtime
.
tm_mday
==
0
)
return
-
EINVAL
;
/* For acceptable year domain (1995 - 2094),
this IS sufficient. */
leap_yr
=
!
(
wtime
.
tm_year
%
4
);
if
(
wtime
.
tm_mday
>
(
days_in_mo
[
wtime
.
tm_mon
]
+
(
wtime
.
tm_mon
==
2
&&
leap_yr
)))
return
-
EINVAL
;
if
(
wtime
.
tm_hour
>=
24
||
wtime
.
tm_min
>=
60
||
wtime
.
tm_sec
>=
60
)
return
-
EINVAL
;
if
(
wtime
.
tm_wday
>
6
)
return
-
EINVAL
;
raw
.
sec
=
BIN2BCD
(
wtime
.
tm_sec
);
raw
.
min
=
BIN2BCD
(
wtime
.
tm_min
);
raw
.
hour
=
BIN2BCD
(
wtime
.
tm_hour
);
raw
.
mday
=
BIN2BCD
(
wtime
.
tm_mday
);
raw
.
mon
=
wtime
.
tm_mon
+
1
;
raw
.
wday
=
wtime
.
tm_wday
;
raw
.
year
=
BIN2BCD
(
wtime
.
tm_year
%
100
);
spin_lock_irq
(
&
rtc_lock
);
upd4990a_set_time
(
&
raw
,
0
);
spin_unlock_irq
(
&
rtc_lock
);
return
0
;
}
default:
return
-
EINVAL
;
}
return
copy_to_user
((
void
*
)
arg
,
&
wtime
,
sizeof
wtime
)
?
-
EFAULT
:
0
;
}
/*
* We enforce only one user at a time here with the open/close.
* Also clear the previous interrupt data on an open, and clean
* up things on a close.
*/
static
int
rtc_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
spin_lock_irq
(
&
rtc_lock
);
if
(
rtc_status
&
RTC_IS_OPEN
)
goto
out_busy
;
rtc_status
|=
RTC_IS_OPEN
;
rtc_irq_data
=
0
;
spin_unlock_irq
(
&
rtc_lock
);
return
0
;
out_busy:
spin_unlock_irq
(
&
rtc_lock
);
return
-
EBUSY
;
}
static
int
rtc_fasync
(
int
fd
,
struct
file
*
filp
,
int
on
)
{
return
fasync_helper
(
fd
,
filp
,
on
,
&
rtc_async_queue
);
}
static
int
rtc_release
(
struct
inode
*
inode
,
struct
file
*
file
)
{
del_timer
(
&
rtc_uie_timer
);
if
(
file
->
f_flags
&
FASYNC
)
rtc_fasync
(
-
1
,
file
,
0
);
rtc_irq_data
=
0
;
/* No need for locking -- nobody else can do anything until this rmw is
* committed, and no timer is running. */
rtc_status
&=
~
(
RTC_IS_OPEN
|
RTC_UIE_TIMER_ON
);
return
0
;
}
static
unsigned
int
rtc_poll
(
struct
file
*
file
,
poll_table
*
wait
)
{
unsigned
long
l
;
poll_wait
(
file
,
&
rtc_wait
,
wait
);
spin_lock_irq
(
&
rtc_lock
);
l
=
rtc_irq_data
;
spin_unlock_irq
(
&
rtc_lock
);
if
(
l
!=
0
)
return
POLLIN
|
POLLRDNORM
;
return
0
;
}
/*
* The various file operations we support.
*/
static
struct
file_operations
rtc_fops
=
{
.
owner
=
THIS_MODULE
,
.
read
=
rtc_read
,
.
poll
=
rtc_poll
,
.
ioctl
=
rtc_ioctl
,
.
open
=
rtc_open
,
.
release
=
rtc_release
,
.
fasync
=
rtc_fasync
,
};
static
struct
miscdevice
rtc_dev
=
{
.
minor
=
RTC_MINOR
,
.
name
=
"rtc"
,
.
fops
=
&
rtc_fops
,
};
static
int
__init
rtc_init
(
void
)
{
int
err
=
0
;
if
(
!
request_region
(
UPD4990A_IO
,
1
,
"rtc"
))
{
printk
(
KERN_ERR
"upd4990a: could not acquire I/O port %#x
\n
"
,
UPD4990A_IO
);
return
-
EBUSY
;
}
err
=
misc_register
(
&
rtc_dev
);
if
(
err
)
{
printk
(
KERN_ERR
"upd4990a: can't misc_register() on minor=%d
\n
"
,
RTC_MINOR
);
release_region
(
UPD4990A_IO
,
1
);
return
err
;
}
#if 0
printk(KERN_INFO "\xB6\xDA\xDD\xC0\xDE \xC4\xDE\xB9\xB2 Driver\n"); /* Calender Clock Driver */
#else
printk
(
KERN_INFO
"Real Time Clock driver for NEC PC-9800 v"
RTC98_VERSION
"
\n
"
);
#endif
create_proc_read_entry
(
"driver/rtc"
,
0
,
NULL
,
rtc_read_proc
,
NULL
);
init_timer
(
&
rtc_uie_timer
);
rtc_uie_timer
.
function
=
rtc_uie_intr
;
return
0
;
}
module_init
(
rtc_init
);
static
void
__exit
rtc_exit
(
void
)
{
del_timer
(
&
rtc_uie_timer
);
release_region
(
UPD4990A_IO
,
1
);
remove_proc_entry
(
"driver/rtc"
,
NULL
);
misc_deregister
(
&
rtc_dev
);
}
module_exit
(
rtc_exit
);
/*
* Info exported via "/proc/driver/rtc".
*/
static
inline
int
rtc_get_status
(
char
*
buf
)
{
char
*
p
;
unsigned
int
year
;
struct
upd4990a_raw_data
data
;
p
=
buf
;
upd4990a_get_time
(
&
data
,
0
);
/*
* There is no way to tell if the luser has the RTC set for local
* time or for Universal Standard Time (GMT). Probably local though.
*/
if
((
year
=
BCD2BIN
(
data
.
year
)
+
1900
)
<
1995
)
year
+=
100
;
p
+=
sprintf
(
p
,
"rtc_time
\t
: %02d:%02d:%02d
\n
"
"rtc_date
\t
: %04d-%02d-%02d
\n
"
,
BCD2BIN
(
data
.
hour
),
BCD2BIN
(
data
.
min
),
BCD2BIN
(
data
.
sec
),
year
,
data
.
mon
,
BCD2BIN
(
data
.
mday
));
return
p
-
buf
;
}
static
int
rtc_read_proc
(
char
*
page
,
char
**
start
,
off_t
off
,
int
count
,
int
*
eof
,
void
*
data
)
{
int
len
=
rtc_get_status
(
page
);
if
(
len
<=
off
+
count
)
*
eof
=
1
;
*
start
=
page
+
off
;
len
-=
off
;
if
(
len
>
count
)
len
=
count
;
if
(
len
<
0
)
len
=
0
;
return
len
;
}
drivers/ide/legacy/hd98.c
deleted
100644 → 0
View file @
bffc8f71
/*
* Copyright (C) 1991, 1992 Linus Torvalds
*
* This is the low-level hd interrupt support. It traverses the
* request-list, using interrupts to jump between functions. As
* all the functions are called within interrupts, we may not
* sleep. Special care is recommended.
*
* modified by Drew Eckhardt to check nr of hd's from the CMOS.
*
* Thanks to Branko Lankester, lankeste@fwi.uva.nl, who found a bug
* in the early extended-partition checks and added DM partitions
*
* IRQ-unmask, drive-id, multiple-mode, support for ">16 heads",
* and general streamlining by Mark Lord.
*
* Removed 99% of above. Use Mark's ide driver for those options.
* This is now a lightweight ST-506 driver. (Paul Gortmaker)
*
* Modified 1995 Russell King for ARM processor.
*
* Bugfix: max_sectors must be <= 255 or the wheels tend to come
* off in a hurry once you queue things up - Paul G. 02/2001
*/
/* Uncomment the following if you want verbose error reports. */
/* #define VERBOSE_ERRORS */
#include <linux/errno.h>
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/timer.h>
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/genhd.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/ioport.h>
#include <linux/mc146818rtc.h>
/* CMOS defines */
#include <linux/init.h>
#include <linux/blkpg.h>
#include <linux/hdreg.h>
#define REALLY_SLOW_IO
#include <asm/system.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include "io_ports.h"
#ifdef __arm__
#undef HD_IRQ
#endif
#include <asm/irq.h>
#ifdef __arm__
#define HD_IRQ IRQ_HARDDISK
#endif
/* Hd controller regster ports */
#define HD_DATA 0x640
/* _CTL when writing */
#define HD_ERROR 0x642
/* see err-bits */
#define HD_NSECTOR 0x644
/* nr of sectors to read/write */
#define HD_SECTOR 0x646
/* starting sector */
#define HD_LCYL 0x648
/* starting cylinder */
#define HD_HCYL 0x64a
/* high byte of starting cyl */
#define HD_CURRENT 0x64c
/* 101dhhhh , d=drive, hhhh=head */
#define HD_STATUS 0x64e
/* see status-bits */
#define HD_FEATURE HD_ERROR
/* same io address, read=error, write=feature */
#define HD_PRECOMP HD_FEATURE
/* obsolete use of this port - predates IDE */
#define HD_COMMAND HD_STATUS
/* same io address, read=status, write=cmd */
#define HD_CMD 0x74c
/* used for resets */
#define HD_ALTSTATUS 0x74c
/* same as HD_STATUS but doesn't clear irq */
/* Bits of HD_STATUS */
#define ERR_STAT 0x01
#define INDEX_STAT 0x02
#define ECC_STAT 0x04
/* Corrected error */
#define DRQ_STAT 0x08
#define SEEK_STAT 0x10
#define SERVICE_STAT SEEK_STAT
#define WRERR_STAT 0x20
#define READY_STAT 0x40
#define BUSY_STAT 0x80
/* Bits for HD_ERROR */
#define MARK_ERR 0x01
/* Bad address mark */
#define TRK0_ERR 0x02
/* couldn't find track 0 */
#define ABRT_ERR 0x04
/* Command aborted */
#define MCR_ERR 0x08
/* media change request */
#define ID_ERR 0x10
/* ID field not found */
#define MC_ERR 0x20
/* media changed */
#define ECC_ERR 0x40
/* Uncorrectable ECC error */
#define BBD_ERR 0x80
/* pre-EIDE meaning: block marked bad */
#define ICRC_ERR 0x80
/* new meaning: CRC error during transfer */
static
spinlock_t
hd_lock
=
SPIN_LOCK_UNLOCKED
;
static
struct
request_queue
*
hd_queue
;
#define CURRENT elv_next_request(hd_queue)
#define TIMEOUT_VALUE (6*HZ)
#define HD_DELAY 0
#define MAX_ERRORS 16
/* Max read/write errors/sector */
#define RESET_FREQ 8
/* Reset controller every 8th retry */
#define RECAL_FREQ 4
/* Recalibrate every 4th retry */
#define MAX_HD 2
#define STAT_OK (READY_STAT|SEEK_STAT)
#define OK_STATUS(s) (((s)&(STAT_OK|(BUSY_STAT|WRERR_STAT|ERR_STAT)))==STAT_OK)
static
void
recal_intr
(
void
);
static
void
bad_rw_intr
(
void
);
static
int
reset
;
static
int
hd_error
;
/*
* This struct defines the HD's and their types.
*/
struct
hd_i_struct
{
unsigned
int
head
,
sect
,
cyl
,
wpcom
,
lzone
,
ctl
;
int
unit
;
int
recalibrate
;
int
special_op
;
};
#ifdef HD_TYPE
static
struct
hd_i_struct
hd_info
[]
=
{
HD_TYPE
};
static
int
NR_HD
=
((
sizeof
(
hd_info
))
/
(
sizeof
(
struct
hd_i_struct
)));
#else
static
struct
hd_i_struct
hd_info
[
MAX_HD
];
static
int
NR_HD
;
#endif
static
struct
gendisk
*
hd_gendisk
[
MAX_HD
];
static
struct
timer_list
device_timer
;
#define TIMEOUT_VALUE (6*HZ)
#define SET_TIMER \
do { \
mod_timer(&device_timer, jiffies + TIMEOUT_VALUE); \
} while (0)
static
void
(
*
do_hd
)(
void
)
=
NULL
;
#define SET_HANDLER(x) \
if ((do_hd = (x)) != NULL) \
SET_TIMER; \
else \
del_timer(&device_timer);
#if (HD_DELAY > 0)
unsigned
long
last_req
;
unsigned
long
read_timer
(
void
)
{
extern
spinlock_t
i8253_lock
;
unsigned
long
t
,
flags
;
int
i
;
spin_lock_irqsave
(
&
i8253_lock
,
flags
);
t
=
jiffies
*
11932
;
outb_p
(
0
,
PIT_MODE
);
i
=
inb_p
(
PIT_CH0
);
i
|=
inb
(
PIT_CH0
)
<<
8
;
spin_unlock_irqrestore
(
&
i8253_lock
,
flags
);
return
(
t
-
i
);
}
#endif
void
__init
hd_setup
(
char
*
str
,
int
*
ints
)
{
int
hdind
=
0
;
if
(
ints
[
0
]
!=
3
)
return
;
if
(
hd_info
[
0
].
head
!=
0
)
hdind
=
1
;
hd_info
[
hdind
].
head
=
ints
[
2
];
hd_info
[
hdind
].
sect
=
ints
[
3
];
hd_info
[
hdind
].
cyl
=
ints
[
1
];
hd_info
[
hdind
].
wpcom
=
0
;
hd_info
[
hdind
].
lzone
=
ints
[
1
];
hd_info
[
hdind
].
ctl
=
(
ints
[
2
]
>
8
?
8
:
0
);
NR_HD
=
hdind
+
1
;
}
static
void
dump_status
(
const
char
*
msg
,
unsigned
int
stat
)
{
char
*
name
=
CURRENT
?
CURRENT
->
rq_dev
->
bd_disk
->
disk_name
:
"hd?"
;
#ifdef VERBOSE_ERRORS
printk
(
"%s: %s: status=0x%02x { "
,
name
,
msg
,
stat
&
0xff
);
if
(
stat
&
BUSY_STAT
)
printk
(
"Busy "
);
if
(
stat
&
READY_STAT
)
printk
(
"DriveReady "
);
if
(
stat
&
WRERR_STAT
)
printk
(
"WriteFault "
);
if
(
stat
&
SEEK_STAT
)
printk
(
"SeekComplete "
);
if
(
stat
&
DRQ_STAT
)
printk
(
"DataRequest "
);
if
(
stat
&
ECC_STAT
)
printk
(
"CorrectedError "
);
if
(
stat
&
INDEX_STAT
)
printk
(
"Index "
);
if
(
stat
&
ERR_STAT
)
printk
(
"Error "
);
printk
(
"}
\n
"
);
if
((
stat
&
ERR_STAT
)
==
0
)
{
hd_error
=
0
;
}
else
{
hd_error
=
inb
(
HD_ERROR
);
printk
(
"%s: %s: error=0x%02x { "
,
name
,
msg
,
hd_error
&
0xff
);
if
(
hd_error
&
BBD_ERR
)
printk
(
"BadSector "
);
if
(
hd_error
&
ECC_ERR
)
printk
(
"UncorrectableError "
);
if
(
hd_error
&
ID_ERR
)
printk
(
"SectorIdNotFound "
);
if
(
hd_error
&
ABRT_ERR
)
printk
(
"DriveStatusError "
);
if
(
hd_error
&
TRK0_ERR
)
printk
(
"TrackZeroNotFound "
);
if
(
hd_error
&
MARK_ERR
)
printk
(
"AddrMarkNotFound "
);
printk
(
"}"
);
if
(
hd_error
&
(
BBD_ERR
|
ECC_ERR
|
ID_ERR
|
MARK_ERR
))
{
printk
(
", CHS=%d/%d/%d"
,
(
inb
(
HD_HCYL
)
<<
8
)
+
inb
(
HD_LCYL
),
inb
(
HD_CURRENT
)
&
0xf
,
inb
(
HD_SECTOR
));
if
(
CURRENT
)
printk
(
", sector=%ld"
,
CURRENT
->
sector
);
}
printk
(
"
\n
"
);
}
#else
printk
(
"%s: %s: status=0x%02x.
\n
"
,
name
,
msg
,
stat
&
0xff
);
if
((
stat
&
ERR_STAT
)
==
0
)
{
hd_error
=
0
;
}
else
{
hd_error
=
inb
(
HD_ERROR
);
printk
(
"%s: %s: error=0x%02x.
\n
"
,
name
,
msg
,
hd_error
&
0xff
);
}
#endif
}
void
check_status
(
void
)
{
int
i
=
inb
(
HD_STATUS
);
if
(
!
OK_STATUS
(
i
))
{
dump_status
(
"check_status"
,
i
);
bad_rw_intr
();
}
}
static
int
controller_busy
(
void
)
{
int
retries
=
100000
;
unsigned
char
status
;
do
{
status
=
inb
(
HD_STATUS
);
}
while
((
status
&
BUSY_STAT
)
&&
--
retries
);
return
status
;
}
static
int
status_ok
(
void
)
{
unsigned
char
status
=
inb
(
HD_STATUS
);
if
(
status
&
BUSY_STAT
)
return
1
;
/* Ancient, but does it make sense??? */
if
(
status
&
WRERR_STAT
)
return
0
;
if
(
!
(
status
&
READY_STAT
))
return
0
;
if
(
!
(
status
&
SEEK_STAT
))
return
0
;
return
1
;
}
static
int
controller_ready
(
unsigned
int
drive
,
unsigned
int
head
)
{
int
retry
=
100
;
do
{
if
(
controller_busy
()
&
BUSY_STAT
)
return
0
;
outb
(
0xA0
|
(
drive
<<
4
)
|
head
,
HD_CURRENT
);
if
(
status_ok
())
return
1
;
}
while
(
--
retry
);
return
0
;
}
static
void
hd_out
(
struct
hd_i_struct
*
disk
,
unsigned
int
nsect
,
unsigned
int
sect
,
unsigned
int
head
,
unsigned
int
cyl
,
unsigned
int
cmd
,
void
(
*
intr_addr
)(
void
))
{
unsigned
short
port
;
#if (HD_DELAY > 0)
while
(
read_timer
()
-
last_req
<
HD_DELAY
)
/* nothing */
;
#endif
if
(
reset
)
return
;
if
(
!
controller_ready
(
disk
->
unit
,
head
))
{
reset
=
1
;
return
;
}
SET_HANDLER
(
intr_addr
);
outb
(
disk
->
ctl
,
HD_CMD
);
port
=
HD_DATA
+
2
;
outb
(
disk
->
wpcom
>>
2
,
port
);
port
+=
2
;
outb
(
nsect
,
port
);
port
+=
2
;
outb
(
sect
,
port
);
port
+=
2
;
outb
(
cyl
,
port
);
port
+=
2
;
outb
(
cyl
>>
8
,
port
);
port
+=
2
;
outb
(
0xA0
|
(
disk
->
unit
<<
4
)
|
head
,
port
);
port
+=
2
;
outb
(
cmd
,
port
);
}
static
void
hd_request
(
void
);
static
int
drive_busy
(
void
)
{
unsigned
int
i
;
unsigned
char
c
;
for
(
i
=
0
;
i
<
500000
;
i
++
)
{
c
=
inb
(
HD_STATUS
);
if
((
c
&
(
BUSY_STAT
|
READY_STAT
|
SEEK_STAT
))
==
STAT_OK
)
return
0
;
}
dump_status
(
"reset timed out"
,
c
);
return
1
;
}
static
void
reset_controller
(
void
)
{
int
i
;
outb
(
4
,
HD_CMD
);
for
(
i
=
0
;
i
<
1000
;
i
++
)
barrier
();
outb
(
hd_info
[
0
].
ctl
&
0x0f
,
HD_CMD
);
for
(
i
=
0
;
i
<
1000
;
i
++
)
barrier
();
if
(
drive_busy
())
printk
(
"hd: controller still busy
\n
"
);
else
if
((
hd_error
=
inb
(
HD_ERROR
))
!=
1
)
printk
(
"hd: controller reset failed: %02x
\n
"
,
hd_error
);
}
static
void
reset_hd
(
void
)
{
static
int
i
;
repeat:
if
(
reset
)
{
reset
=
0
;
i
=
-
1
;
reset_controller
();
}
else
{
check_status
();
if
(
reset
)
goto
repeat
;
}
if
(
++
i
<
NR_HD
)
{
struct
hd_i_struct
*
disk
=
&
hd_info
[
i
];
disk
->
special_op
=
disk
->
recalibrate
=
1
;
hd_out
(
disk
,
disk
->
sect
,
disk
->
sect
,
disk
->
head
-
1
,
disk
->
cyl
,
WIN_SPECIFY
,
&
reset_hd
);
if
(
reset
)
goto
repeat
;
}
else
hd_request
();
}
/*
* Ok, don't know what to do with the unexpected interrupts: on some machines
* doing a reset and a retry seems to result in an eternal loop. Right now I
* ignore it, and just set the timeout.
*
* On laptops (and "green" PCs), an unexpected interrupt occurs whenever the
* drive enters "idle", "standby", or "sleep" mode, so if the status looks
* "good", we just ignore the interrupt completely.
*/
void
unexpected_hd_interrupt
(
void
)
{
unsigned
int
stat
=
inb
(
HD_STATUS
);
if
(
stat
&
(
BUSY_STAT
|
DRQ_STAT
|
ECC_STAT
|
ERR_STAT
))
{
dump_status
(
"unexpected interrupt"
,
stat
);
SET_TIMER
;
}
}
/*
* bad_rw_intr() now tries to be a bit smarter and does things
* according to the error returned by the controller.
* -Mika Liljeberg (liljeber@cs.Helsinki.FI)
*/
static
void
bad_rw_intr
(
void
)
{
struct
request
*
req
=
CURRENT
;
struct
hd_i_struct
*
disk
;
if
(
!
req
)
return
;
disk
=
req
->
rq_disk
->
private_data
;
if
(
++
req
->
errors
>=
MAX_ERRORS
||
(
hd_error
&
BBD_ERR
))
{
end_request
(
req
,
0
);
disk
->
special_op
=
disk
->
recalibrate
=
1
;
}
else
if
(
req
->
errors
%
RESET_FREQ
==
0
)
reset
=
1
;
else
if
((
hd_error
&
TRK0_ERR
)
||
req
->
errors
%
RECAL_FREQ
==
0
)
disk
->
special_op
=
disk
->
recalibrate
=
1
;
/* Otherwise just retry */
}
static
inline
int
wait_DRQ
(
void
)
{
int
retries
=
100000
,
stat
;
while
(
--
retries
>
0
)
if
((
stat
=
inb
(
HD_STATUS
))
&
DRQ_STAT
)
return
0
;
dump_status
(
"wait_DRQ"
,
stat
);
return
-
1
;
}
static
void
read_intr
(
void
)
{
int
i
,
retries
=
100000
;
struct
request
*
req
;
do
{
i
=
(
unsigned
)
inb
(
HD_STATUS
);
if
(
i
&
BUSY_STAT
)
continue
;
if
(
!
OK_STATUS
(
i
))
break
;
if
(
i
&
DRQ_STAT
)
goto
ok_to_read
;
}
while
(
--
retries
>
0
);
dump_status
(
"read_intr"
,
i
);
bad_rw_intr
();
hd_request
();
return
;
ok_to_read:
req
=
CURRENT
;
insw
(
HD_DATA
,
req
->
buffer
,
256
);
req
->
sector
++
;
req
->
buffer
+=
512
;
req
->
errors
=
0
;
i
=
--
req
->
nr_sectors
;
--
req
->
current_nr_sectors
;
#ifdef DEBUG
printk
(
"%s: read: sector %ld, remaining = %ld, buffer=%p
\n
"
,
req
->
rq_disk
->
disk_name
,
req
->
sector
,
req
->
nr_sectors
,
req
->
buffer
+
512
);
#endif
if
(
req
->
current_nr_sectors
<=
0
)
end_request
(
req
,
1
);
if
(
i
>
0
)
{
SET_HANDLER
(
&
read_intr
);
return
;
}
(
void
)
inb
(
HD_STATUS
);
#if (HD_DELAY > 0)
last_req
=
read_timer
();
#endif
if
(
CURRENT
)
hd_request
();
return
;
}
static
void
write_intr
(
void
)
{
int
i
;
int
retries
=
100000
;
struct
request
*
req
=
CURRENT
;
do
{
i
=
(
unsigned
)
inb
(
HD_STATUS
);
if
(
i
&
BUSY_STAT
)
continue
;
if
(
!
OK_STATUS
(
i
))
break
;
if
((
req
->
nr_sectors
<=
1
)
||
(
i
&
DRQ_STAT
))
goto
ok_to_write
;
}
while
(
--
retries
>
0
);
dump_status
(
"write_intr"
,
i
);
bad_rw_intr
();
hd_request
();
return
;
ok_to_write:
req
->
sector
++
;
i
=
--
req
->
nr_sectors
;
--
req
->
current_nr_sectors
;
req
->
buffer
+=
512
;
if
(
!
i
||
(
req
->
bio
&&
req
->
current_nr_sectors
<
1
))
end_request
(
req
,
1
);
if
(
i
>
0
)
{
SET_HANDLER
(
&
write_intr
);
outsw
(
HD_DATA
,
req
->
buffer
,
256
);
local_irq_enable
();
}
else
{
#if (HD_DELAY > 0)
last_req
=
read_timer
();
#endif
hd_request
();
}
return
;
}
static
void
recal_intr
(
void
)
{
check_status
();
#if (HD_DELAY > 0)
last_req
=
read_timer
();
#endif
hd_request
();
}
/*
* This is another of the error-routines I don't know what to do with. The
* best idea seems to just set reset, and start all over again.
*/
static
void
hd_times_out
(
unsigned
long
dummy
)
{
do_hd
=
NULL
;
if
(
!
CURRENT
)
return
;
disable_irq
(
HD_IRQ
);
local_irq_enable
();
reset
=
1
;
printk
(
"%s: timeout
\n
"
,
CURRENT
->
rq_disk
->
disk_name
);
if
(
++
CURRENT
->
errors
>=
MAX_ERRORS
)
{
#ifdef DEBUG
printk
(
"%s: too many errors
\n
"
,
CURRENT
->
rq_disk
->
disk_name
);
#endif
end_request
(
CURRENT
,
0
);
}
local_irq_disable
();
hd_request
();
enable_irq
(
HD_IRQ
);
}
int
do_special_op
(
struct
hd_i_struct
*
disk
,
struct
request
*
req
)
{
if
(
disk
->
recalibrate
)
{
disk
->
recalibrate
=
0
;
hd_out
(
disk
,
disk
->
sect
,
0
,
0
,
0
,
WIN_RESTORE
,
&
recal_intr
);
return
reset
;
}
if
(
disk
->
head
>
16
)
{
printk
(
"%s: cannot handle device with more than 16 heads - giving up
\n
"
,
req
->
rq_disk
->
disk_name
);
end_request
(
req
,
0
);
}
disk
->
special_op
=
0
;
return
1
;
}
/*
* The driver enables interrupts as much as possible. In order to do this,
* (a) the device-interrupt is disabled before entering hd_request(),
* and (b) the timeout-interrupt is disabled before the sti().
*
* Interrupts are still masked (by default) whenever we are exchanging
* data/cmds with a drive, because some drives seem to have very poor
* tolerance for latency during I/O. The IDE driver has support to unmask
* interrupts for non-broken hardware, so use that driver if required.
*/
static
void
hd_request
(
void
)
{
unsigned
int
block
,
nsect
,
sec
,
track
,
head
,
cyl
;
struct
hd_i_struct
*
disk
;
struct
request
*
req
;
if
(
do_hd
)
return
;
repeat:
del_timer
(
&
device_timer
);
local_irq_enable
();
if
(
!
CURRENT
)
{
do_hd
=
NULL
;
return
;
}
req
=
CURRENT
;
if
(
reset
)
{
local_irq_disable
();
reset_hd
();
return
;
}
disk
=
req
->
rq_disk
->
private_data
;
block
=
req
->
sector
;
nsect
=
req
->
nr_sectors
;
if
(
block
>=
get_capacity
(
req
->
rq_disk
)
||
((
block
+
nsect
)
>
get_capacity
(
req
->
rq_disk
)))
{
printk
(
"%s: bad access: block=%d, count=%d
\n
"
,
req
->
rq_disk
->
disk_name
,
block
,
nsect
);
end_request
(
req
,
0
);
goto
repeat
;
}
if
(
disk
->
special_op
)
{
if
(
do_special_op
(
disk
,
req
))
goto
repeat
;
return
;
}
sec
=
block
%
disk
->
sect
+
1
;
track
=
block
/
disk
->
sect
;
head
=
track
%
disk
->
head
;
cyl
=
track
/
disk
->
head
;
#ifdef DEBUG
printk
(
"%s: %sing: CHS=%d/%d/%d, sectors=%d, buffer=%p
\n
"
,
req
->
rq_disk
->
disk_name
,
(
req
->
cmd
==
READ
)
?
"read"
:
"writ"
,
cyl
,
head
,
sec
,
nsect
,
req
->
buffer
);
#endif
if
(
req
->
flags
&
REQ_CMD
)
{
switch
(
rq_data_dir
(
req
))
{
case
READ
:
hd_out
(
disk
,
nsect
,
sec
,
head
,
cyl
,
WIN_READ
,
&
read_intr
);
if
(
reset
)
goto
repeat
;
break
;
case
WRITE
:
hd_out
(
disk
,
nsect
,
sec
,
head
,
cyl
,
WIN_WRITE
,
&
write_intr
);
if
(
reset
)
goto
repeat
;
if
(
wait_DRQ
())
{
bad_rw_intr
();
goto
repeat
;
}
outsw
(
HD_DATA
,
req
->
buffer
,
256
);
break
;
default:
printk
(
"unknown hd-command
\n
"
);
end_request
(
req
,
0
);
break
;
}
}
}
static
void
do_hd_request
(
request_queue_t
*
q
)
{
disable_irq
(
HD_IRQ
);
hd_request
();
enable_irq
(
HD_IRQ
);
}
static
int
hd_ioctl
(
struct
inode
*
inode
,
struct
file
*
file
,
unsigned
int
cmd
,
unsigned
long
arg
)
{
struct
hd_i_struct
*
disk
=
inode
->
i_bdev
->
bd_disk
->
private_data
;
struct
hd_geometry
*
loc
=
(
struct
hd_geometry
*
)
arg
;
struct
hd_geometry
g
;
if
(
cmd
!=
HDIO_GETGEO
)
return
-
EINVAL
;
if
(
!
loc
)
return
-
EINVAL
;
g
.
heads
=
disk
->
head
;
g
.
sectors
=
disk
->
sect
;
g
.
cylinders
=
disk
->
cyl
;
g
.
start
=
get_start_sect
(
inode
->
i_bdev
);
return
copy_to_user
(
loc
,
&
g
,
sizeof
g
)
?
-
EFAULT
:
0
;
}
/*
* Releasing a block device means we sync() it, so that it can safely
* be forgotten about...
*/
static
void
hd_interrupt
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
)
{
void
(
*
handler
)(
void
)
=
do_hd
;
do_hd
=
NULL
;
del_timer
(
&
device_timer
);
if
(
!
handler
)
handler
=
unexpected_hd_interrupt
;
handler
();
local_irq_enable
();
}
static
struct
block_device_operations
hd_fops
=
{
.
ioctl
=
hd_ioctl
,
};
/*
* This is the hard disk IRQ description. The SA_INTERRUPT in sa_flags
* means we run the IRQ-handler with interrupts disabled: this is bad for
* interrupt latency, but anything else has led to problems on some
* machines.
*
* We enable interrupts in some of the routines after making sure it's
* safe.
*/
static
int
__init
hd_init
(
void
)
{
int
drive
;
if
(
register_blkdev
(
HD_MAJOR
,
"hd"
))
{
printk
(
"hd: unable to get major %d for hard disk
\n
"
,
HD_MAJOR
);
return
-
1
;
}
hd_queue
=
blk_init_queue
(
do_hd_request
,
&
hd_lock
);
if
(
!
hd_queue
)
{
unregister_blkdev
(
HD_MAJOR
,
"hd"
);
return
-
1
;
}
blk_queue_max_sectors
(
hd_queue
,
255
);
init_timer
(
&
device_timer
);
device_timer
.
function
=
hd_times_out
;
blk_queue_hardsect_size
(
hd_queue
,
512
);
#ifdef __i386__
if
(
!
NR_HD
)
{
extern
struct
drive_info
drive_info
;
unsigned
char
*
BIOS
=
(
unsigned
char
*
)
&
drive_info
;
unsigned
long
flags
;
#ifndef CONFIG_X86_PC9800
int
cmos_disks
;
#endif
for
(
drive
=
0
;
drive
<
2
;
drive
++
)
{
hd_info
[
drive
].
cyl
=
*
(
unsigned
short
*
)
BIOS
;
hd_info
[
drive
].
head
=
*
(
3
+
BIOS
);
hd_info
[
drive
].
sect
=
*
(
2
+
BIOS
);
hd_info
[
drive
].
wpcom
=
0
;
hd_info
[
drive
].
ctl
=
*
(
3
+
BIOS
)
>
8
?
8
:
0
;
hd_info
[
drive
].
lzone
=
*
(
unsigned
short
*
)
BIOS
;
if
(
hd_info
[
drive
].
cyl
&&
NR_HD
==
drive
)
NR_HD
++
;
BIOS
+=
6
;
}
}
#endif
/* __i386__ */
#ifdef __arm__
if
(
!
NR_HD
)
{
/* We don't know anything about the drive. This means
* that you *MUST* specify the drive parameters to the
* kernel yourself.
*/
printk
(
"hd: no drives specified - use hd=cyl,head,sectors"
" on kernel command line
\n
"
);
}
#endif
if
(
!
NR_HD
)
goto
out
;
for
(
drive
=
0
;
drive
<
NR_HD
;
drive
++
)
{
struct
gendisk
*
disk
=
alloc_disk
(
64
);
struct
hd_i_struct
*
p
=
&
hd_info
[
drive
];
if
(
!
disk
)
goto
Enomem
;
disk
->
major
=
HD_MAJOR
;
disk
->
first_minor
=
drive
<<
6
;
disk
->
fops
=
&
hd_fops
;
sprintf
(
disk
->
disk_name
,
"hd%c"
,
'a'
+
drive
);
disk
->
private_data
=
p
;
set_capacity
(
disk
,
p
->
head
*
p
->
sect
*
p
->
cyl
);
disk
->
queue
=
hd_queue
;
p
->
unit
=
drive
;
hd_gendisk
[
drive
]
=
disk
;
printk
(
"%s: %luMB, CHS=%d/%d/%d
\n
"
,
disk
->
disk_name
,
(
unsigned
long
)
get_capacity
(
disk
)
/
2048
,
p
->
cyl
,
p
->
head
,
p
->
sect
);
}
if
(
request_irq
(
HD_IRQ
,
hd_interrupt
,
SA_INTERRUPT
,
"hd"
,
NULL
))
{
printk
(
"hd: unable to get IRQ%d for the hard disk driver
\n
"
,
HD_IRQ
);
goto
out1
;
}
if
(
!
request_region
(
HD_DATA
,
2
,
"hd(data)"
))
{
printk
(
KERN_WARNING
"hd: port 0x%x busy
\n
"
,
HD_DATA
);
NR_HD
=
0
;
free_irq
(
HD_IRQ
,
NULL
);
return
;
}
if
(
!
request_region
(
HD_DATA
+
2
,
1
,
"hd"
))
{
printk
(
KERN_WARNING
"hd: port 0x%x busy
\n
"
,
HD_DATA
);
goto
out2
;
}
if
(
!
request_region
(
HD_DATA
+
4
,
1
,
"hd"
))
{
printk
(
KERN_WARNING
"hd: port 0x%x busy
\n
"
,
HD_DATA
);
goto
out3
;
}
if
(
!
request_region
(
HD_DATA
+
6
,
1
,
"hd"
))
{
printk
(
KERN_WARNING
"hd: port 0x%x busy
\n
"
,
HD_DATA
);
goto
out4
;
}
if
(
!
request_region
(
HD_DATA
+
8
,
1
,
"hd"
))
{
printk
(
KERN_WARNING
"hd: port 0x%x busy
\n
"
,
HD_DATA
);
goto
out5
;
}
if
(
!
request_region
(
HD_DATA
+
10
,
1
,
"hd"
))
{
printk
(
KERN_WARNING
"hd: port 0x%x busy
\n
"
,
HD_DATA
);
goto
out6
;
}
if
(
!
request_region
(
HD_DATA
+
12
,
1
,
"hd"
))
{
printk
(
KERN_WARNING
"hd: port 0x%x busy
\n
"
,
HD_DATA
);
goto
out7
;
}
if
(
!
request_region
(
HD_CMD
,
1
,
"hd(cmd)"
))
{
printk
(
KERN_WARNING
"hd: port 0x%x busy
\n
"
,
HD_CMD
);
goto
out8
;
}
if
(
!
request_region
(
HD_CMD
+
2
,
1
,
"hd(cmd)"
))
{
printk
(
KERN_WARNING
"hd: port 0x%x busy
\n
"
,
HD_CMD
);
goto
out9
;
}
for
(
drive
=
0
;
drive
<
NR_HD
;
drive
++
)
add_disk
(
hd_gendisk
[
drive
]);
return
0
;
out9:
release_region
(
HD_CMD
,
1
);
out8:
release_region
(
HD_DATA
+
12
,
1
);
out7:
release_region
(
HD_DATA
+
10
,
1
);
out6:
release_region
(
HD_DATA
+
8
,
1
);
out5:
release_region
(
HD_DATA
+
6
,
1
);
out4:
release_region
(
HD_DATA
+
4
,
1
);
out3:
release_region
(
HD_DATA
+
2
,
1
);
out2:
release_region
(
HD_DATA
,
2
);
free_irq
(
HD_IRQ
,
NULL
);
out1:
for
(
drive
=
0
;
drive
<
NR_HD
;
drive
++
)
put_disk
(
hd_gendisk
[
drive
]);
NR_HD
=
0
;
out:
del_timer
(
&
device_timer
);
unregister_blkdev
(
HD_MAJOR
,
"hd"
);
blk_cleanup_queue
(
hd_queue
);
return
-
1
;
Enomem:
while
(
drive
--
)
put_disk
(
hd_gendisk
[
drive
]);
goto
out
;
}
static
int
parse_hd_setup
(
char
*
line
)
{
int
ints
[
6
];
(
void
)
get_options
(
line
,
ARRAY_SIZE
(
ints
),
ints
);
hd_setup
(
NULL
,
ints
);
return
1
;
}
__setup
(
"hd="
,
parse_hd_setup
);
module_init
(
hd_init
);
drivers/ide/legacy/pc9800.c
deleted
100644 → 0
View file @
bffc8f71
/*
* ide_pc9800.c
*
* Copyright (C) 1997-2000 Linux/98 project,
* Kyoto University Microcomputer Club.
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/ioport.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <asm/io.h>
#include <asm/pc9800.h>
#define PC9800_IDE_BANKSELECT 0x432
#undef PC9800_IDE_DEBUG
static
void
pc9800_select
(
ide_drive_t
*
drive
)
{
#ifdef PC9800_IDE_DEBUG
byte
old
;
/* Too noisy: */
/* printk(KERN_DEBUG "pc9800_select(%s)\n", drive->name); */
outb
(
0x80
,
PC9800_IDE_BANKSELECT
);
old
=
inb
(
PC9800_IDE_BANKSELECT
);
if
(
old
!=
HWIF
(
drive
)
->
index
)
printk
(
KERN_DEBUG
"ide-pc9800: switching bank #%d -> #%d
\n
"
,
old
,
HWIF
(
drive
)
->
index
);
#endif
outb
(
HWIF
(
drive
)
->
index
,
PC9800_IDE_BANKSELECT
);
}
void
__init
ide_probe_for_pc9800
(
void
)
{
u8
saved_bank
;
if
(
!
PC9800_9821_P
()
/* || !PC9821_IDEIF_DOUBLE_P() */
)
return
;
if
(
!
request_region
(
PC9800_IDE_BANKSELECT
,
1
,
"ide0/1 bank"
))
{
printk
(
KERN_ERR
"ide: bank select port (%#x) is already occupied!
\n
"
,
PC9800_IDE_BANKSELECT
);
return
;
}
/* Do actual probing. */
if
((
saved_bank
=
inb
(
PC9800_IDE_BANKSELECT
))
==
(
u8
)
~
0
||
(
outb
(
saved_bank
^
1
,
PC9800_IDE_BANKSELECT
),
/* Next outb is dummy for reading status. */
outb
(
0x80
,
PC9800_IDE_BANKSELECT
),
inb
(
PC9800_IDE_BANKSELECT
)
!=
(
saved_bank
^
1
)))
{
printk
(
KERN_INFO
"ide: pc9800 type bank selecting port not found
\n
"
);
release_region
(
PC9800_IDE_BANKSELECT
,
1
);
return
;
}
/* Restore original value, just in case. */
outb
(
saved_bank
,
PC9800_IDE_BANKSELECT
);
/* These ports are reseved by IDE I/F. */
if
(
!
request_region
(
0x430
,
1
,
"ide"
)
||
!
request_region
(
0x435
,
1
,
"ide"
))
{
printk
(
KERN_WARNING
"ide: IO port 0x430 and 0x435 are reserved for IDE"
" the card using these ports may not work
\n
"
);
}
if
(
ide_hwifs
[
0
].
io_ports
[
IDE_DATA_OFFSET
]
==
HD_DATA
&&
ide_hwifs
[
1
].
io_ports
[
IDE_DATA_OFFSET
]
==
HD_DATA
)
{
ide_hwifs
[
0
].
chipset
=
ide_pc9800
;
ide_hwifs
[
0
].
mate
=
&
ide_hwifs
[
1
];
ide_hwifs
[
0
].
selectproc
=
pc9800_select
;
ide_hwifs
[
1
].
chipset
=
ide_pc9800
;
ide_hwifs
[
1
].
mate
=
&
ide_hwifs
[
0
];
ide_hwifs
[
1
].
selectproc
=
pc9800_select
;
}
}
drivers/input/keyboard/98kbd.c
deleted
100644 → 0
View file @
bffc8f71
/*
* drivers/input/keyboard/98kbd.c
*
* PC-9801 keyboard driver for Linux
*
* Based on atkbd.c and xtkbd.c written by Vojtech Pavlik
*
* Copyright (c) 2002 Osamu Tomita
* Copyright (c) 1999-2001 Vojtech Pavlik
*/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/input.h>
#include <linux/init.h>
#include <linux/serio.h>
#include <asm/io.h>
#include <asm/pc9800.h>
MODULE_AUTHOR
(
"Osamu Tomita <tomita@cinet.co.jp>"
);
MODULE_DESCRIPTION
(
"PC-9801 keyboard driver"
);
MODULE_LICENSE
(
"GPL"
);
#define KBD98_KEY 0x7f
#define KBD98_RELEASE 0x80
static
unsigned
char
kbd98_keycode
[
256
]
=
{
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
,
9
,
10
,
11
,
12
,
13
,
43
,
14
,
15
,
16
,
17
,
18
,
19
,
20
,
21
,
22
,
23
,
24
,
25
,
41
,
26
,
28
,
30
,
31
,
32
,
33
,
34
,
35
,
36
,
37
,
38
,
39
,
40
,
27
,
44
,
45
,
46
,
47
,
48
,
49
,
50
,
51
,
52
,
53
,
12
,
57
,
92
,
109
,
104
,
110
,
111
,
103
,
105
,
106
,
108
,
102
,
107
,
74
,
98
,
71
,
72
,
73
,
55
,
75
,
76
,
77
,
78
,
79
,
80
,
81
,
117
,
82
,
121
,
83
,
94
,
87
,
88
,
183
,
184
,
185
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
102
,
0
,
99
,
133
,
59
,
60
,
61
,
62
,
63
,
64
,
65
,
66
,
67
,
68
,
0
,
0
,
0
,
0
,
54
,
58
,
42
,
56
,
29
};
struct
jis_kbd_conv
{
unsigned
char
scancode
;
struct
{
unsigned
char
shift
;
unsigned
char
keycode
;
}
emul
[
2
];
};
static
struct
jis_kbd_conv
kbd98_jis
[]
=
{
{
0x02
,
{{
0
,
3
},
{
1
,
40
}}},
{
0x06
,
{{
0
,
7
},
{
1
,
8
}}},
{
0x07
,
{{
0
,
8
},
{
0
,
40
}}},
{
0x08
,
{{
0
,
9
},
{
1
,
10
}}},
{
0x09
,
{{
0
,
10
},
{
1
,
11
}}},
{
0x0a
,
{{
0
,
11
},
{
1
,
255
}}},
{
0x0b
,
{{
0
,
12
},
{
0
,
13
}}},
{
0x0c
,
{{
1
,
7
},
{
0
,
41
}}},
{
0x1a
,
{{
1
,
3
},
{
1
,
41
}}},
{
0x26
,
{{
0
,
39
},
{
1
,
13
}}},
{
0x27
,
{{
1
,
39
},
{
1
,
9
}}},
{
0x33
,
{{
0
,
255
},
{
1
,
12
}}},
{
0xff
,
{{
0
,
255
},
{
1
,
255
}}}
/* terminater */
};
#define KBD98_CMD_SETEXKEY 0x1095
/* Enable/Disable Windows, Appli key */
#define KBD98_CMD_SETRATE 0x109c
/* Set typematic rate */
#define KBD98_CMD_SETLEDS 0x109d
/* Set keyboard leds */
#define KBD98_CMD_GETLEDS 0x119d
/* Get keyboard leds */
#define KBD98_CMD_GETID 0x019f
#define KBD98_RET_ACK 0xfa
#define KBD98_RET_NAK 0xfc
/* Command NACK, send the cmd again */
#define KBD98_KEY_JIS_EMUL 253
#define KBD98_KEY_UNKNOWN 254
#define KBD98_KEY_NULL 255
static
char
*
kbd98_name
=
"PC-9801 Keyboard"
;
struct
kbd98
{
unsigned
char
keycode
[
256
];
struct
input_dev
dev
;
struct
serio
*
serio
;
char
phys
[
32
];
unsigned
char
cmdbuf
[
4
];
unsigned
char
cmdcnt
;
signed
char
ack
;
unsigned
char
shift
;
struct
{
unsigned
char
scancode
;
unsigned
char
keycode
;
}
emul
;
struct
jis_kbd_conv
jis
[
16
];
};
irqreturn_t
kbd98_interrupt
(
struct
serio
*
serio
,
unsigned
char
data
,
unsigned
int
flags
,
struct
pt_regs
*
regs
)
{
struct
kbd98
*
kbd98
=
serio
->
private
;
unsigned
char
scancode
,
keycode
;
int
press
,
i
;
switch
(
data
)
{
case
KBD98_RET_ACK
:
kbd98
->
ack
=
1
;
goto
out
;
case
KBD98_RET_NAK
:
kbd98
->
ack
=
-
1
;
goto
out
;
}
if
(
kbd98
->
cmdcnt
)
{
kbd98
->
cmdbuf
[
--
kbd98
->
cmdcnt
]
=
data
;
goto
out
;
}
scancode
=
data
&
KBD98_KEY
;
keycode
=
kbd98
->
keycode
[
scancode
];
press
=
!
(
data
&
KBD98_RELEASE
);
if
(
kbd98
->
emul
.
scancode
!=
KBD98_KEY_UNKNOWN
&&
scancode
!=
kbd98
->
emul
.
scancode
)
{
input_report_key
(
&
kbd98
->
dev
,
kbd98
->
emul
.
keycode
,
0
);
kbd98
->
emul
.
scancode
=
KBD98_KEY_UNKNOWN
;
}
if
(
keycode
==
KEY_RIGHTSHIFT
)
kbd98
->
shift
=
press
;
switch
(
keycode
)
{
case
KEY_2
:
case
KEY_6
:
case
KEY_7
:
case
KEY_8
:
case
KEY_9
:
case
KEY_0
:
case
KEY_MINUS
:
case
KEY_EQUAL
:
case
KEY_GRAVE
:
case
KEY_SEMICOLON
:
case
KEY_APOSTROPHE
:
/* emulation: JIS keyboard to US101 keyboard */
i
=
0
;
while
(
kbd98
->
jis
[
i
].
scancode
!=
0xff
)
{
if
(
scancode
==
kbd98
->
jis
[
i
].
scancode
)
break
;
i
++
;
}
keycode
=
kbd98
->
jis
[
i
].
emul
[
kbd98
->
shift
].
keycode
;
if
(
keycode
==
KBD98_KEY_NULL
)
break
;
if
(
press
)
{
kbd98
->
emul
.
scancode
=
scancode
;
kbd98
->
emul
.
keycode
=
keycode
;
if
(
kbd98
->
jis
[
i
].
emul
[
kbd98
->
shift
].
shift
!=
kbd98
->
shift
)
input_report_key
(
&
kbd98
->
dev
,
KEY_RIGHTSHIFT
,
!
(
kbd98
->
shift
));
}
input_report_key
(
&
kbd98
->
dev
,
keycode
,
press
);
if
(
!
press
)
{
if
(
kbd98
->
jis
[
i
].
emul
[
kbd98
->
shift
].
shift
!=
kbd98
->
shift
)
input_report_key
(
&
kbd98
->
dev
,
KEY_RIGHTSHIFT
,
kbd98
->
shift
);
kbd98
->
emul
.
scancode
=
KBD98_KEY_UNKNOWN
;
}
input_sync
(
&
kbd98
->
dev
);
break
;
case
KEY_CAPSLOCK
:
input_report_key
(
&
kbd98
->
dev
,
keycode
,
1
);
input_sync
(
&
kbd98
->
dev
);
input_report_key
(
&
kbd98
->
dev
,
keycode
,
0
);
input_sync
(
&
kbd98
->
dev
);
break
;
case
KBD98_KEY_NULL
:
break
;
case
0
:
printk
(
KERN_WARNING
"kbd98.c: Unknown key (scancode %#x) %s.
\n
"
,
data
&
KBD98_KEY
,
data
&
KBD98_RELEASE
?
"released"
:
"pressed"
);
break
;
default:
input_report_key
(
&
kbd98
->
dev
,
keycode
,
press
);
input_sync
(
&
kbd98
->
dev
);
break
;
}
out:
return
IRQ_HANDLED
;
}
/*
* kbd98_sendbyte() sends a byte to the keyboard, and waits for
* acknowledge. It doesn't handle resends according to the keyboard
* protocol specs, because if these are needed, the keyboard needs
* replacement anyway, and they only make a mess in the protocol.
*/
static
int
kbd98_sendbyte
(
struct
kbd98
*
kbd98
,
unsigned
char
byte
)
{
int
timeout
=
10000
;
/* 100 msec */
kbd98
->
ack
=
0
;
if
(
serio_write
(
kbd98
->
serio
,
byte
))
return
-
1
;
while
(
!
kbd98
->
ack
&&
timeout
--
)
udelay
(
10
);
return
-
(
kbd98
->
ack
<=
0
);
}
/*
* kbd98_command() sends a command, and its parameters to the keyboard,
* then waits for the response and puts it in the param array.
*/
static
int
kbd98_command
(
struct
kbd98
*
kbd98
,
unsigned
char
*
param
,
int
command
)
{
int
timeout
=
50000
;
/* 500 msec */
int
send
=
(
command
>>
12
)
&
0xf
;
int
receive
=
(
command
>>
8
)
&
0xf
;
int
i
;
kbd98
->
cmdcnt
=
receive
;
if
(
command
&
0xff
)
if
(
kbd98_sendbyte
(
kbd98
,
command
&
0xff
))
return
(
kbd98
->
cmdcnt
=
0
)
-
1
;
for
(
i
=
0
;
i
<
send
;
i
++
)
if
(
kbd98_sendbyte
(
kbd98
,
param
[
i
]))
return
(
kbd98
->
cmdcnt
=
0
)
-
1
;
while
(
kbd98
->
cmdcnt
&&
timeout
--
)
udelay
(
10
);
if
(
param
)
for
(
i
=
0
;
i
<
receive
;
i
++
)
param
[
i
]
=
kbd98
->
cmdbuf
[(
receive
-
1
)
-
i
];
if
(
kbd98
->
cmdcnt
)
return
(
kbd98
->
cmdcnt
=
0
)
-
1
;
return
0
;
}
/*
* Event callback from the input module. Events that change the state of
* the hardware are processed here.
*/
static
int
kbd98_event
(
struct
input_dev
*
dev
,
unsigned
int
type
,
unsigned
int
code
,
int
value
)
{
struct
kbd98
*
kbd98
=
dev
->
private
;
char
param
[
2
];
switch
(
type
)
{
case
EV_LED
:
if
(
__PC9800SCA_TEST_BIT
(
0x481
,
3
))
{
/* 98note with Num Lock key */
/* keep Num Lock status */
*
param
=
0x60
;
if
(
kbd98_command
(
kbd98
,
param
,
KBD98_CMD_GETLEDS
))
printk
(
KERN_DEBUG
"kbd98: Get keyboard LED"
" status Error
\n
"
);
*
param
&=
1
;
}
else
{
/* desktop PC-9801 */
*
param
=
1
;
/* Always set Num Lock */
}
*
param
|=
0x70
|
(
test_bit
(
LED_CAPSL
,
dev
->
led
)
?
4
:
0
)
|
(
test_bit
(
LED_KANA
,
dev
->
led
)
?
8
:
0
);
kbd98_command
(
kbd98
,
param
,
KBD98_CMD_SETLEDS
);
return
0
;
}
return
-
1
;
}
void
kbd98_connect
(
struct
serio
*
serio
,
struct
serio_dev
*
dev
)
{
struct
kbd98
*
kbd98
;
int
i
;
if
((
serio
->
type
&
SERIO_TYPE
)
!=
SERIO_PC9800
)
return
;
if
(
!
(
kbd98
=
kmalloc
(
sizeof
(
struct
kbd98
),
GFP_KERNEL
)))
return
;
memset
(
kbd98
,
0
,
sizeof
(
struct
kbd98
));
kbd98
->
emul
.
scancode
=
KBD98_KEY_UNKNOWN
;
kbd98
->
dev
.
evbit
[
0
]
=
BIT
(
EV_KEY
)
|
BIT
(
EV_LED
)
|
BIT
(
EV_REP
);
kbd98
->
dev
.
ledbit
[
0
]
=
BIT
(
LED_NUML
)
|
BIT
(
LED_CAPSL
)
|
BIT
(
LED_KANA
);
kbd98
->
serio
=
serio
;
init_input_dev
(
&
kbd98
->
dev
);
kbd98
->
dev
.
keycode
=
kbd98
->
keycode
;
kbd98
->
dev
.
keycodesize
=
sizeof
(
unsigned
char
);
kbd98
->
dev
.
keycodemax
=
ARRAY_SIZE
(
kbd98_keycode
);
kbd98
->
dev
.
event
=
kbd98_event
;
kbd98
->
dev
.
private
=
kbd98
;
serio
->
private
=
kbd98
;
if
(
serio_open
(
serio
,
dev
))
{
kfree
(
kbd98
);
return
;
}
memcpy
(
kbd98
->
jis
,
kbd98_jis
,
sizeof
(
kbd98_jis
));
memcpy
(
kbd98
->
keycode
,
kbd98_keycode
,
sizeof
(
kbd98
->
keycode
));
for
(
i
=
0
;
i
<
255
;
i
++
)
set_bit
(
kbd98
->
keycode
[
i
],
kbd98
->
dev
.
keybit
);
clear_bit
(
0
,
kbd98
->
dev
.
keybit
);
sprintf
(
kbd98
->
phys
,
"%s/input0"
,
serio
->
phys
);
kbd98
->
dev
.
name
=
kbd98_name
;
kbd98
->
dev
.
phys
=
kbd98
->
phys
;
kbd98
->
dev
.
id
.
bustype
=
BUS_XTKBD
;
kbd98
->
dev
.
id
.
vendor
=
0x0002
;
kbd98
->
dev
.
id
.
product
=
0x0001
;
kbd98
->
dev
.
id
.
version
=
0x0100
;
input_register_device
(
&
kbd98
->
dev
);
printk
(
KERN_INFO
"input: %s on %s
\n
"
,
kbd98_name
,
serio
->
phys
);
}
void
kbd98_disconnect
(
struct
serio
*
serio
)
{
struct
kbd98
*
kbd98
=
serio
->
private
;
input_unregister_device
(
&
kbd98
->
dev
);
serio_close
(
serio
);
kfree
(
kbd98
);
}
struct
serio_dev
kbd98_dev
=
{
.
interrupt
=
kbd98_interrupt
,
.
connect
=
kbd98_connect
,
.
disconnect
=
kbd98_disconnect
};
int
__init
kbd98_init
(
void
)
{
serio_register_device
(
&
kbd98_dev
);
return
0
;
}
void
__exit
kbd98_exit
(
void
)
{
serio_unregister_device
(
&
kbd98_dev
);
}
module_init
(
kbd98_init
);
module_exit
(
kbd98_exit
);
drivers/input/misc/98spkr.c
deleted
100644 → 0
View file @
bffc8f71
/*
* PC-9800 Speaker beeper driver for Linux
*
* Copyright (c) 2002 Osamu Tomita
* Copyright (c) 2002 Vojtech Pavlik
* Copyright (c) 1992 Orest Zborowski
*
*/
/*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/input.h>
#include <asm/8253pit.h>
#include <asm/io.h>
MODULE_AUTHOR
(
"Osamu Tomita <tomita@cinet.co.jp>"
);
MODULE_DESCRIPTION
(
"PC-9800 Speaker beeper driver"
);
MODULE_LICENSE
(
"GPL"
);
static
char
spkr98_name
[]
=
"PC-9801 Speaker"
;
static
char
spkr98_phys
[]
=
"isa3fdb/input0"
;
static
struct
input_dev
spkr98_dev
;
spinlock_t
i8253_beep_lock
=
SPIN_LOCK_UNLOCKED
;
static
int
spkr98_event
(
struct
input_dev
*
dev
,
unsigned
int
type
,
unsigned
int
code
,
int
value
)
{
unsigned
int
count
=
0
;
unsigned
long
flags
;
if
(
type
!=
EV_SND
)
return
-
1
;
switch
(
code
)
{
case
SND_BELL
:
if
(
value
)
value
=
1000
;
case
SND_TONE
:
break
;
default:
return
-
1
;
}
if
(
value
>
20
&&
value
<
32767
)
count
=
PIT_TICK_RATE
/
value
;
spin_lock_irqsave
(
&
i8253_beep_lock
,
flags
);
if
(
count
)
{
outb
(
0x76
,
0x3fdf
);
outb
(
0
,
0x5f
);
outb
(
count
&
0xff
,
0x3fdb
);
outb
(
0
,
0x5f
);
outb
((
count
>>
8
)
&
0xff
,
0x3fdb
);
/* beep on */
outb
(
6
,
0x37
);
}
else
{
/* beep off */
outb
(
7
,
0x37
);
}
spin_unlock_irqrestore
(
&
i8253_beep_lock
,
flags
);
return
0
;
}
static
int
__init
spkr98_init
(
void
)
{
spkr98_dev
.
evbit
[
0
]
=
BIT
(
EV_SND
);
spkr98_dev
.
sndbit
[
0
]
=
BIT
(
SND_BELL
)
|
BIT
(
SND_TONE
);
spkr98_dev
.
event
=
spkr98_event
;
spkr98_dev
.
name
=
spkr98_name
;
spkr98_dev
.
phys
=
spkr98_phys
;
spkr98_dev
.
id
.
bustype
=
BUS_ISA
;
spkr98_dev
.
id
.
vendor
=
0x001f
;
spkr98_dev
.
id
.
product
=
0x0001
;
spkr98_dev
.
id
.
version
=
0x0100
;
input_register_device
(
&
spkr98_dev
);
printk
(
KERN_INFO
"input: %s
\n
"
,
spkr98_name
);
return
0
;
}
static
void
__exit
spkr98_exit
(
void
)
{
input_unregister_device
(
&
spkr98_dev
);
}
module_init
(
spkr98_init
);
module_exit
(
spkr98_exit
);
drivers/input/mouse/98busmouse.c
deleted
100644 → 0
View file @
bffc8f71
/*
*
* Copyright (c) 2002 Osamu Tomita
*
* Based on the work of:
* James Banks Matthew Dillon
* David Giller Nathan Laredo
* Linus Torvalds Johan Myreen
* Cliff Matthews Philip Blundell
* Russell King Vojtech Pavlik
*/
/*
* NEC PC-9801 Bus Mouse Driver for Linux
*/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/delay.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/input.h>
#include <linux/interrupt.h>
#include <asm/io.h>
#include <asm/irq.h>
MODULE_AUTHOR
(
"Osamu Tomita <tomita@cinet.co.jp>"
);
MODULE_DESCRIPTION
(
"PC-9801 busmouse driver"
);
MODULE_LICENSE
(
"GPL"
);
#define PC98BM_BASE 0x7fd9
#define PC98BM_DATA_PORT PC98BM_BASE + 0
/* PC98BM_SIGNATURE_PORT does not exist */
#define PC98BM_CONTROL_PORT PC98BM_BASE + 4
/* PC98BM_INTERRUPT_PORT does not exist */
#define PC98BM_CONFIG_PORT PC98BM_BASE + 6
#define PC98BM_ENABLE_IRQ 0x00
#define PC98BM_DISABLE_IRQ 0x10
#define PC98BM_READ_X_LOW 0x80
#define PC98BM_READ_X_HIGH 0xa0
#define PC98BM_READ_Y_LOW 0xc0
#define PC98BM_READ_Y_HIGH 0xe0
#define PC98BM_DEFAULT_MODE 0x93
/* PC98BM_CONFIG_BYTE is not used */
/* PC98BM_SIGNATURE_BYTE is not used */
#define PC98BM_TIMER_PORT 0xbfdb
#define PC98BM_DEFAULT_TIMER_VAL 0x00
#define PC98BM_IRQ 13
static
int
pc98bm_irq
=
PC98BM_IRQ
;
module_param_named
(
irq
,
pc98bm_irq
,
uint
,
0
);
MODULE_PARM_DESC
(
irq
,
"IRQ number (13=default)"
);
__obsolete_setup
(
"pc98bm_irq="
);
static
int
pc98bm_used
=
0
;
static
irqreturn_t
pc98bm_interrupt
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
);
static
int
pc98bm_open
(
struct
input_dev
*
dev
)
{
if
(
pc98bm_used
++
)
return
0
;
if
(
request_irq
(
pc98bm_irq
,
pc98bm_interrupt
,
0
,
"98busmouse"
,
NULL
))
{
pc98bm_used
--
;
printk
(
KERN_ERR
"98busmouse.c: Can't allocate irq %d
\n
"
,
pc98bm_irq
);
return
-
EBUSY
;
}
outb
(
PC98BM_ENABLE_IRQ
,
PC98BM_CONTROL_PORT
);
return
0
;
}
static
void
pc98bm_close
(
struct
input_dev
*
dev
)
{
if
(
--
pc98bm_used
)
return
;
outb
(
PC98BM_DISABLE_IRQ
,
PC98BM_CONTROL_PORT
);
free_irq
(
pc98bm_irq
,
NULL
);
}
static
struct
input_dev
pc98bm_dev
=
{
.
evbit
=
{
BIT
(
EV_KEY
)
|
BIT
(
EV_REL
)
},
.
keybit
=
{
[
LONG
(
BTN_LEFT
)]
=
BIT
(
BTN_LEFT
)
|
BIT
(
BTN_MIDDLE
)
|
BIT
(
BTN_RIGHT
)
},
.
relbit
=
{
BIT
(
REL_X
)
|
BIT
(
REL_Y
)
},
.
open
=
pc98bm_open
,
.
close
=
pc98bm_close
,
.
name
=
"PC-9801 bus mouse"
,
.
phys
=
"isa7fd9/input0"
,
.
id
=
{
.
bustype
=
BUS_ISA
,
.
vendor
=
0x0004
,
.
product
=
0x0001
,
.
version
=
0x0100
,
},
};
static
irqreturn_t
pc98bm_interrupt
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
)
{
char
dx
,
dy
;
unsigned
char
buttons
;
outb
(
PC98BM_READ_X_LOW
,
PC98BM_CONTROL_PORT
);
dx
=
(
inb
(
PC98BM_DATA_PORT
)
&
0xf
);
outb
(
PC98BM_READ_X_HIGH
,
PC98BM_CONTROL_PORT
);
dx
|=
(
inb
(
PC98BM_DATA_PORT
)
&
0xf
)
<<
4
;
outb
(
PC98BM_READ_Y_LOW
,
PC98BM_CONTROL_PORT
);
dy
=
(
inb
(
PC98BM_DATA_PORT
)
&
0xf
);
outb
(
PC98BM_READ_Y_HIGH
,
PC98BM_CONTROL_PORT
);
buttons
=
inb
(
PC98BM_DATA_PORT
);
dy
|=
(
buttons
&
0xf
)
<<
4
;
buttons
=
~
buttons
>>
5
;
input_report_rel
(
&
pc98bm_dev
,
REL_X
,
dx
);
input_report_rel
(
&
pc98bm_dev
,
REL_Y
,
dy
);
input_report_key
(
&
pc98bm_dev
,
BTN_RIGHT
,
buttons
&
1
);
input_report_key
(
&
pc98bm_dev
,
BTN_MIDDLE
,
buttons
&
2
);
input_report_key
(
&
pc98bm_dev
,
BTN_LEFT
,
buttons
&
4
);
input_sync
(
&
pc98bm_dev
);
outb
(
PC98BM_ENABLE_IRQ
,
PC98BM_CONTROL_PORT
);
return
IRQ_HANDLED
;
}
static
int
__init
pc98bm_init
(
void
)
{
int
i
;
for
(
i
=
0
;
i
<=
6
;
i
+=
2
)
{
if
(
!
request_region
(
PC98BM_BASE
+
i
,
1
,
"98busmouse"
))
{
printk
(
KERN_ERR
"98busmouse.c: Can't allocate ports at %#x
\n
"
,
PC98BM_BASE
+
i
);
while
(
i
>
0
)
{
i
-=
2
;
release_region
(
PC98BM_BASE
+
i
,
1
);
}
return
-
EBUSY
;
}
}
if
(
!
request_region
(
PC98BM_TIMER_PORT
,
1
,
"98busmouse"
))
{
printk
(
KERN_ERR
"98busmouse.c: Can't allocate ports at %#x
\n
"
,
PC98BM_TIMER_PORT
);
for
(
i
=
0
;
i
<=
6
;
i
+=
2
)
release_region
(
PC98BM_BASE
+
i
,
1
);
return
-
EBUSY
;
}
outb
(
PC98BM_DEFAULT_MODE
,
PC98BM_CONFIG_PORT
);
outb
(
PC98BM_DISABLE_IRQ
,
PC98BM_CONTROL_PORT
);
outb
(
PC98BM_DEFAULT_TIMER_VAL
,
PC98BM_TIMER_PORT
);
input_register_device
(
&
pc98bm_dev
);
printk
(
KERN_INFO
"input: PC-9801 bus mouse at %#x irq %d
\n
"
,
PC98BM_BASE
,
pc98bm_irq
);
return
0
;
}
static
void
__exit
pc98bm_exit
(
void
)
{
int
i
;
input_unregister_device
(
&
pc98bm_dev
);
for
(
i
=
0
;
i
<=
6
;
i
+=
2
)
release_region
(
PC98BM_BASE
+
i
,
1
);
release_region
(
PC98BM_TIMER_PORT
,
1
);
}
module_init
(
pc98bm_init
);
module_exit
(
pc98bm_exit
);
drivers/input/serio/98kbd-io.c
deleted
100644 → 0
View file @
bffc8f71
/*
* NEC PC-9801 keyboard controller driver for Linux
*
* Copyright (c) 1999-2002 Osamu Tomita <tomita@cinet.co.jp>
* Based on i8042.c written by Vojtech Pavlik
*/
/*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*/
#include <linux/config.h>
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/serio.h>
#include <linux/sched.h>
#include <asm/io.h>
MODULE_AUTHOR
(
"Osamu Tomita <tomita@cinet.co.jp>"
);
MODULE_DESCRIPTION
(
"NEC PC-9801 keyboard controller driver"
);
MODULE_LICENSE
(
"GPL"
);
/*
* Names.
*/
#define KBD98_PHYS_DESC "isa0041/serio0"
/*
* IRQs.
*/
#define KBD98_IRQ 1
/*
* Register numbers.
*/
#define KBD98_COMMAND_REG 0x43
#define KBD98_STATUS_REG 0x43
#define KBD98_DATA_REG 0x41
spinlock_t
kbd98io_lock
=
SPIN_LOCK_UNLOCKED
;
static
struct
serio
kbd98_port
;
extern
struct
pt_regs
*
kbd_pt_regs
;
static
irqreturn_t
kbd98io_interrupt
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
);
/*
* kbd98_flush() flushes all data that may be in the keyboard buffers
*/
static
int
kbd98_flush
(
void
)
{
unsigned
long
flags
;
spin_lock_irqsave
(
&
kbd98io_lock
,
flags
);
while
(
inb
(
KBD98_STATUS_REG
)
&
0x02
)
/* RxRDY */
inb
(
KBD98_DATA_REG
);
if
(
inb
(
KBD98_STATUS_REG
)
&
0x38
)
printk
(
"98kbd-io: Keyboard error!
\n
"
);
spin_unlock_irqrestore
(
&
kbd98io_lock
,
flags
);
return
0
;
}
/*
* kbd98_write() sends a byte out through the keyboard interface.
*/
static
int
kbd98_write
(
struct
serio
*
port
,
unsigned
char
c
)
{
unsigned
long
flags
;
spin_lock_irqsave
(
&
kbd98io_lock
,
flags
);
outb
(
0
,
0x5f
);
/* wait */
outb
(
0x17
,
KBD98_COMMAND_REG
);
/* enable send command */
outb
(
0
,
0x5f
);
/* wait */
outb
(
c
,
KBD98_DATA_REG
);
outb
(
0
,
0x5f
);
/* wait */
outb
(
0x16
,
KBD98_COMMAND_REG
);
/* disable send command */
outb
(
0
,
0x5f
);
/* wait */
spin_unlock_irqrestore
(
&
kbd98io_lock
,
flags
);
return
0
;
}
/*
* kbd98_open() is called when a port is open by the higher layer.
* It allocates the interrupt and enables in in the chip.
*/
static
int
kbd98_open
(
struct
serio
*
port
)
{
kbd98_flush
();
if
(
request_irq
(
KBD98_IRQ
,
kbd98io_interrupt
,
0
,
"kbd98"
,
NULL
))
{
printk
(
KERN_ERR
"98kbd-io.c: Can't get irq %d for %s, unregistering the port.
\n
"
,
KBD98_IRQ
,
"KBD"
);
serio_unregister_port
(
port
);
return
-
1
;
}
return
0
;
}
static
void
kbd98_close
(
struct
serio
*
port
)
{
free_irq
(
KBD98_IRQ
,
NULL
);
kbd98_flush
();
}
/*
* Structures for registering the devices in the serio.c module.
*/
static
struct
serio
kbd98_port
=
{
.
type
=
SERIO_PC9800
,
.
write
=
kbd98_write
,
.
open
=
kbd98_open
,
.
close
=
kbd98_close
,
.
driver
=
NULL
,
.
name
=
"PC-9801 Kbd Port"
,
.
phys
=
KBD98_PHYS_DESC
,
};
/*
* kbd98io_interrupt() is the most important function in this driver -
* it handles the interrupts from keyboard, and sends incoming bytes
* to the upper layers.
*/
static
irqreturn_t
kbd98io_interrupt
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
)
{
unsigned
long
flags
;
unsigned
char
data
;
spin_lock_irqsave
(
&
kbd98io_lock
,
flags
);
data
=
inb
(
KBD98_DATA_REG
);
spin_unlock_irqrestore
(
&
kbd98io_lock
,
flags
);
serio_interrupt
(
&
kbd98_port
,
data
,
0
,
regs
);
return
IRQ_HANDLED
;
}
int
__init
kbd98io_init
(
void
)
{
serio_register_port
(
&
kbd98_port
);
printk
(
KERN_INFO
"serio: PC-9801 %s port at %#lx,%#lx irq %d
\n
"
,
"KBD"
,
(
unsigned
long
)
KBD98_DATA_REG
,
(
unsigned
long
)
KBD98_COMMAND_REG
,
KBD98_IRQ
);
return
0
;
}
void
__exit
kbd98io_exit
(
void
)
{
serio_unregister_port
(
&
kbd98_port
);
}
module_init
(
kbd98io_init
);
module_exit
(
kbd98io_exit
);
drivers/net/ne2k_cbus.c
deleted
100644 → 0
View file @
bffc8f71
/*
ne2k_cbus.c: A driver for the NE2000 like ethernet on NEC PC-9800.
This is a copy of the 2.5.66 Linux ISA NE2000 driver "ne.c"
(Donald Becker/Paul Gortmaker) with the NEC PC-9800 specific
changes added by Osamu Tomita.
From ne.c:
-----------
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.
-----------
*/
/* Routines for the NatSemi-based designs (NE[12]000). */
static
const
char
version
[]
=
"ne2k_cbus.c:v1.0 3/24/03 Osamu Tomita
\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"
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. */
static
int
__init
do_ne_probe
(
struct
net_device
*
dev
)
{
unsigned
int
base_addr
=
dev
->
base_addr
;
int
irq
=
dev
->
irq
;
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
,
irq
);
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
,
irq
)
==
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
,
irq
)
==
0
)
return
0
;
}
}
}
#endif
ne2k_cbus_destroy
(
dev
);
return
-
ENODEV
;
}
static
void
cleanup_card
(
struct
net_device
*
dev
)
{
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
);
}
ne2k_cbus_destroy
(
dev
);
}
struct
net_device
*
__init
ne_probe
(
int
unit
)
{
struct
net_device
*
dev
=
alloc_ei_netdev
();
int
err
;
if
(
!
dev
)
return
ERR_PTR
(
-
ENOMEM
);
sprintf
(
dev
->
name
,
"eth%d"
,
unit
);
netdev_boot_setup_check
(
dev
);
err
=
do_ne_probe
(
dev
);
if
(
err
)
goto
out
;
err
=
register_netdev
(
dev
);
if
(
err
)
goto
out1
;
return
dev
;
out1:
cleanup_card
(
dev
);
out:
free_netdev
(
dev
);
return
ERR_PTR
(
err
);
}
static
int
__init
ne_probe_cbus
(
struct
net_device
*
dev
,
const
struct
ne2k_cbus_hwinfo
*
hw
,
int
ioaddr
,
int
irq
)
{
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
);
dev
->
irq
=
irq
;
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
);
dev
->
irq
=
irq
;
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"
,
version
);
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 */
ret
=
-
ENODEV
;
i
=
inb
(
ioaddr
);
if
((
i
&
~
0x2
)
!=
(
0x20
|
0x01
))
goto
err_out
;
if
((
inb
(
ioaddr
+
0x7
)
&
0x80
)
!=
0x80
)
goto
err_out
;
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
);
goto
err_out
;
}
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
"
);
goto
err_out
;
}
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
;
}
/* 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
;
#ifdef CONFIG_NET_POLL_CONTROLLER
dev
->
poll_controller
=
ei_poll
;
#endif
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
=
alloc_ei_netdev
();
if
(
!
dev
)
break
;
dev
->
irq
=
irq
[
this_dev
];
dev
->
mem_end
=
bad
[
this_dev
];
dev
->
base_addr
=
io
[
this_dev
];
dev
->
mem_start
=
hwtype
[
this_dev
];
if
(
do_ne_probe
(
dev
)
==
0
)
{
if
(
register_netdev
(
dev
)
==
0
)
{
dev_ne
[
found
++
]
=
dev
;
continue
;
}
cleanup_card
(
dev
);
}
free_netdev
(
dev
);
if
(
found
)
break
;
if
(
io
[
this_dev
]
!=
0
)
printk
(
KERN_WARNING
"ne2k_cbus: 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 ISA cards.
\n
"
);
return
-
ENXIO
;
}
if
(
found
)
return
0
;
return
-
ENODEV
;
}
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
)
{
unregister_netdev
(
dev
);
cleanup_card
(
dev
);
free_netdev
(
dev
);
}
}
}
#endif
/* MODULE */
drivers/net/ne2k_cbus.h
deleted
100644 → 0
View file @
bffc8f71
/* 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
,
int
irq
);
/* End of ne2k_cbus.h */
drivers/scsi/pc980155.c
deleted
100644 → 0
View file @
bffc8f71
/*
*
* drivers/scsi/pc980155.c
*
* PC-9801-55 SCSI host adapter driver
*
* Copyright (C) 1997-2003 Kyoto University Microcomputer Club
* (Linux/98 project)
* Tomoharu Ugawa <ohirune@kmc.gr.jp>
*
*/
#include <linux/module.h>
#include <linux/blkdev.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 <ohirune@kmc.gr.jp>"
);
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"
drivers/scsi/pc980155.h
deleted
100644 → 0
View file @
bffc8f71
/*
*
* drivers/scsi/pc980155.h
*
* PC-9801-55 SCSI host adapter driver
*
* Copyright (C) 1997-2003 Kyoto University Microcomputer Club
* (Linux/98 project)
* Tomoharu Ugawa <ohirune@kmc.gr.jp>
*
*/
#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 */
drivers/scsi/scsi_pc98.c
deleted
100644 → 0
View file @
bffc8f71
/*
* Copyright (C) 2003 Osamu Tomita <tomita@cinet.co.jp>
*
* PC9801 BIOS geometry handling.
*/
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/genhd.h>
#include <linux/blkdev.h>
#include <asm/pc9800.h>
#include "scsi.h"
#include "hosts.h"
static
int
pc98_first_bios_param
(
struct
scsi_device
*
sdev
,
int
*
ip
)
{
const
u8
*
p
=
(
&
__PC9800SCA
(
u8
,
PC9800SCA_SCSI_PARAMS
)
+
sdev
->
id
*
4
);
ip
[
0
]
=
p
[
1
];
/* # of heads */
ip
[
1
]
=
p
[
0
];
/* # of sectors/track */
ip
[
2
]
=
*
(
u16
*
)
&
p
[
2
]
&
0x0fff
;
/* # of cylinders */
if
(
p
[
3
]
&
(
1
<<
6
))
{
/* #-of-cylinders is 16-bit */
ip
[
2
]
|=
(
ip
[
0
]
&
0xf0
)
<<
8
;
ip
[
0
]
&=
0x0f
;
}
return
0
;
}
int
pc98_bios_param
(
struct
scsi_device
*
sdev
,
struct
block_device
*
bdev
,
sector_t
capacity
,
int
*
ip
)
{
struct
Scsi_Host
*
first_real
=
first_real_host
();
/*
* XXX
* XXX This needs to become a sysfs attribute that's set
* XXX by code that knows which host is the first one.
* XXX
* XXX Currently we support only one host on with a
* XXX PC98ish HBA.
* XXX
*/
if
(
1
||
sdev
->
host
==
first_real
&&
sdev
->
id
<
7
&&
__PC9800SCA_TEST_BIT
(
PC9800SCA_DISK_EQUIPS
,
sdev
->
id
))
return
pc98_first_bios_param
(
sdev
,
ip
);
/* Assume PC-9801-92 compatible parameters for HAs without BIOS. */
ip
[
0
]
=
8
;
ip
[
1
]
=
32
;
ip
[
2
]
=
capacity
/
(
8
*
32
);
if
(
ip
[
2
]
>
65535
)
{
/* if capacity >= 8GB */
/* Recent on-board adapters seem to use this parameter. */
ip
[
1
]
=
128
;
ip
[
2
]
=
capacity
/
(
8
*
128
);
if
(
ip
[
2
]
>
65535
)
{
/* if capacity >= 32GB */
/* Clip the number of cylinders. Currently
this is the limit that we deal with. */
ip
[
2
]
=
65535
;
}
}
return
0
;
}
EXPORT_SYMBOL
(
pc98_bios_param
);
drivers/serial/serial98.c
deleted
100644 → 0
View file @
bffc8f71
/*
* linux/drivers/serial/serial98.c
*
* Driver for NEC PC-9801/PC-9821 standard serial ports
*
* Based on drivers/serial/8250.c, by Russell King.
* Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
*
* Copyright (C) 2002 Osamu Tomita <tomita@cinet.co.jp>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/tty.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/serial.h>
#include <linux/console.h>
#include <linux/sysrq.h>
#include <linux/serial_reg.h>
#include <linux/delay.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/pc9800.h>
#include <asm/pc9800_sca.h>
#if defined(CONFIG_SERIAL98_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
#define SUPPORT_SYSRQ
#endif
#include <linux/serial_core.h>
#define SERIAL98_NR 1
#define SERIAL98_ISR_PASS_LIMIT 256
#define SERIAL98_EXT 0x434
//#define RX_8251F 0x130 /* In: Receive buffer */
//#define TX_8251F 0x130 /* Out: Transmit buffer */
//#define LSR_8251F 0x132 /* In: Line Status Register */
//#define MSR_8251F 0x134 /* In: Modem Status Register */
#define IIR_8251F 0x136
/* In: Interrupt ID Register */
#define FCR_8251F 0x138
/* I/O: FIFO Control Register */
#define VFAST_8251F 0x13a
/* I/O: VFAST mode Register */
#define CMD_8251F 0x32
/* Out: 8251 Command Resister */
#define IER2_8251F 0x34
/* I/O: Interrupt Enable Register */
#define IER1_8251F 0x35
/* I/O: Interrupt Enable Register */
#define IER1_CTL 0x37
/* Out: Interrupt Enable Register */
#define DIS_RXR_INT 0x00
/* disable RxRDY Interrupt */
#define ENA_RXR_INT 0x01
/* enable RxRDY Interrupt */
#define DIS_TXE_INT 0x02
/* disable TxEMPTY Interrupt */
#define ENA_TXE_INT 0x03
/* enable TxEMPTY Interrupt */
#define DIS_TXR_INT 0x04
/* disable TxRDY Interrupt */
#define ENA_TXR_INT 0x05
/* enable TxRDY Interrupt */
#define CMD_RESET 0x40
/* Reset Command */
#define CMD_RTS 0x20
/* Set RTS line */
#define CMD_CLR_ERR 0x10
/* Clear error flag */
#define CMD_BREAK 0x08
/* Send Break */
#define CMD_RXE 0x04
/* Enable receive */
#define CMD_DTR 0x02
/* Set DTR line */
#define CMD_TXE 0x01
/* Enable send */
#define CMD_DUMMY 0x00
/* Dummy Command */
#define VFAST_ENABLE 0x80
/* V.Fast mode Enable */
/* Interrupt masks */
#define INTR_8251_TXRE 0x04
#define INTR_8251_TXEE 0x02
#define INTR_8251_RXRE 0x01
/* I/O Port */
//#define PORT_8251_DATA 0
//#define PORT_8251_CMD 2
//#define PORT_8251_MOD 2
//#define PORT_8251_STS 2
/* status read */
#define STAT_8251_TXRDY 0x01
#define STAT_8251_RXRDY 0x02
#define STAT_8251_TXEMP 0x04
#define STAT_8251_PER 0x08
#define STAT_8251_OER 0x10
#define STAT_8251_FER 0x20
#define STAT_8251_BRK 0x40
#define STAT_8251_DSR 0x80
#if 1
#define STAT_8251F_TXEMP 0x01
#define STAT_8251F_TXRDY 0x02
#define STAT_8251F_RXRDY 0x04
#define STAT_8251F_DSR 0x08
#define STAT_8251F_OER 0x10
#define STAT_8251F_PER 0x20
#define STAT_8251F_FER 0x40
#define STAT_8251F_BRK 0x80
#else
#define STAT_8251F_TXEMP 0x01
#define STAT_8251F_TEMT 0x01
#define STAT_8251F_TXRDY 0x02
#define STAT_8251F_THRE 0x02
#define STAT_8251F_RXRDY 0x04
#define STAT_8251F_DSR 0x04
#define STAT_8251F_PER 0x08
#define STAT_8251F_OER 0x10
#define STAT_8251F_FER 0x20
#define STAT_8251F_BRK 0x40
#endif
/*
* We wrap our port structure around the generic uart_port.
*/
struct
serial98_port
{
struct
uart_port
port
;
unsigned
int
type
;
unsigned
int
ext
;
unsigned
int
lsr_break_flag
;
unsigned
char
cmd
;
unsigned
char
mode
;
unsigned
char
msr
;
unsigned
char
ier
;
unsigned
char
rxchk
;
unsigned
char
txemp
;
unsigned
char
txrdy
;
unsigned
char
rxrdy
;
unsigned
char
brk
;
unsigned
char
fe
;
unsigned
char
oe
;
unsigned
char
pe
;
unsigned
char
dr
;
};
#ifdef CONFIG_SERIAL98_CONSOLE
static
void
serial98_console_write
(
struct
console
*
co
,
const
char
*
s
,
unsigned
int
count
);
static
int
__init
serial98_console_setup
(
struct
console
*
co
,
char
*
options
);
extern
struct
uart_driver
serial98_reg
;
static
struct
console
serial98_console
=
{
.
name
=
"ttyS"
,
.
write
=
serial98_console_write
,
.
device
=
uart_console_device
,
.
setup
=
serial98_console_setup
,
.
flags
=
CON_PRINTBUFFER
,
.
index
=
-
1
,
.
data
=
&
serial98_reg
,
};
#define SERIAL98_CONSOLE &serial98_console
#else
#define SERIAL98_CONSOLE NULL
#endif
static
struct
uart_driver
serial98_reg
=
{
.
owner
=
THIS_MODULE
,
.
driver_name
=
"serial98"
,
.
dev_name
=
"ttyS"
,
.
major
=
TTY_MAJOR
,
.
minor
=
64
,
.
nr
=
SERIAL98_NR
,
.
cons
=
SERIAL98_CONSOLE
,
};
static
int
serial98_clk
;
static
char
type_str
[
48
];
#define PORT98 ((struct serial98_port *)port)
#define PORT (PORT98->port)
static
void
serial98_fifo_enable
(
struct
uart_port
*
port
,
int
enable
)
{
unsigned
char
fcr
;
if
(
PORT
.
type
==
PORT_FIFO_PC98
||
PORT
.
type
==
PORT_VFAST_PC98
)
{
fcr
=
inb
(
FCR_8251F
);
if
(
enable
)
fcr
|=
UART_FCR_ENABLE_FIFO
;
else
fcr
&=
~
UART_FCR_ENABLE_FIFO
;
outb
(
fcr
,
FCR_8251F
);
}
if
(
!
enable
)
return
;
outb
(
0
,
0x5f
);
/* wait */
outb
(
0
,
0x5f
);
outb
(
0
,
0x5f
);
outb
(
0
,
0x5f
);
}
static
void
serial98_cmd_out
(
struct
uart_port
*
port
,
unsigned
char
cmd
)
{
serial98_fifo_enable
(
port
,
0
);
outb
(
cmd
,
CMD_8251F
);
serial98_fifo_enable
(
port
,
1
);
}
static
void
serial98_mode_set
(
struct
uart_port
*
port
)
{
serial98_cmd_out
(
port
,
CMD_DUMMY
);
serial98_cmd_out
(
port
,
CMD_DUMMY
);
serial98_cmd_out
(
port
,
CMD_DUMMY
);
serial98_cmd_out
(
port
,
CMD_RESET
);
serial98_cmd_out
(
port
,
PORT98
->
mode
);
}
static
unsigned
char
serial98_msr_in
(
struct
uart_port
*
port
)
{
unsigned
long
flags
;
unsigned
int
ms
,
st
;
unsigned
int
tmp
;
spin_lock_irqsave
(
&
PORT
.
lock
,
flags
);
if
(
PORT
.
type
==
PORT_FIFO_PC98
||
PORT
.
type
==
PORT_VFAST_PC98
)
{
PORT98
->
msr
=
inb
(
PORT
.
iobase
+
4
);
}
else
{
ms
=
inb
(
0x33
);
st
=
inb
(
0x32
);
tmp
=
0
;
if
(
!
(
ms
&
0x20
))
tmp
|=
UART_MSR_DCD
;
if
(
!
(
ms
&
0x80
))
{
tmp
|=
UART_MSR_RI
;
PORT98
->
msr
|=
UART_MSR_RI
;
}
if
(
!
(
ms
&
0x40
))
tmp
|=
UART_MSR_CTS
;
if
(
st
&
0x80
)
tmp
|=
UART_MSR_DSR
;
PORT98
->
msr
=
((
PORT98
->
msr
^
tmp
)
>>
4
)
|
tmp
;
}
spin_unlock_irqrestore
(
&
PORT
.
lock
,
flags
);
return
PORT98
->
msr
;
}
static
void
serial98_stop_tx
(
struct
uart_port
*
port
,
unsigned
int
tty_stop
)
{
unsigned
int
ier
=
inb
(
IER1_8251F
);
ier
&=
~
(
INTR_8251_TXRE
|
INTR_8251_TXEE
);
outb
(
ier
,
IER1_8251F
);
}
static
void
serial98_start_tx
(
struct
uart_port
*
port
,
unsigned
int
tty_start
)
{
unsigned
int
ier
=
inb
(
IER1_8251F
);
ier
|=
INTR_8251_TXRE
|
INTR_8251_TXEE
;
outb
(
ier
,
IER1_8251F
);
}
static
void
serial98_stop_rx
(
struct
uart_port
*
port
)
{
PORT
.
read_status_mask
&=
~
PORT98
->
dr
;
outb
(
DIS_RXR_INT
,
IER1_CTL
);
}
static
void
serial98_enable_ms
(
struct
uart_port
*
port
)
{
outb
(
PORT98
->
ier
|
0x80
,
IER2_8251F
);
}
static
void
serial98_rx_chars
(
struct
uart_port
*
port
,
int
*
status
,
struct
pt_regs
*
regs
)
{
struct
tty_struct
*
tty
=
PORT
.
info
->
tty
;
unsigned
char
ch
;
int
max_count
=
256
;
do
{
if
(
unlikely
(
tty
->
flip
.
count
>=
TTY_FLIPBUF_SIZE
))
{
tty
->
flip
.
work
.
func
((
void
*
)
tty
);
if
(
tty
->
flip
.
count
>=
TTY_FLIPBUF_SIZE
)
return
;
// if TTY_DONT_FLIP is set
}
ch
=
inb
(
PORT
.
iobase
);
*
tty
->
flip
.
char_buf_ptr
=
ch
;
*
tty
->
flip
.
flag_buf_ptr
=
TTY_NORMAL
;
PORT
.
icount
.
rx
++
;
if
(
unlikely
(
*
status
&
(
PORT98
->
brk
|
PORT98
->
pe
|
PORT98
->
fe
|
PORT98
->
oe
)))
{
/*
* For statistics only
*/
if
(
*
status
&
PORT98
->
brk
)
{
*
status
&=
~
(
PORT98
->
fe
|
PORT98
->
pe
);
PORT
.
icount
.
brk
++
;
/*
* We do the SysRQ and SAK checking
* here because otherwise the break
* may get masked by ignore_status_mask
* or read_status_mask.
*/
if
(
uart_handle_break
(
&
PORT
))
goto
ignore_char
;
}
else
if
(
*
status
&
PORT98
->
pe
)
PORT
.
icount
.
parity
++
;
else
if
(
*
status
&
PORT98
->
fe
)
PORT
.
icount
.
frame
++
;
if
(
*
status
&
PORT98
->
oe
)
PORT
.
icount
.
overrun
++
;
/*
* Mask off conditions which should be ingored.
*/
*
status
&=
PORT
.
read_status_mask
;
#ifdef CONFIG_SERIAL98_CONSOLE
if
(
PORT
.
line
==
PORT
.
cons
->
index
)
{
/* Recover the break flag from console xmit */
*
status
|=
PORT98
->
lsr_break_flag
;
PORT98
->
lsr_break_flag
=
0
;
}
#endif
if
(
*
status
&
PORT98
->
brk
)
{
*
tty
->
flip
.
flag_buf_ptr
=
TTY_BREAK
;
}
else
if
(
*
status
&
PORT98
->
pe
)
*
tty
->
flip
.
flag_buf_ptr
=
TTY_PARITY
;
else
if
(
*
status
&
PORT98
->
fe
)
*
tty
->
flip
.
flag_buf_ptr
=
TTY_FRAME
;
}
if
(
uart_handle_sysrq_char
(
&
PORT
,
ch
,
regs
))
goto
ignore_char
;
if
((
*
status
&
PORT
.
ignore_status_mask
)
==
0
)
{
tty
->
flip
.
flag_buf_ptr
++
;
tty
->
flip
.
char_buf_ptr
++
;
tty
->
flip
.
count
++
;
}
if
((
*
status
&
PORT98
->
oe
)
&&
tty
->
flip
.
count
<
TTY_FLIPBUF_SIZE
)
{
/*
* Overrun is special, since it's reported
* immediately, and doesn't affect the current
* character.
*/
*
tty
->
flip
.
flag_buf_ptr
=
TTY_OVERRUN
;
tty
->
flip
.
flag_buf_ptr
++
;
tty
->
flip
.
char_buf_ptr
++
;
tty
->
flip
.
count
++
;
}
ignore_char:
*
status
=
inb
(
PORT
.
iobase
+
2
);
}
while
((
*
status
&
PORT98
->
rxchk
)
&&
(
max_count
--
>
0
));
tty_flip_buffer_push
(
tty
);
}
static
void
serial98_tx_chars
(
struct
uart_port
*
port
)
{
struct
circ_buf
*
xmit
=
&
PORT
.
info
->
xmit
;
int
count
;
if
(
PORT
.
x_char
)
{
outb
(
PORT
.
x_char
,
PORT
.
iobase
);
PORT
.
icount
.
tx
++
;
PORT
.
x_char
=
0
;
return
;
}
if
(
uart_circ_empty
(
xmit
)
||
uart_tx_stopped
(
&
PORT
))
{
serial98_stop_tx
(
port
,
0
);
return
;
}
count
=
PORT
.
fifosize
;
do
{
outb
(
xmit
->
buf
[
xmit
->
tail
],
PORT
.
iobase
);
xmit
->
tail
=
(
xmit
->
tail
+
1
)
&
(
UART_XMIT_SIZE
-
1
);
PORT
.
icount
.
tx
++
;
if
(
uart_circ_empty
(
xmit
))
break
;
}
while
(
--
count
>
0
);
if
(
uart_circ_chars_pending
(
xmit
)
<
WAKEUP_CHARS
)
uart_write_wakeup
(
&
PORT
);
if
(
uart_circ_empty
(
xmit
))
serial98_stop_tx
(
&
PORT
,
0
);
}
static
void
serial98_modem_status
(
struct
uart_port
*
port
)
{
int
status
;
status
=
serial98_msr_in
(
port
);
if
((
status
&
UART_MSR_ANY_DELTA
)
==
0
)
return
;
if
(
status
&
UART_MSR_TERI
)
PORT
.
icount
.
rng
++
;
if
(
status
&
UART_MSR_DDSR
)
PORT
.
icount
.
dsr
++
;
if
(
status
&
UART_MSR_DDCD
)
uart_handle_dcd_change
(
&
PORT
,
status
&
UART_MSR_DCD
);
if
(
status
&
UART_MSR_DCTS
)
uart_handle_cts_change
(
&
PORT
,
status
&
UART_MSR_CTS
);
wake_up_interruptible
(
&
PORT
.
info
->
delta_msr_wait
);
}
static
void
serial98_int
(
int
irq
,
void
*
port
,
struct
pt_regs
*
regs
)
{
unsigned
int
status
;
spin_lock
(
&
PORT
.
lock
);
status
=
inb
(
PORT
.
iobase
+
2
);
if
(
status
&
PORT98
->
rxrdy
)
{
serial98_rx_chars
(
port
,
&
status
,
regs
);
}
serial98_modem_status
(
port
);
if
(
status
&
PORT98
->
txrdy
)
{
serial98_tx_chars
(
port
);
}
spin_unlock
(
&
PORT
.
lock
);
}
static
unsigned
int
serial98_tx_empty
(
struct
uart_port
*
port
)
{
unsigned
long
flags
;
unsigned
int
ret
=
0
;
spin_lock_irqsave
(
&
PORT
.
lock
,
flags
);
if
(
inb
(
PORT
.
iobase
+
2
)
&
PORT98
->
txemp
)
ret
=
TIOCSER_TEMT
;
spin_unlock_irqrestore
(
&
PORT
.
lock
,
flags
);
return
ret
;
}
static
unsigned
int
serial98_get_mctrl
(
struct
uart_port
*
port
)
{
unsigned
char
status
;
unsigned
int
ret
=
0
;
status
=
serial98_msr_in
(
port
);
if
(
status
&
UART_MSR_DCD
)
ret
|=
TIOCM_CAR
;
if
(
status
&
UART_MSR_RI
)
ret
|=
TIOCM_RNG
;
if
(
status
&
UART_MSR_DSR
)
ret
|=
TIOCM_DSR
;
if
(
status
&
UART_MSR_CTS
)
ret
|=
TIOCM_CTS
;
return
ret
;
}
static
void
serial98_set_mctrl
(
struct
uart_port
*
port
,
unsigned
int
mctrl
)
{
PORT98
->
cmd
&=
0xdd
;
if
(
mctrl
&
TIOCM_RTS
)
PORT98
->
cmd
|=
CMD_RTS
;
if
(
mctrl
&
TIOCM_DTR
)
PORT98
->
cmd
|=
CMD_DTR
;
serial98_cmd_out
(
port
,
PORT98
->
cmd
);
}
static
void
serial98_break_ctl
(
struct
uart_port
*
port
,
int
break_state
)
{
unsigned
long
flags
;
spin_lock_irqsave
(
&
PORT
.
lock
,
flags
);
if
(
break_state
==
-
1
)
PORT98
->
cmd
|=
CMD_BREAK
;
else
PORT98
->
cmd
&=
~
CMD_BREAK
;
serial98_cmd_out
(
port
,
PORT98
->
cmd
);
spin_unlock_irqrestore
(
&
PORT
.
lock
,
flags
);
}
static
int
serial98_startup
(
struct
uart_port
*
port
)
{
int
retval
;
if
(
PORT
.
type
==
PORT_8251_PC98
)
{
/* Wake up UART */
PORT98
->
mode
=
0xfc
;
serial98_mode_set
(
port
);
outb
(
DIS_RXR_INT
,
IER1_CTL
);
outb
(
DIS_TXE_INT
,
IER1_CTL
);
outb
(
DIS_TXR_INT
,
IER1_CTL
);
PORT98
->
mode
=
0
;
serial98_mode_set
(
port
);
}
/*
* Clear the FIFO buffers and disable them.
* (they will be reeanbled in set_termios())
*/
if
(
PORT
.
type
==
PORT_FIFO_PC98
||
PORT
.
type
==
PORT_VFAST_PC98
)
{
outb
(
UART_FCR_ENABLE_FIFO
,
FCR_8251F
);
outb
((
UART_FCR_ENABLE_FIFO
|
UART_FCR_CLEAR_RCVR
|
UART_FCR_CLEAR_XMIT
),
FCR_8251F
);
outb
(
0
,
FCR_8251F
);
}
/* Clear the interrupt registers. */
inb
(
0x30
);
inb
(
0x32
);
if
(
PORT
.
type
==
PORT_FIFO_PC98
||
PORT
.
type
==
PORT_VFAST_PC98
)
{
inb
(
PORT
.
iobase
);
inb
(
PORT
.
iobase
+
2
);
inb
(
PORT
.
iobase
+
4
);
inb
(
PORT
.
iobase
+
6
);
}
/* Allocate the IRQ */
retval
=
request_irq
(
PORT
.
irq
,
serial98_int
,
0
,
serial98_reg
.
driver_name
,
port
);
if
(
retval
)
return
retval
;
/*
* Now, initialize the UART
*/
PORT98
->
mode
=
0x4e
;
serial98_mode_set
(
port
);
PORT98
->
cmd
=
0x15
;
serial98_cmd_out
(
port
,
PORT98
->
cmd
);
PORT98
->
cmd
=
0x05
;
/*
* Finally, enable interrupts
*/
outb
(
0x00
,
IER2_8251F
);
outb
(
ENA_RXR_INT
,
IER1_CTL
);
/*
* And clear the interrupt registers again for luck.
*/
inb
(
0x30
);
inb
(
0x32
);
if
(
PORT
.
type
==
PORT_FIFO_PC98
||
PORT
.
type
==
PORT_VFAST_PC98
)
{
inb
(
PORT
.
iobase
);
inb
(
PORT
.
iobase
+
2
);
inb
(
PORT
.
iobase
+
4
);
inb
(
PORT
.
iobase
+
6
);
}
return
0
;
}
static
void
serial98_shutdown
(
struct
uart_port
*
port
)
{
unsigned
long
flags
;
/*
* disable all interrupts
*/
spin_lock_irqsave
(
&
PORT
.
lock
,
flags
);
if
(
PORT
.
type
==
PORT_VFAST_PC98
)
outb
(
0
,
VFAST_8251F
);
/* V.FAST mode off */
/* disnable all modem status interrupt */
outb
(
0x80
,
IER2_8251F
);
/* disnable TX/RX interrupt */
outb
(
0x00
,
IER2_8251F
);
outb
(
DIS_RXR_INT
,
IER1_CTL
);
outb
(
DIS_TXE_INT
,
IER1_CTL
);
outb
(
DIS_TXR_INT
,
IER1_CTL
);
PORT98
->
ier
=
0
;
spin_unlock_irqrestore
(
&
PORT
.
lock
,
flags
);
/*
* Free the interrupt
*/
free_irq
(
PORT
.
irq
,
port
);
/* disable break condition and disable the port */
serial98_mode_set
(
port
);
/* disable FIFO's */
if
(
PORT
.
type
==
PORT_FIFO_PC98
||
PORT
.
type
==
PORT_VFAST_PC98
)
{
outb
((
UART_FCR_ENABLE_FIFO
|
UART_FCR_CLEAR_RCVR
|
UART_FCR_CLEAR_XMIT
),
FCR_8251F
);
outb
(
0
,
FCR_8251F
);
}
inb
(
PORT
.
iobase
);
}
static
void
serial98_set_termios
(
struct
uart_port
*
port
,
struct
termios
*
termios
,
struct
termios
*
old
)
{
unsigned
char
stopbit
,
cval
,
fcr
=
0
,
ier
=
0
;
unsigned
long
flags
;
unsigned
int
baud
,
quot
;
stopbit
=
0x80
;
switch
(
termios
->
c_cflag
&
CSIZE
)
{
case
CS5
:
cval
=
0x42
;
stopbit
=
0xc0
;
break
;
case
CS6
:
cval
=
0x46
;
break
;
case
CS7
:
cval
=
0x4a
;
break
;
default:
case
CS8
:
cval
=
0x4e
;
break
;
}
if
(
termios
->
c_cflag
&
CSTOPB
)
cval
^=
stopbit
;
if
(
termios
->
c_cflag
&
PARENB
)
cval
|=
0x10
;
if
(
!
(
termios
->
c_cflag
&
PARODD
))
cval
|=
0x20
;
/*
* Ask the core to calculate the divisor for us.
*/
baud
=
uart_get_baud_rate
(
port
,
termios
,
old
,
0
,
port
->
uartclk
/
16
);
quot
=
uart_get_divisor
(
port
,
baud
);
if
(
PORT
.
type
==
PORT_FIFO_PC98
||
PORT
.
type
==
PORT_VFAST_PC98
)
{
if
((
PORT
.
uartclk
/
quot
)
<
(
2400
*
16
))
fcr
=
UART_FCR_ENABLE_FIFO
|
UART_FCR_TRIGGER_1
;
else
fcr
=
UART_FCR_ENABLE_FIFO
|
UART_FCR_TRIGGER_8
;
}
/*
* Ok, we're now changing the port state. Do it with
* interrupts disabled.
*/
spin_lock_irqsave
(
&
PORT
.
lock
,
flags
);
/*
* Update the per-port timeout.
*/
uart_update_timeout
(
port
,
termios
->
c_cflag
,
baud
);
PORT
.
read_status_mask
=
PORT98
->
oe
|
PORT98
->
txemp
|
PORT98
->
dr
;
if
(
termios
->
c_iflag
&
INPCK
)
PORT
.
read_status_mask
|=
PORT98
->
fe
|
PORT98
->
pe
;
if
(
termios
->
c_iflag
&
(
BRKINT
|
PARMRK
))
PORT
.
read_status_mask
|=
PORT98
->
brk
;
/*
* Characters to ignore
*/
PORT
.
ignore_status_mask
=
0
;
if
(
termios
->
c_iflag
&
IGNPAR
)
PORT
.
ignore_status_mask
|=
PORT98
->
fe
|
PORT98
->
pe
;
if
(
termios
->
c_iflag
&
IGNBRK
)
{
PORT
.
ignore_status_mask
|=
PORT98
->
brk
;
/*
* If we're ignoring parity and break indicators,
* ignore overruns too (for real raw support).
*/
if
(
termios
->
c_iflag
&
IGNPAR
)
PORT
.
ignore_status_mask
|=
PORT98
->
oe
;
}
/*
* ignore all characters if CREAD is not set
*/
if
((
termios
->
c_cflag
&
CREAD
)
==
0
)
PORT
.
ignore_status_mask
|=
PORT98
->
dr
;
/*
* CTS flow control flag and modem status interrupts
*/
if
(
PORT
.
flags
&
UPF_HARDPPS_CD
)
ier
|=
0x80
;
/* enable modem status interrupt */
if
(
termios
->
c_cflag
&
CRTSCTS
)
{
ier
|=
0x08
;
/* enable CTS interrupt */
ier
|=
0x80
;
/* enable modem status interrupt */
}
if
(
!
(
termios
->
c_cflag
&
CLOCAL
))
{
ier
|=
0x20
;
/* enable CD interrupt */
ier
|=
0x80
;
/* enable modem status interrupt */
}
PORT98
->
ier
=
ier
;
PORT98
->
mode
=
cval
;
serial98_mode_set
(
port
);
if
(
PORT
.
type
==
PORT_VFAST_PC98
&&
quot
<=
48
)
{
quot
/=
4
;
if
(
quot
<
1
)
quot
=
1
;
outb
(
quot
|
VFAST_ENABLE
,
VFAST_8251F
);
}
else
{
quot
/=
3
;
if
(
quot
<
1
)
quot
=
1
;
if
(
PORT
.
type
==
PORT_VFAST_PC98
)
outb
(
0
,
VFAST_8251F
);
/* V.FAST mode off */
outb
(
0xb6
,
0x77
);
outb
(
quot
&
0xff
,
0x75
);
/* LS of divisor */
outb
(
quot
>>
8
,
0x75
);
/* MS of divisor */
}
if
(
fcr
&
UART_FCR_ENABLE_FIFO
)
{
outb
(
UART_FCR_ENABLE_FIFO
,
FCR_8251F
);
outb
(
fcr
,
FCR_8251F
);
}
/* enable RX/TX */
PORT98
->
cmd
=
0x15
;
serial98_cmd_out
(
port
,
PORT98
->
cmd
);
PORT98
->
cmd
=
0x05
;
/* enable interrupts */
outb
(
0x00
,
IER2_8251F
);
outb
(
ENA_RXR_INT
,
IER1_CTL
);
spin_unlock_irqrestore
(
&
PORT
.
lock
,
flags
);
}
static
const
char
*
serial98_type
(
struct
uart_port
*
port
)
{
char
*
p
;
switch
(
PORT
.
type
)
{
case
PORT_8251_PC98
:
p
=
"PC98 onboard legacy 8251"
;
break
;
case
PORT_19K_PC98
:
p
=
"PC98 onboard max 19200bps"
;
break
;
case
PORT_FIFO_PC98
:
p
=
"PC98 onboard with FIFO"
;
break
;
case
PORT_VFAST_PC98
:
p
=
"PC98 onboard V.FAST"
;
break
;
case
PORT_PC9861
:
p
=
"PC-9861K RS-232C ext. board"
;
break
;
case
PORT_PC9801_101
:
p
=
"PC-9801-101 RS-232C ext. board"
;
break
;
default:
return
NULL
;
}
sprintf
(
type_str
,
"%s Clock %dMHz"
,
p
,
serial98_clk
);
return
type_str
;
}
/* Release the region(s) being used by 'port' */
static
void
serial98_release_port
(
struct
uart_port
*
port
)
{
switch
(
PORT
.
type
)
{
case
PORT_VFAST_PC98
:
release_region
(
PORT
.
iobase
+
0xa
,
1
);
case
PORT_FIFO_PC98
:
release_region
(
PORT
.
iobase
+
8
,
1
);
release_region
(
PORT
.
iobase
+
6
,
1
);
release_region
(
PORT
.
iobase
+
4
,
1
);
release_region
(
PORT
.
iobase
+
2
,
1
);
release_region
(
PORT
.
iobase
,
1
);
case
PORT_19K_PC98
:
release_region
(
SERIAL98_EXT
,
1
);
release_region
(
0x34
,
1
);
case
PORT_8251_PC98
:
release_region
(
0x32
,
1
);
release_region
(
0x30
,
1
);
}
}
/* Request the region(s) being used by 'port' */
#define REQ_REGION98(base) (request_region((base), 1, serial98_reg.driver_name))
static
int
serial98_request_region
(
unsigned
int
type
)
{
if
(
!
REQ_REGION98
(
0x30
))
return
-
EBUSY
;
if
(
REQ_REGION98
(
0x32
))
{
if
(
type
==
PORT_8251_PC98
)
return
0
;
if
(
REQ_REGION98
(
0x34
))
{
if
(
REQ_REGION98
(
SERIAL98_EXT
))
{
unsigned
long
base
;
if
(
type
==
PORT_19K_PC98
)
return
0
;
for
(
base
=
0x130
;
base
<=
0x138
;
base
+=
2
)
{
if
(
!
REQ_REGION98
(
base
))
{
base
-=
2
;
goto
err
;
}
}
if
(
type
==
PORT_FIFO_PC98
)
return
0
;
if
(
type
==
PORT_VFAST_PC98
)
{
if
(
REQ_REGION98
(
0x13a
))
return
0
;
}
err:
while
(
base
>=
0x130
)
{
release_region
(
base
,
1
);
base
-=
2
;
}
release_region
(
SERIAL98_EXT
,
1
);
}
release_region
(
0x34
,
1
);
}
release_region
(
0x32
,
1
);
}
release_region
(
0x30
,
1
);
return
-
EBUSY
;
}
static
int
serial98_request_port
(
struct
uart_port
*
port
)
{
return
serial98_request_region
(
PORT
.
type
);
}
/*
* Configure/autoconfigure the port.
*/
static
void
serial98_config_port
(
struct
uart_port
*
port
,
int
flags
)
{
if
(
flags
&
UART_CONFIG_TYPE
)
PORT
.
type
=
PORT98
->
type
;
}
/*
* verify the new serial_struct (for TIOCSSERIAL).
*/
static
int
serial98_verify_port
(
struct
uart_port
*
port
,
struct
serial_struct
*
ser
)
{
switch
(
ser
->
type
)
{
case
PORT_VFAST_PC98
:
case
PORT_FIFO_PC98
:
case
PORT_19K_PC98
:
case
PORT_8251_PC98
:
/* not implemented yet
case PORT_PC9861:
case PORT_PC9801_101:
*/
case
PORT_UNKNOWN
:
break
;
default:
return
-
EINVAL
;
}
if
(
ser
->
irq
<
0
||
ser
->
irq
>=
NR_IRQS
)
return
-
EINVAL
;
if
(
ser
->
baud_base
<
9600
)
return
-
EINVAL
;
return
0
;
}
static
struct
uart_ops
serial98_ops
=
{
.
tx_empty
=
serial98_tx_empty
,
.
set_mctrl
=
serial98_set_mctrl
,
.
get_mctrl
=
serial98_get_mctrl
,
.
stop_tx
=
serial98_stop_tx
,
.
start_tx
=
serial98_start_tx
,
.
stop_rx
=
serial98_stop_rx
,
.
enable_ms
=
serial98_enable_ms
,
.
break_ctl
=
serial98_break_ctl
,
.
startup
=
serial98_startup
,
.
shutdown
=
serial98_shutdown
,
.
set_termios
=
serial98_set_termios
,
.
type
=
serial98_type
,
.
release_port
=
serial98_release_port
,
.
request_port
=
serial98_request_port
,
.
config_port
=
serial98_config_port
,
.
verify_port
=
serial98_verify_port
,
};
static
struct
serial98_port
serial98_ports
[
SERIAL98_NR
]
=
{
{
.
port
=
{
.
iobase
=
0x30
,
.
iotype
=
SERIAL_IO_PORT
,
.
irq
=
4
,
.
fifosize
=
1
,
.
ops
=
&
serial98_ops
,
.
flags
=
ASYNC_BOOT_AUTOCONF
,
.
line
=
0
,
},
.
rxchk
=
STAT_8251_RXRDY
,
.
txemp
=
STAT_8251_TXEMP
,
.
txrdy
=
STAT_8251_TXRDY
,
.
rxrdy
=
STAT_8251_RXRDY
,
.
brk
=
STAT_8251_BRK
,
.
fe
=
STAT_8251_FER
,
.
oe
=
STAT_8251_OER
,
.
pe
=
STAT_8251_PER
,
.
dr
=
STAT_8251_DSR
,
},
};
#ifdef CONFIG_SERIAL98_CONSOLE
#define BOTH_EMPTY (PORT98->txemp | PORT98->txrdy)
/*
* Wait for transmitter & holding register to empty
*/
static
inline
void
wait_for_xmitr
(
struct
uart_port
*
port
)
{
unsigned
int
status
,
tmout
=
10000
;
/* Wait up to 10ms for the character(s) to be sent. */
do
{
status
=
inb
(
PORT
.
iobase
+
2
);
if
(
status
&
PORT98
->
brk
)
PORT98
->
lsr_break_flag
=
PORT98
->
brk
;
if
(
--
tmout
==
0
)
break
;
udelay
(
1
);
}
while
((
status
&
BOTH_EMPTY
)
!=
BOTH_EMPTY
);
/* Wait up to 1s for flow control if necessary */
if
(
PORT
.
flags
&
UPF_CONS_FLOW
)
{
tmout
=
1000000
;
while
(
--
tmout
&&
((
serial98_msr_in
(
port
)
&
UART_MSR_CTS
)
==
0
))
udelay
(
1
);
}
}
/*
* Print a string to the serial port trying not to disturb
* any possible real use of the port...
*
* The console_lock must be held when we get here.
*/
static
void
serial98_console_write
(
struct
console
*
co
,
const
char
*
s
,
unsigned
int
count
)
{
struct
uart_port
*
port
=
(
struct
uart_port
*
)
&
serial98_ports
[
co
->
index
];
unsigned
int
ier1
,
ier2
;
int
i
;
/*
* First save the UER then disable the interrupts
*/
ier1
=
inb
(
IER1_8251F
);
ier2
=
inb
(
IER2_8251F
);
/* disnable all modem status interrupt */
outb
(
0x80
,
IER2_8251F
);
/* disnable TX/RX interrupt */
outb
(
0x00
,
IER2_8251F
);
outb
(
DIS_RXR_INT
,
IER1_CTL
);
outb
(
DIS_TXE_INT
,
IER1_CTL
);
outb
(
DIS_TXR_INT
,
IER1_CTL
);
/*
* Now, do each character
*/
for
(
i
=
0
;
i
<
count
;
i
++
,
s
++
)
{
wait_for_xmitr
(
port
);
/*
* Send the character out.
* If a LF, also do CR...
*/
outb
(
*
s
,
PORT
.
iobase
);
if
(
*
s
==
10
)
{
wait_for_xmitr
(
port
);
outb
(
13
,
PORT
.
iobase
);
}
}
/*
* Finally, wait for transmitter to become empty
* and restore the IER
*/
wait_for_xmitr
(
port
);
/* restore TX/RX interrupt */
outb
(
0x00
,
IER2_8251F
);
if
(
ier1
&
0x01
)
outb
(
ENA_RXR_INT
,
IER1_CTL
);
if
(
ier1
&
0x02
)
outb
(
ENA_TXE_INT
,
IER1_CTL
);
if
(
ier1
&
0x04
)
outb
(
ENA_TXR_INT
,
IER1_CTL
);
/* restore modem status interrupt */
outb
(
ier2
,
IER2_8251F
);
}
static
int
__init
serial98_console_setup
(
struct
console
*
co
,
char
*
options
)
{
struct
uart_port
*
port
;
int
baud
=
9600
;
int
bits
=
8
;
int
parity
=
'n'
;
int
flow
=
'n'
;
/*
* Check whether an invalid uart number has been specified, and
* if so, search for the first available port that does have
* console support.
*/
if
(
co
->
index
>=
SERIAL98_NR
)
co
->
index
=
0
;
port
=
&
serial98_ports
[
co
->
index
].
port
;
/*
* Temporary fix.
*/
spin_lock_init
(
&
port
->
lock
);
if
(
options
)
uart_parse_options
(
options
,
&
baud
,
&
parity
,
&
bits
,
&
flow
);
return
uart_set_options
(
port
,
co
,
baud
,
parity
,
bits
,
flow
);
}
void
__init
serial98_console_init
(
void
)
{
register_console
(
&
serial98_console
);
}
#endif
/* CONFIG_SERIAL98_CONSOLE */
static
int
__init
serial98_init
(
void
)
{
int
ret
;
unsigned
char
iir1
,
iir2
;
if
(
PC9800_8MHz_P
())
{
serial98_clk
=
8
;
serial98_ports
[
0
].
port
.
uartclk
=
374400
*
16
;
}
else
{
serial98_clk
=
5
;
serial98_ports
[
0
].
port
.
uartclk
=
460800
*
16
;
}
printk
(
KERN_INFO
"serial98: PC-9801 standard serial port driver Version 0.1alpha
\n
"
);
serial98_ports
[
0
].
type
=
PORT_8251_PC98
;
/* Check FIFO exist */
iir1
=
inb
(
IIR_8251F
);
iir2
=
inb
(
IIR_8251F
);
if
((
iir1
&
0x40
)
!=
(
iir2
&
0x40
)
&&
(
iir1
&
0x20
)
==
(
iir2
&
0x20
))
{
serial98_ports
[
0
].
port
.
iobase
=
0x130
;
serial98_ports
[
0
].
port
.
fifosize
=
16
;
serial98_ports
[
0
].
rxchk
=
STAT_8251F_DSR
;
serial98_ports
[
0
].
txemp
=
STAT_8251F_TXEMP
;
serial98_ports
[
0
].
txrdy
=
STAT_8251F_TXRDY
;
serial98_ports
[
0
].
rxrdy
=
STAT_8251F_RXRDY
;
serial98_ports
[
0
].
brk
=
STAT_8251F_BRK
;
serial98_ports
[
0
].
fe
=
STAT_8251F_FER
;
serial98_ports
[
0
].
oe
=
STAT_8251F_OER
;
serial98_ports
[
0
].
pe
=
STAT_8251F_PER
;
serial98_ports
[
0
].
dr
=
STAT_8251F_DSR
;
if
(
*
(
unsigned
char
*
)
__va
(
PC9821SCA_RSFLAGS
)
&
0x10
)
serial98_ports
[
0
].
type
=
PORT_VFAST_PC98
;
else
{
outb
(
serial98_ports
[
0
].
ext
|
0x40
,
SERIAL98_EXT
);
serial98_ports
[
0
].
port
.
uartclk
*=
4
;
serial98_ports
[
0
].
type
=
PORT_FIFO_PC98
;
}
}
else
if
((
serial98_ports
[
0
].
ext
=
inb
(
SERIAL98_EXT
))
!=
0xff
)
{
outb
(
serial98_ports
[
0
].
ext
|
0x40
,
SERIAL98_EXT
);
if
(
inb
(
SERIAL98_EXT
)
==
(
serial98_ports
[
0
].
ext
|
0x40
))
{
serial98_ports
[
0
].
port
.
uartclk
*=
4
;
serial98_ports
[
0
].
type
=
PORT_19K_PC98
;
}
else
{
serial98_ops
.
enable_ms
=
NULL
;
outb
(
serial98_ports
[
0
].
ext
,
SERIAL98_EXT
);
}
}
if
(
serial98_request_region
(
serial98_ports
[
0
].
type
))
return
-
EBUSY
;
ret
=
uart_register_driver
(
&
serial98_reg
);
if
(
ret
==
0
)
{
int
i
;
for
(
i
=
0
;
i
<
SERIAL98_NR
;
i
++
)
{
uart_add_one_port
(
&
serial98_reg
,
(
struct
uart_port
*
)
&
serial98_ports
[
i
]);
}
}
return
ret
;
}
static
void
__exit
serial98_exit
(
void
)
{
int
i
;
if
(
serial98_ports
[
0
].
type
==
PORT_19K_PC98
||
serial98_ports
[
0
].
type
==
PORT_FIFO_PC98
)
outb
(
serial98_ports
[
0
].
ext
,
SERIAL98_EXT
);
for
(
i
=
0
;
i
<
SERIAL98_NR
;
i
++
)
{
uart_remove_one_port
(
&
serial98_reg
,
(
struct
uart_port
*
)
&
serial98_ports
[
i
]);
}
uart_unregister_driver
(
&
serial98_reg
);
}
module_init
(
serial98_init
);
module_exit
(
serial98_exit
);
MODULE_AUTHOR
(
"Osamu Tomita <tomita@cinet.co.jp>"
);
MODULE_DESCRIPTION
(
"PC-9801 standard serial port driver Version 0.1alpha"
);
MODULE_LICENSE
(
"GPL"
);
fs/partitions/nec98.c
deleted
100644 → 0
View file @
bffc8f71
/*
* NEC PC-9800 series partition supports
*
* Copyright (C) 1999 Kyoto University Microcomputer Club
*/
#include <linux/config.h>
#include <linux/fs.h>
#include <linux/genhd.h>
#include <linux/kernel.h>
#include <linux/hdreg.h>
#include "check.h"
#include "nec98.h"
struct
nec98_partition
{
__u8
mid
;
/* 0x80 - active */
__u8
sid
;
/* 0x80 - bootable */
__u16
pad1
;
/* dummy for padding */
__u8
ipl_sector
;
/* IPL sector */
__u8
ipl_head
;
/* IPL head */
__u16
ipl_cyl
;
/* IPL cylinder */
__u8
sector
;
/* starting sector */
__u8
head
;
/* starting head */
__u16
cyl
;
/* starting cylinder */
__u8
end_sector
;
/* end sector */
__u8
end_head
;
/* end head */
__u16
end_cyl
;
/* end cylinder */
unsigned
char
name
[
16
];
}
__attribute__
((
__packed__
));
#define NEC98_BSD_PARTITION_MID 0x14
#define NEC98_BSD_PARTITION_SID 0x44
#define MID_SID_16(mid, sid) (((mid) & 0xFF) | (((sid) & 0xFF) << 8))
#define NEC98_BSD_PARTITION_MID_SID \
MID_SID_16(NEC98_BSD_PARTITION_MID, NEC98_BSD_PARTITION_SID)
#define NEC98_VALID_PTABLE_ENTRY(P) \
(!(P)->pad1 && (P)->cyl <= (P)->end_cyl)
extern
int
pc98_bios_param
(
struct
block_device
*
bdev
,
int
*
ip
);
static
inline
int
is_valid_nec98_partition_table
(
const
struct
nec98_partition
*
ptable
,
__u8
nsectors
,
__u8
nheads
)
{
int
i
;
int
valid
=
0
;
for
(
i
=
0
;
i
<
16
;
i
++
)
{
if
(
!*
(
__u16
*
)
&
ptable
[
i
])
continue
;
/* empty slot */
if
(
ptable
[
i
].
pad1
/* `pad1' contains junk */
||
ptable
[
i
].
ipl_sector
>=
nsectors
||
ptable
[
i
].
sector
>=
nsectors
||
ptable
[
i
].
end_sector
>=
nsectors
||
ptable
[
i
].
ipl_head
>=
nheads
||
ptable
[
i
].
head
>=
nheads
||
ptable
[
i
].
end_head
>=
nheads
||
ptable
[
i
].
cyl
>
ptable
[
i
].
end_cyl
)
return
0
;
valid
=
1
;
/* We have a valid partition. */
}
/* If no valid PC-9800-style partitions found,
the disk may have other type of partition table. */
return
valid
;
}
int
nec98_partition
(
struct
parsed_partitions
*
state
,
struct
block_device
*
bdev
)
{
unsigned
int
nr
;
struct
hd_geometry
geo
;
Sector
sect
;
const
struct
nec98_partition
*
part
;
unsigned
char
*
data
;
int
sector_size
=
bdev_hardsect_size
(
bdev
);
if
(
ioctl_by_bdev
(
bdev
,
HDIO_GETGEO
,
(
unsigned
long
)
&
geo
)
!=
0
)
{
printk
(
" unsupported disk (%s)
\n
"
,
bdev
->
bd_disk
->
disk_name
);
return
0
;
}
#ifdef NEC98_PARTITION_DEBUG
printk
(
"ioctl_by_bdev head=%d sect=%d
\n
"
,
geo
.
heads
,
geo
.
sectors
);
#endif
data
=
read_dev_sector
(
bdev
,
0
,
&
sect
);
if
(
!
data
)
{
if
(
warn_no_part
)
printk
(
" unable to read partition table
\n
"
);
return
-
1
;
}
/* magic(?) check */
if
(
*
(
__u16
*
)(
data
+
sector_size
-
2
)
!=
NEC98_PTABLE_MAGIC
)
{
put_dev_sector
(
sect
);
return
0
;
}
put_dev_sector
(
sect
);
data
=
read_dev_sector
(
bdev
,
1
,
&
sect
);
if
(
!
data
)
{
if
(
warn_no_part
)
printk
(
" unable to read partition table
\n
"
);
return
-
1
;
}
if
(
!
is_valid_nec98_partition_table
((
struct
nec98_partition
*
)
data
,
geo
.
sectors
,
geo
.
heads
))
{
#ifdef NEC98_PARTITION_DEBUG
if
(
warn_no_part
)
printk
(
" partition table consistency check failed"
" (not PC-9800 disk?)
\n
"
);
#endif
put_dev_sector
(
sect
);
return
0
;
}
part
=
(
const
struct
nec98_partition
*
)
data
;
for
(
nr
=
0
;
nr
<
16
;
nr
++
,
part
++
)
{
unsigned
int
start_sect
,
end_sect
;
if
(
part
->
mid
==
0
||
part
->
sid
==
0
)
continue
;
if
(
nr
)
printk
(
" "
);
{
/* Print partition name. Fdisk98 might put NUL
characters in partition name... */
int
j
;
unsigned
char
*
p
;
unsigned
char
buf
[
sizeof
(
part
->
name
)
*
2
+
1
];
for
(
p
=
buf
,
j
=
0
;
j
<
sizeof
(
part
->
name
);
j
++
,
p
++
)
if
((
*
p
=
part
->
name
[
j
])
<
' '
)
{
*
p
++
=
'^'
;
*
p
=
part
->
name
[
j
]
+
'@'
;
}
*
p
=
0
;
printk
(
" <%s>"
,
buf
);
}
start_sect
=
(
part
->
cyl
*
geo
.
heads
+
part
->
head
)
*
geo
.
sectors
+
part
->
sector
;
end_sect
=
(
part
->
end_cyl
+
1
)
*
geo
.
heads
*
geo
.
sectors
;
if
(
end_sect
<=
start_sect
)
{
printk
(
" (invalid partition info)
\n
"
);
continue
;
}
put_partition
(
state
,
nr
+
1
,
start_sect
,
end_sect
-
start_sect
);
#ifdef CONFIG_BSD_DISKLABEL
if
((
*
(
__u16
*
)
&
part
->
mid
&
0x7F7F
)
==
NEC98_BSD_PARTITION_MID_SID
)
{
printk
(
"!"
);
/* NEC98_BSD_PARTITION_MID_SID is not valid SYSIND for
IBM PC's MS-DOS partition table, so we simply pass
it to bsd_disklabel_partition;
it will just print `<bsd: ... >'. */
parse_bsd
(
state
,
bdev
,
start_sect
,
end_sect
-
start_sect
,
nr
+
1
,
"bsd98"
,
BSD_MAXPARTITIONS
);
}
#endif
{
/* Pretty size printing. */
/* XXX sector size? */
unsigned
int
psize
=
(
end_sect
-
start_sect
)
/
2
;
int
unit_char
=
'K'
;
if
(
psize
>
99999
)
{
psize
>>=
10
;
unit_char
=
'M'
;
}
printk
(
" %5d%cB (%5d-%5d)
\n
"
,
psize
,
unit_char
,
part
->
cyl
,
part
->
end_cyl
);
}
}
put_dev_sector
(
sect
);
return
nr
?
1
:
0
;
}
/*
* Local variables:
* c-basic-offset: 8
* End:
*/
fs/partitions/nec98.h
deleted
100644 → 0
View file @
bffc8f71
/*
* NEC PC-9800 series partition supports
*
* Copyright (C) 1998-2000 Kyoto University Microcomputer Club
*/
#define NEC98_PTABLE_MAGIC 0xAA55
extern
int
nec98_partition
(
struct
parsed_partitions
*
state
,
struct
block_device
*
bdev
);
include/asm-i386/mach-pc9800/apm.h
deleted
100644 → 0
View file @
bffc8f71
/*
* include/asm-i386/mach-pc9800/apm.h
*
* Machine specific APM BIOS functions for NEC PC9800.
* Split out from apm.c by Osamu Tomita <tomita@cinet.co.jp>
*/
#ifndef _ASM_APM_H
#define _ASM_APM_H
#include <linux/apm_bios.h>
#ifdef APM_ZERO_SEGS
# define APM_DO_ZERO_SEGS \
"pushl %%ds\n\t" \
"pushl %%es\n\t" \
"xorl %%edx, %%edx\n\t" \
"mov %%dx, %%ds\n\t" \
"mov %%dx, %%es\n\t" \
"mov %%dx, %%fs\n\t" \
"mov %%dx, %%gs\n\t"
# define APM_DO_POP_SEGS \
"popl %%es\n\t" \
"popl %%ds\n\t"
#else
# define APM_DO_ZERO_SEGS
# define APM_DO_POP_SEGS
#endif
static
inline
void
apm_bios_call_asm
(
u32
func
,
u32
ebx_in
,
u32
ecx_in
,
u32
*
eax
,
u32
*
ebx
,
u32
*
ecx
,
u32
*
edx
,
u32
*
esi
)
{
/*
* N.B. We do NOT need a cld after the BIOS call
* because we always save and restore the flags.
*/
__asm__
__volatile__
(
APM_DO_ZERO_SEGS
"pushl %%edi
\n\t
"
"pushl %%ebp
\n\t
"
"pushfl
\n\t
"
"lcall *%%cs:apm_bios_entry
\n\t
"
"setc %%al
\n\t
"
"popl %%ebp
\n\t
"
"popl %%edi
\n\t
"
APM_DO_POP_SEGS
:
"=a"
(
*
eax
),
"=b"
(
*
ebx
),
"=c"
(
*
ecx
),
"=d"
(
*
edx
),
"=S"
(
*
esi
)
:
"a"
(
func
),
"b"
(
ebx_in
),
"c"
(
ecx_in
)
:
"memory"
,
"cc"
);
}
static
inline
u8
apm_bios_call_simple_asm
(
u32
func
,
u32
ebx_in
,
u32
ecx_in
,
u32
*
eax
)
{
int
cx
,
dx
,
si
;
u8
error
;
/*
* N.B. We do NOT need a cld after the BIOS call
* because we always save and restore the flags.
*/
__asm__
__volatile__
(
APM_DO_ZERO_SEGS
"pushl %%edi
\n\t
"
"pushl %%ebp
\n\t
"
"pushfl
\n\t
"
"lcall *%%cs:apm_bios_entry
\n\t
"
"setc %%bl
\n\t
"
"popl %%ebp
\n\t
"
"popl %%edi
\n\t
"
APM_DO_POP_SEGS
:
"=a"
(
*
eax
),
"=b"
(
error
),
"=c"
(
cx
),
"=d"
(
dx
),
"=S"
(
si
)
:
"a"
(
func
),
"b"
(
ebx_in
),
"c"
(
ecx_in
)
:
"memory"
,
"cc"
);
if
(
func
==
APM_FUNC_VERSION
)
*
eax
=
(
*
eax
&
0xff00
)
|
((
*
eax
&
0x00f0
)
>>
4
);
return
error
;
}
#endif
/* _ASM_APM_H */
include/asm-i386/mach-pc9800/bios_ebda.h
deleted
100644 → 0
View file @
bffc8f71
#ifndef _MACH_BIOS_EBDA_H
#define _MACH_BIOS_EBDA_H
/*
* PC-9800 has no EBDA.
* Its BIOS uses 0x40E for other purpose,
* Not pointer to 4K EBDA area.
*/
static
inline
unsigned
int
get_bios_ebda
(
void
)
{
return
0
;
/* 0 means none */
}
#endif
/* _MACH_BIOS_EBDA_H */
include/asm-i386/mach-pc9800/do_timer.h
deleted
100644 → 0
View file @
bffc8f71
/* defines for inline arch setup functions */
#include <asm/apic.h>
/**
* do_timer_interrupt_hook - hook into timer tick
* @regs: standard registers from interrupt
*
* Description:
* This hook is called immediately after the timer interrupt is ack'd.
* It's primary purpose is to allow architectures that don't possess
* individual per CPU clocks (like the CPU APICs supply) to broadcast the
* timer interrupt as a means of triggering reschedules etc.
**/
static
inline
void
do_timer_interrupt_hook
(
struct
pt_regs
*
regs
)
{
do_timer
(
regs
);
/*
* In the SMP case we use the local APIC timer interrupt to do the
* profiling, except when we simulate SMP mode on a uniprocessor
* system, in that case we have to call the local interrupt handler.
*/
#ifndef CONFIG_X86_LOCAL_APIC
x86_do_profile
(
regs
);
#else
if
(
!
using_apic_timer
)
smp_local_timer_interrupt
(
regs
);
#endif
}
/* you can safely undefine this if you don't have the Neptune chipset */
#define BUGGY_NEPTUN_TIMER
/**
* do_timer_overflow - process a detected timer overflow condition
* @count: hardware timer interrupt count on overflow
*
* Description:
* This call is invoked when the jiffies count has not incremented but
* the hardware timer interrupt has. It means that a timer tick interrupt
* came along while the previous one was pending, thus a tick was missed
**/
static
inline
int
do_timer_overflow
(
int
count
)
{
int
i
;
spin_lock
(
&
i8259A_lock
);
/*
* This is tricky when I/O APICs are used;
* see do_timer_interrupt().
*/
i
=
inb
(
0x00
);
spin_unlock
(
&
i8259A_lock
);
/* assumption about timer being IRQ0 */
if
(
i
&
0x01
)
{
/*
* We cannot detect lost timer interrupts ...
* well, that's why we call them lost, don't we? :)
* [hmm, on the Pentium and Alpha we can ... sort of]
*/
count
-=
LATCH
;
}
else
{
#ifdef BUGGY_NEPTUN_TIMER
/*
* for the Neptun bug we know that the 'latch'
* command doesn't latch the high and low value
* of the counter atomically. Thus we have to
* substract 256 from the counter
* ... funny, isnt it? :)
*/
count
-=
256
;
#else
printk
(
"do_slow_gettimeoffset(): hardware timer problem?
\n
"
);
#endif
}
return
count
;
}
include/asm-i386/mach-pc9800/io_ports.h
deleted
100644 → 0
View file @
bffc8f71
/*
* arch/i386/mach-pc9800/io_ports.h
*
* Machine specific IO port address definition for PC-9800.
* Written by Osamu Tomita <tomita@cinet.co.jp>
*/
#ifndef _MACH_IO_PORTS_H
#define _MACH_IO_PORTS_H
/* i8253A PIT registers */
#define PIT_MODE 0x77
#define PIT_CH0 0x71
#define PIT_CH2 0x75
/* i8259A PIC registers */
#define PIC_MASTER_CMD 0x00
#define PIC_MASTER_IMR 0x02
#define PIC_MASTER_ISR PIC_MASTER_CMD
#define PIC_MASTER_POLL PIC_MASTER_ISR
#define PIC_MASTER_OCW3 PIC_MASTER_ISR
#define PIC_SLAVE_CMD 0x08
#define PIC_SLAVE_IMR 0x0a
/* i8259A PIC related values */
#define PIC_CASCADE_IR 7
#define MASTER_ICW4_DEFAULT 0x1d
#define SLAVE_ICW4_DEFAULT 0x09
#define PIC_ICW4_AEOI 0x02
#endif
/* !_MACH_IO_PORTS_H */
include/asm-i386/mach-pc9800/irq_vectors.h
deleted
100644 → 0
View file @
bffc8f71
/*
* This file should contain #defines for all of the interrupt vector
* numbers used by this architecture.
*
* In addition, there are some standard defines:
*
* FIRST_EXTERNAL_VECTOR:
* The first free place for external interrupts
*
* SYSCALL_VECTOR:
* The IRQ vector a syscall makes the user to kernel transition
* under.
*
* TIMER_IRQ:
* The IRQ number the timer interrupt comes in at.
*
* NR_IRQS:
* The total number of interrupt vectors (including all the
* architecture specific interrupts) needed.
*
* NR_IRQ_VECTORS:
* The total number of IO APIC vector inputs
*
*/
#ifndef _ASM_IRQ_VECTORS_H
#define _ASM_IRQ_VECTORS_H
/*
* IDT vectors usable for external interrupt sources start
* at 0x20:
*/
#define FIRST_EXTERNAL_VECTOR 0x20
#define SYSCALL_VECTOR 0x80
/*
* Vectors 0x20-0x2f are used for ISA interrupts.
*/
/*
* Special IRQ vectors used by the SMP architecture, 0xf0-0xff
*
* some of the following vectors are 'rare', they are merged
* into a single vector (CALL_FUNCTION_VECTOR) to save vector space.
* TLB, reschedule and local APIC vectors are performance-critical.
*
* Vectors 0xf0-0xfa are free (reserved for future Linux use).
*/
#define SPURIOUS_APIC_VECTOR 0xff
#define ERROR_APIC_VECTOR 0xfe
#define INVALIDATE_TLB_VECTOR 0xfd
#define RESCHEDULE_VECTOR 0xfc
#define CALL_FUNCTION_VECTOR 0xfb
#define THERMAL_APIC_VECTOR 0xf0
/*
* Local APIC timer IRQ vector is on a different priority level,
* to work around the 'lost local interrupt if more than 2 IRQ
* sources per level' errata.
*/
#define LOCAL_TIMER_VECTOR 0xef
/*
* First APIC vector available to drivers: (vectors 0x30-0xee)
* we start at 0x31 to spread out vectors evenly between priority
* levels. (0x80 is the syscall vector)
*/
#define FIRST_DEVICE_VECTOR 0x31
#define FIRST_SYSTEM_VECTOR 0xef
#define TIMER_IRQ 0
/*
* 16 8259A IRQ's, 208 potential APIC interrupt sources.
* Right now the APIC is mostly only used for SMP.
* 256 vectors is an architectural limit. (we can have
* more than 256 devices theoretically, but they will
* have to use shared interrupts)
* Since vectors 0x00-0x1f are used/reserved for the CPU,
* the usable vector space is 0x20-0xff (224 vectors)
*/
#ifdef CONFIG_X86_IO_APIC
#define NR_IRQS 224
#else
#define NR_IRQS 16
#endif
#define NR_VECTORS 256
#define NR_IRQ_VECTORS NR_IRQS
#define FPU_IRQ 8
#define FIRST_VM86_IRQ 2
#define LAST_VM86_IRQ 15
#define invalid_vm86_irq(irq) ((irq) < 2 || (irq) == 7 || (irq) > 15)
#endif
/* _ASM_IRQ_VECTORS_H */
include/asm-i386/mach-pc9800/mach_reboot.h
deleted
100644 → 0
View file @
bffc8f71
/*
* arch/i386/mach-pc9800/mach_reboot.h
*
* Machine specific reboot functions for PC-9800.
* Written by Osamu Tomita <tomita@cinet.co.jp>
*/
#ifndef _MACH_REBOOT_H
#define _MACH_REBOOT_H
#ifdef CMOS_WRITE
#undef CMOS_WRITE
#define CMOS_WRITE(a,b) do{}while(0)
#endif
static
inline
void
mach_reboot
(
void
)
{
outb
(
0
,
0xf0
);
/* signal CPU reset */
mdelay
(
1
);
}
#endif
/* !_MACH_REBOOT_H */
include/asm-i386/mach-pc9800/mach_time.h
deleted
100644 → 0
View file @
bffc8f71
/*
* include/asm-i386/mach-pc9800/mach_time.h
*
* Machine specific set RTC function for PC-9800.
* Written by Osamu Tomita <tomita@cinet.co.jp>
*/
#ifndef _MACH_TIME_H
#define _MACH_TIME_H
#include <linux/bcd.h>
#include <linux/upd4990a.h>
/* for check timing call set_rtc_mmss() */
/* used in arch/i386/time.c::do_timer_interrupt() */
/*
* Because PC-9800's RTC (NEC uPD4990A) does not allow setting
* time partially, we always have to read-modify-write the
* entire time (including year) so that set_rtc_mmss() will
* take quite much time to execute. You may want to relax
* RTC resetting interval (currently ~11 minuts)...
*/
#define USEC_AFTER 1000000
#define USEC_BEFORE 0
static
inline
int
mach_set_rtc_mmss
(
unsigned
long
nowtime
)
{
int
retval
=
0
;
int
real_seconds
,
real_minutes
,
cmos_minutes
;
struct
upd4990a_raw_data
data
;
upd4990a_get_time
(
&
data
,
1
);
cmos_minutes
=
BCD2BIN
(
data
.
min
);
/*
* since we're only adjusting minutes and seconds,
* don't interfere with hour overflow. This avoids
* messing with unknown time zones but requires your
* RTC not to be off by more than 15 minutes
*/
real_seconds
=
nowtime
%
60
;
real_minutes
=
nowtime
/
60
;
if
(((
abs
(
real_minutes
-
cmos_minutes
)
+
15
)
/
30
)
&
1
)
real_minutes
+=
30
;
/* correct for half hour time zone */
real_minutes
%=
60
;
if
(
abs
(
real_minutes
-
cmos_minutes
)
<
30
)
{
u8
temp_seconds
=
(
real_seconds
/
10
)
*
16
+
real_seconds
%
10
;
u8
temp_minutes
=
(
real_minutes
/
10
)
*
16
+
real_minutes
%
10
;
if
(
data
.
sec
!=
temp_seconds
||
data
.
min
!=
temp_minutes
)
{
data
.
sec
=
temp_seconds
;
data
.
min
=
temp_minutes
;
upd4990a_set_time
(
&
data
,
1
);
}
}
else
{
printk
(
KERN_WARNING
"set_rtc_mmss: can't update from %d to %d
\n
"
,
cmos_minutes
,
real_minutes
);
retval
=
-
1
;
}
/* uPD4990A users' manual says we should issue Register Hold
* command after reading time, or future Time Read command
* may not work. When we have set the time, this also starts
* the clock.
*/
upd4990a_serial_command
(
UPD4990A_REGISTER_HOLD
);
return
retval
;
}
static
inline
unsigned
long
mach_get_cmos_time
(
void
)
{
int
i
;
u8
prev
,
cur
;
unsigned
int
year
;
struct
upd4990a_raw_data
data
;
/* Connect uPD4990A's DATA OUT pin to its 1Hz reference clock. */
upd4990a_serial_command
(
UPD4990A_REGISTER_HOLD
);
/* Catch rising edge of reference clock. */
prev
=
~
UPD4990A_READ_DATA
();
for
(
i
=
0
;
i
<
1800000
;
i
++
)
{
/* may take up to 1 second... */
__asm__
(
"outb %%al,%0"
:
:
"N"
(
0x5f
));
/* 0.6usec delay */
cur
=
UPD4990A_READ_DATA
();
if
(
!
(
prev
&
cur
&
1
))
break
;
prev
=
~
cur
;
}
upd4990a_get_time
(
&
data
,
0
);
if
((
year
=
BCD2BIN
(
data
.
year
)
+
1900
)
<
1995
)
year
+=
100
;
return
mktime
(
year
,
data
.
mon
,
BCD2BIN
(
data
.
mday
),
BCD2BIN
(
data
.
hour
),
BCD2BIN
(
data
.
min
),
BCD2BIN
(
data
.
sec
));
}
#endif
/* !_MACH_TIME_H */
include/asm-i386/mach-pc9800/mach_timer.h
deleted
100644 → 0
View file @
bffc8f71
/*
* include/asm-i386/mach-pc9800/mach_timer.h
*
* Machine specific calibrate_tsc() for PC-9800.
* Written by Osamu Tomita <tomita@cinet.co.jp>
*/
/* ------ Calibrate the TSC -------
* PC-9800:
* CTC cannot be used because some models (especially
* note-machines) may disable clock to speaker channel (#1)
* unless speaker is enabled. We use ARTIC instead.
*/
#ifndef _MACH_TIMER_H
#define _MACH_TIMER_H
#define CALIBRATE_LATCH (5 * 307200/HZ)
/* 0.050sec * 307200Hz = 15360 */
static
inline
void
mach_prepare_counter
(
void
)
{
/* ARTIC can't be stopped nor reset. So we wait roundup. */
while
(
inw
(
0x5c
));
}
static
inline
void
mach_countup
(
unsigned
long
*
count
)
{
do
{
*
count
=
inw
(
0x5c
);
}
while
(
*
count
<
CALIBRATE_LATCH
);
}
#endif
/* !_MACH_TIMER_H */
include/asm-i386/mach-pc9800/mach_traps.h
deleted
100644 → 0
View file @
bffc8f71
/*
* include/asm-i386/mach-pc9800/mach_traps.h
*
* Machine specific NMI handling for PC-9800.
* Written by Osamu Tomita <tomita@cinet.co.jp>
*/
#ifndef _MACH_TRAPS_H
#define _MACH_TRAPS_H
static
inline
void
clear_mem_error
(
unsigned
char
reason
)
{
outb
(
0x08
,
0x37
);
outb
(
0x09
,
0x37
);
}
static
inline
unsigned
char
get_nmi_reason
(
void
)
{
return
(
inb
(
0x33
)
&
6
)
?
0x80
:
0
;
}
static
inline
void
reassert_nmi
(
void
)
{
outb
(
0x09
,
0x50
);
/* disable NMI once */
outb
(
0x09
,
0x52
);
/* re-enable it */
}
#endif
/* !_MACH_TRAPS_H */
include/asm-i386/mach-pc9800/mach_wakecpu.h
deleted
100644 → 0
View file @
bffc8f71
#ifndef __ASM_MACH_WAKECPU_H
#define __ASM_MACH_WAKECPU_H
/*
* This file copes with machines that wakeup secondary CPUs by the
* INIT, INIT, STARTUP sequence.
*/
#define WAKE_SECONDARY_VIA_INIT
/*
* On PC-9800, continuation on warm reset is done by loading
* %ss:%sp from 0x0000:0404 and executing 'lret', so:
*/
#define TRAMPOLINE_LOW phys_to_virt(0x4fa)
#define TRAMPOLINE_HIGH phys_to_virt(0x4fc)
#define boot_cpu_apicid boot_cpu_physical_apicid
static
inline
void
wait_for_init_deassert
(
atomic_t
*
deassert
)
{
while
(
!
atomic_read
(
deassert
));
return
;
}
/* Nothing to do for most platforms, since cleared by the INIT cycle */
static
inline
void
smp_callin_clear_local_apic
(
void
)
{
}
static
inline
void
store_NMI_vector
(
unsigned
short
*
high
,
unsigned
short
*
low
)
{
}
static
inline
void
restore_NMI_vector
(
unsigned
short
*
high
,
unsigned
short
*
low
)
{
}
#if APIC_DEBUG
#define inquire_remote_apic(apicid) __inquire_remote_apic(apicid)
#else
#define inquire_remote_apic(apicid) {}
#endif
#endif
/* __ASM_MACH_WAKECPU_H */
include/asm-i386/mach-pc9800/pci-functions.h
deleted
100644 → 0
View file @
bffc8f71
/*
* PCI BIOS function codes for the PC9800. Different to
* standard PC systems
*/
/* Note: PC-9800 confirms PCI 2.1 on only few models */
#define PCIBIOS_PCI_FUNCTION_ID 0xccXX
#define PCIBIOS_PCI_BIOS_PRESENT 0xcc81
#define PCIBIOS_FIND_PCI_DEVICE 0xcc82
#define PCIBIOS_FIND_PCI_CLASS_CODE 0xcc83
/* PCIBIOS_GENERATE_SPECIAL_CYCLE 0xcc86 (not supported by bios) */
#define PCIBIOS_READ_CONFIG_BYTE 0xcc88
#define PCIBIOS_READ_CONFIG_WORD 0xcc89
#define PCIBIOS_READ_CONFIG_DWORD 0xcc8a
#define PCIBIOS_WRITE_CONFIG_BYTE 0xcc8b
#define PCIBIOS_WRITE_CONFIG_WORD 0xcc8c
#define PCIBIOS_WRITE_CONFIG_DWORD 0xcc8d
#define PCIBIOS_GET_ROUTING_OPTIONS 0xcc8e
/* PCI 2.1 only */
#define PCIBIOS_SET_PCI_HW_INT 0xcc8f
/* PCI 2.1 only */
include/asm-i386/mach-pc9800/setup_arch_post.h
deleted
100644 → 0
View file @
bffc8f71
/**
* machine_specific_memory_setup - Hook for machine specific memory setup.
*
* Description:
* This is included late in kernel/setup.c so that it can make
* use of all of the static functions.
**/
static
inline
char
*
__init
machine_specific_memory_setup
(
void
)
{
char
*
who
;
unsigned
long
low_mem_size
,
lower_high
,
higher_high
;
who
=
"BIOS (common area)"
;
low_mem_size
=
((
*
(
unsigned
char
*
)
__va
(
PC9800SCA_BIOS_FLAG
)
&
7
)
+
1
)
<<
17
;
add_memory_region
(
0
,
low_mem_size
,
1
);
lower_high
=
(
__u32
)
*
(
__u8
*
)
bus_to_virt
(
PC9800SCA_EXPMMSZ
)
<<
17
;
higher_high
=
(
__u32
)
*
(
__u16
*
)
bus_to_virt
(
PC9800SCA_MMSZ16M
)
<<
20
;
if
(
lower_high
!=
0x00f00000UL
)
{
add_memory_region
(
HIGH_MEMORY
,
lower_high
,
1
);
add_memory_region
(
0x01000000UL
,
higher_high
,
1
);
}
else
add_memory_region
(
HIGH_MEMORY
,
lower_high
+
higher_high
,
1
);
return
who
;
}
include/asm-i386/mach-pc9800/setup_arch_pre.h
deleted
100644 → 0
View file @
bffc8f71
/* Hook to call BIOS initialisation function */
/* no action for generic */
#define ARCH_SETUP arch_setup_pc9800();
#include <linux/timex.h>
#include <asm/io.h>
#include <asm/pc9800.h>
#include <asm/pc9800_sca.h>
int
CLOCK_TICK_RATE
;
extern
unsigned
long
tick_usec
;
/* ACTHZ period (usec) */
extern
unsigned
long
tick_nsec
;
/* USER_HZ period (nsec) */
unsigned
char
pc9800_misc_flags
;
/* (bit 0) 1:High Address Video ram exists 0:otherwise */
#ifdef CONFIG_SMP
#define MPC_TABLE_SIZE 512
#define MPC_TABLE ((char *) (PARAM+0x400))
char
mpc_table
[
MPC_TABLE_SIZE
];
#endif
static
inline
void
arch_setup_pc9800
(
void
)
{
CLOCK_TICK_RATE
=
PC9800_8MHz_P
()
?
1996800
:
2457600
;
printk
(
KERN_DEBUG
"CLOCK_TICK_RATE = %d
\n
"
,
CLOCK_TICK_RATE
);
tick_usec
=
TICK_USEC
;
/* USER_HZ period (usec) */
tick_nsec
=
TICK_NSEC
;
/* ACTHZ period (nsec) */
pc9800_misc_flags
=
PC9800_MISC_FLAGS
;
#ifdef CONFIG_SMP
if
((
*
(
u32
*
)(
MPC_TABLE
))
==
0x504d4350
)
memcpy
(
mpc_table
,
MPC_TABLE
,
*
(
u16
*
)(
MPC_TABLE
+
4
));
#endif
/* CONFIG_SMP */
}
include/asm-i386/mach-pc9800/smpboot_hooks.h
deleted
100644 → 0
View file @
bffc8f71
/* two abstractions specific to kernel/smpboot.c, mainly to cater to visws
* which needs to alter them. */
static
inline
void
smpboot_clear_io_apic_irqs
(
void
)
{
io_apic_irqs
=
0
;
}
static
inline
void
smpboot_setup_warm_reset_vector
(
unsigned
long
start_eip
)
{
/* reset code is stored in 8255 on PC-9800. */
outb
(
0x0e
,
0x37
);
/* SHUT0 = 0 */
local_flush_tlb
();
Dprintk
(
"1.
\n
"
);
*
((
volatile
unsigned
short
*
)
TRAMPOLINE_HIGH
)
=
start_eip
>>
4
;
Dprintk
(
"2.
\n
"
);
*
((
volatile
unsigned
short
*
)
TRAMPOLINE_LOW
)
=
start_eip
&
0xf
;
Dprintk
(
"3.
\n
"
);
/*
* On PC-9800, continuation on warm reset is done by loading
* %ss:%sp from 0x0000:0404 and executing 'lret', so:
*/
/* 0x3f0 is on unused interrupt vector and should be safe... */
*
((
volatile
unsigned
long
*
)
phys_to_virt
(
0x404
))
=
0x000003f0
;
Dprintk
(
"4.
\n
"
);
}
static
inline
void
smpboot_restore_warm_reset_vector
(
void
)
{
/*
* Install writable page 0 entry to set BIOS data area.
*/
local_flush_tlb
();
/*
* Paranoid: Set warm reset code and vector here back
* to default values.
*/
outb
(
0x0f
,
0x37
);
/* SHUT0 = 1 */
*
((
volatile
long
*
)
phys_to_virt
(
0x404
))
=
0
;
}
static
inline
void
smpboot_setup_io_apic
(
void
)
{
/*
* Here we can be sure that there is an IO-APIC in the system. Let's
* go and set it up:
*/
if
(
!
skip_ioapic_setup
&&
nr_ioapics
)
setup_IO_APIC
();
}
include/asm-i386/pc9800.h
deleted
100644 → 0
View file @
bffc8f71
/*
* PC-9800 machine types.
*
* Copyright (C) 1999 TAKAI Kosuke <tak@kmc.kyoto-u.ac.jp>
* (Linux/98 Project)
*/
#ifndef _ASM_PC9800_H_
#define _ASM_PC9800_H_
#include <asm/pc9800_sca.h>
#include <asm/types.h>
#define __PC9800SCA(type, pa) (*(type *) phys_to_virt(pa))
#define __PC9800SCA_TEST_BIT(pa, n) \
((__PC9800SCA(u8, pa) & (1U << (n))) != 0)
#define PC9800_HIGHRESO_P() __PC9800SCA_TEST_BIT(PC9800SCA_BIOS_FLAG, 3)
#define PC9800_8MHz_P() __PC9800SCA_TEST_BIT(PC9800SCA_BIOS_FLAG, 7)
/* 0x2198 is 98 21 on memory... */
#define PC9800_9821_P() (__PC9800SCA(u16, PC9821SCA_ROM_ID) == 0x2198)
/* Note PC9821_...() are valid only when PC9800_9821_P() was true. */
#define PC9821_IDEIF_DOUBLE_P() __PC9800SCA_TEST_BIT(PC9821SCA_ROM_FLAG4, 4)
#endif
include/asm-i386/pc9800_sca.h
deleted
100644 → 0
View file @
bffc8f71
/*
* System-common area definitions for NEC PC-9800 series
*
* Copyright (C) 1999 TAKAI Kousuke <tak@kmc.kyoto-u.ac.jp>,
* Kyoto University Microcomputer Club.
*/
#ifndef _ASM_I386_PC9800SCA_H_
#define _ASM_I386_PC9800SCA_H_
#define PC9800SCA_EXPMMSZ (0x0401)
/* B */
#define PC9800SCA_SCSI_PARAMS (0x0460)
/* 8 * 4B */
#define PC9800SCA_DISK_EQUIPS (0x0482)
/* B */
#define PC9800SCA_XROM_ID (0x04C0)
/* 52B */
#define PC9800SCA_BIOS_FLAG (0x0501)
/* B */
#define PC9800SCA_MMSZ16M (0x0594)
/* W */
/* PC-9821 have additional system common area in their BIOS-ROM segment. */
#define PC9821SCA__BASE (0xF8E8 << 4)
#define PC9821SCA_ROM_ID (PC9821SCA__BASE + 0x00)
#define PC9821SCA_ROM_FLAG4 (PC9821SCA__BASE + 0x05)
#define PC9821SCA_RSFLAGS (PC9821SCA__BASE + 0x11)
/* B */
#endif
/* !_ASM_I386_PC9800SCA_H_ */
sound/isa/cs423x/pc98.c
deleted
100644 → 0
View file @
bffc8f71
/*
* Driver for CS4232 on NEC PC9800 series
* Copyright (c) by Jaroslav Kysela <perex@suse.cz>
* Osamu Tomita <tomita@cinet.co.jp>
* Takashi Iwai <tiwai@suse.de>
* Hideaki Okubo <okubo@msh.biglobe.ne.jp>
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <sound/driver.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/moduleparam.h>
#include <sound/core.h>
#include <sound/cs4231.h>
#include <sound/mpu401.h>
#include <sound/opl3.h>
#include <sound/initval.h>
#include "sound_pc9800.h"
#define chip_t cs4231_t
MODULE_AUTHOR
(
"Osamu Tomita <tomita@cinet.co.jp>"
);
MODULE_LICENSE
(
"GPL"
);
MODULE_CLASSES
(
"{sound}"
);
MODULE_DESCRIPTION
(
"NEC PC9800 CS4232"
);
MODULE_DEVICES
(
"{{NEC,PC9800}}"
);
#define IDENT "PC98-CS4232"
static
int
index
[
SNDRV_CARDS
]
=
SNDRV_DEFAULT_IDX
;
/* Index 0-MAX */
static
char
*
id
[
SNDRV_CARDS
]
=
SNDRV_DEFAULT_STR
;
/* ID for this card */
static
int
enable
[
SNDRV_CARDS
]
=
SNDRV_DEFAULT_ENABLE_ISAPNP
;
/* Enable this card */
static
long
port
[
SNDRV_CARDS
]
=
SNDRV_DEFAULT_PORT
;
/* PnP setup */
#if 0 /* NOT USED */
static long cport[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */
#endif
static
long
mpu_port
[
SNDRV_CARDS
]
=
SNDRV_DEFAULT_PORT
;
/* PnP setup */
static
long
fm_port
[
SNDRV_CARDS
]
=
SNDRV_DEFAULT_PORT
;
/* PnP setup */
static
int
irq
[
SNDRV_CARDS
]
=
SNDRV_DEFAULT_IRQ
;
/* 5,7,9,11,12,15 */
static
int
mpu_irq
[
SNDRV_CARDS
]
=
SNDRV_DEFAULT_IRQ
;
/* 9,11,12,15 */
static
int
dma1
[
SNDRV_CARDS
]
=
SNDRV_DEFAULT_DMA
;
/* 0,1,3,5,6,7 */
static
int
dma2
[
SNDRV_CARDS
]
=
SNDRV_DEFAULT_DMA
;
/* 0,1,3,5,6,7 */
static
int
pc98ii
[
SNDRV_CARDS
];
/* PC98II */
static
int
boot_devs
;
module_param_array
(
index
,
int
,
boot_devs
,
0444
);
MODULE_PARM_DESC
(
index
,
"Index value for "
IDENT
" soundcard."
);
MODULE_PARM_SYNTAX
(
index
,
SNDRV_INDEX_DESC
);
module_param_array
(
id
,
charp
,
boot_devs
,
0444
);
MODULE_PARM_DESC
(
id
,
"ID string for "
IDENT
" soundcard."
);
MODULE_PARM_SYNTAX
(
id
,
SNDRV_ID_DESC
);
module_param_array
(
enable
,
bool
,
boot_devs
,
0444
);
MODULE_PARM_DESC
(
enable
,
"Enable "
IDENT
" soundcard."
);
MODULE_PARM_SYNTAX
(
enable
,
SNDRV_ENABLE_DESC
);
module_param_array
(
port
,
long
,
boot_devs
,
0444
);
MODULE_PARM_DESC
(
port
,
"Port # for "
IDENT
" driver."
);
MODULE_PARM_SYNTAX
(
port
,
SNDRV_PORT12_DESC
);
#if 0 /* NOT USED */
module_param_array(cport, long, boot_devs, 0444);
MODULE_PARM_DESC(cport, "Control port # for " IDENT " driver.");
MODULE_PARM_SYNTAX(cport, SNDRV_PORT12_DESC);
#endif
module_param_array
(
mpu_port
,
long
,
boot_devs
,
0444
);
MODULE_PARM_DESC
(
mpu_port
,
"MPU-401 port # for "
IDENT
" driver."
);
MODULE_PARM_SYNTAX
(
mpu_port
,
SNDRV_PORT12_DESC
);
module_param_array
(
fm_port
,
long
,
boot_devs
,
0444
);
MODULE_PARM_DESC
(
fm_port
,
"FM port # for "
IDENT
" driver."
);
MODULE_PARM_SYNTAX
(
fm_port
,
SNDRV_PORT12_DESC
);
module_param_array
(
irq
,
int
,
boot_devs
,
0444
);
MODULE_PARM_DESC
(
irq
,
"IRQ # for "
IDENT
" driver."
);
MODULE_PARM_SYNTAX
(
irq
,
SNDRV_IRQ_DESC
);
module_param_array
(
mpu_irq
,
int
,
boot_devs
,
0444
);
MODULE_PARM_DESC
(
mpu_irq
,
"MPU-401 IRQ # for "
IDENT
" driver."
);
MODULE_PARM_SYNTAX
(
mpu_irq
,
SNDRV_IRQ_DESC
);
module_param_array
(
dma1
,
int
,
boot_devs
,
0444
);
MODULE_PARM_DESC
(
dma1
,
"DMA1 # for "
IDENT
" driver."
);
MODULE_PARM_SYNTAX
(
dma1
,
SNDRV_DMA_DESC
);
module_param_array
(
dma2
,
int
,
boot_devs
,
0444
);
MODULE_PARM_DESC
(
dma2
,
"DMA2 # for "
IDENT
" driver."
);
MODULE_PARM_SYNTAX
(
dma2
,
SNDRV_DMA_DESC
);
module_param_array
(
pc98ii
,
bool
,
boot_devs
,
0444
);
MODULE_PARM_DESC
(
pc98ii
,
"Roland MPU-PC98II support."
);
MODULE_PARM_SYNTAX
(
pc98ii
,
SNDRV_BOOLEAN_FALSE_DESC
);
static
snd_card_t
*
snd_pc98_cards
[
SNDRV_CARDS
]
=
SNDRV_DEFAULT_PTR
;
/*
* initialize MPU401-UART
*/
static
int
__init
pc98_mpu401_init
(
int
irq
)
{
#include "pc9801_118_magic.h"
#define outp118(reg,data) outb((reg),0x148e);outb((data),0x148f)
#define WAIT118 outb(0x00,0x5f)
int
mpu_intr
,
count
;
#ifdef OOKUBO_ORIGINAL
int
err
=
0
;
#endif
/* OOKUBO_ORIGINAL */
switch
(
irq
)
{
case
3
:
mpu_intr
=
3
;
break
;
case
5
:
mpu_intr
=
2
;
break
;
case
6
:
mpu_intr
=
1
;
break
;
case
10
:
mpu_intr
=
0
;
break
;
default:
snd_printk
(
KERN_ERR
IDENT
": Bad IRQ %d
\n
"
,
irq
);
return
-
EINVAL
;
}
outp118
(
0x21
,
mpu_intr
);
WAIT118
;
outb
(
0x00
,
0x148e
);
if
(
inb
(
0x148f
)
&
0x08
)
{
snd_printk
(
KERN_INFO
IDENT
": No MIDI daughter board found
\n
"
);
return
0
;
}
outp118
(
0x20
,
0x00
);
outp118
(
0x05
,
0x04
);
for
(
count
=
0
;
count
<
35000
;
count
++
)
WAIT118
;
outb
(
0x05
,
0x148e
);
for
(
count
=
0
;
count
<
65000
;
count
++
)
if
(
inb
(
0x148f
)
==
0x04
)
goto
set_mode_118
;
snd_printk
(
KERN_ERR
IDENT
": MIDI daughter board initialize failed at stage1
\n\n
"
);
return
-
EINVAL
;
set_mode_118:
outp118
(
0x05
,
0x0c
);
outb
(
0xaa
,
0x485
);
outb
(
0x99
,
0x485
);
outb
(
0x2a
,
0x485
);
for
(
count
=
0
;
count
<
sizeof
(
Data0485_99
);
count
++
)
{
outb
(
Data0485_99
[
count
],
0x485
);
WAIT118
;
}
outb
(
0x00
,
0x486
);
outb
(
0xaa
,
0x485
);
outb
(
0x9e
,
0x485
);
outb
(
0x2a
,
0x485
);
for
(
count
=
0
;
count
<
sizeof
(
Data0485_9E
);
count
++
)
if
(
inb
(
0x485
)
!=
Data0485_9E
[
count
])
{
#ifdef OOKUBO_ORIGINAL
err
=
1
;
#endif
/* OOKUBO_ORIGINAL */
break
;
}
outb
(
0x00
,
0x486
);
for
(
count
=
0
;
count
<
2000
;
count
++
)
WAIT118
;
#ifdef OOKUBO_ORIGINAL
if
(
!
err
)
{
outb
(
0xaa
,
0x485
);
outb
(
0x36
,
0x485
);
outb
(
0x28
,
0x485
);
for
(
count
=
0
;
count
<
sizeof
(
Data0485_36
);
count
++
)
outb
(
Data0485_36
[
count
],
0x485
);
outb
(
0x00
,
0x486
);
for
(
count
=
0
;
count
<
1500
;
count
++
)
WAIT118
;
outp118
(
0x05
,
inb
(
0x148f
)
|
0x08
);
outb
(
0xff
,
0x148c
);
outp118
(
0x05
,
inb
(
0x148f
)
&
0xf7
);
for
(
count
=
0
;
count
<
1500
;
count
++
)
WAIT118
;
}
#endif
/* OOKUBO_ORIGINAL */
outb
(
0xaa
,
0x485
);
outb
(
0xa9
,
0x485
);
outb
(
0x21
,
0x485
);
for
(
count
=
0
;
count
<
sizeof
(
Data0485_A9
);
count
++
)
{
outb
(
Data0485_A9
[
count
],
0x485
);
WAIT118
;
}
outb
(
0x00
,
0x486
);
outb
(
0xaa
,
0x485
);
outb
(
0x0c
,
0x485
);
outb
(
0x20
,
0x485
);
for
(
count
=
0
;
count
<
sizeof
(
Data0485_0C
);
count
++
)
{
outb
(
Data0485_0C
[
count
],
0x485
);
WAIT118
;
}
outb
(
0x00
,
0x486
);
outb
(
0xaa
,
0x485
);
outb
(
0x66
,
0x485
);
outb
(
0x20
,
0x485
);
for
(
count
=
0
;
count
<
sizeof
(
Data0485_66
);
count
++
)
{
outb
(
Data0485_66
[
count
],
0x485
);
WAIT118
;
}
outb
(
0x00
,
0x486
);
outb
(
0xaa
,
0x485
);
outb
(
0x60
,
0x485
);
outb
(
0x20
,
0x485
);
for
(
count
=
0
;
count
<
sizeof
(
Data0485_60
);
count
++
)
{
outb
(
Data0485_60
[
count
],
0x485
);
WAIT118
;
}
outb
(
0x00
,
0x486
);
outp118
(
0x05
,
0x04
);
outp118
(
0x05
,
0x00
);
for
(
count
=
0
;
count
<
35000
;
count
++
)
WAIT118
;
outb
(
0x05
,
0x148e
);
for
(
count
=
0
;
count
<
65000
;
count
++
)
if
(
inb
(
0x148f
)
==
0x00
)
goto
end_mode_118
;
snd_printk
(
KERN_ERR
IDENT
": MIDI daughter board initialize failed at stage2
\n
"
);
return
-
EINVAL
;
end_mode_118:
outb
(
0x3f
,
0x148d
);
snd_printk
(
KERN_INFO
IDENT
": MIDI daughter board initialized
\n
"
);
return
0
;
}
static
int
__init
pc98_cs4231_chip_init
(
int
dev
)
{
int
intr_bits
,
intr_bits2
,
dma_bits
;
switch
(
irq
[
dev
])
{
case
3
:
intr_bits
=
0x08
;
intr_bits2
=
0x03
;
break
;
case
5
:
intr_bits
=
0x10
;
intr_bits2
=
0x08
;
break
;
case
10
:
intr_bits
=
0x18
;
intr_bits2
=
0x02
;
break
;
case
12
:
intr_bits
=
0x20
;
intr_bits2
=
0x00
;
break
;
default:
snd_printk
(
KERN_ERR
IDENT
": Bad IRQ %d
\n
"
,
irq
[
dev
]);
return
-
EINVAL
;
}
switch
(
dma1
[
dev
])
{
case
0
:
dma_bits
=
0x01
;
break
;
case
1
:
dma_bits
=
0x02
;
break
;
case
3
:
dma_bits
=
0x03
;
break
;
default:
snd_printk
(
KERN_ERR
IDENT
": Bad DMA %d
\n
"
,
dma1
[
dev
]);
return
-
EINVAL
;
}
if
(
dma2
[
dev
]
>=
2
)
{
snd_printk
(
KERN_ERR
IDENT
": Bad DMA %d
\n
"
,
dma2
[
dev
]);
return
-
EINVAL
;
}
outb
(
dma1
[
dev
],
0x29
);
/* dma1 boundary 64KB */
if
(
dma1
[
dev
]
!=
dma2
[
dev
]
&&
dma2
[
dev
]
>=
0
)
{
outb
(
0
,
0x5f
);
/* wait */
outb
(
dma2
[
dev
],
0x29
);
/* dma2 boundary 64KB */
intr_bits
|=
0x04
;
}
if
(
PC9800_SOUND_ID
()
==
PC9800_SOUND_ID_118
)
{
/* Set up CanBe control registers. */
snd_printd
(
KERN_INFO
"Setting up CanBe Sound System
\n
"
);
outb
(
inb
(
PC9800_SOUND_IO_ID
)
|
0x03
,
PC9800_SOUND_IO_ID
);
outb
(
0x01
,
0x0f4a
);
outb
(
intr_bits2
,
0x0f4b
);
}
outb
(
intr_bits
|
dma_bits
,
0xf40
);
return
0
;
}
static
int
__init
snd_card_pc98_probe
(
int
dev
)
{
snd_card_t
*
card
;
snd_pcm_t
*
pcm
=
NULL
;
cs4231_t
*
chip
;
opl3_t
*
opl3
;
int
err
;
if
(
port
[
dev
]
==
SNDRV_AUTO_PORT
)
{
snd_printk
(
KERN_ERR
IDENT
": specify port
\n
"
);
return
-
EINVAL
;
}
card
=
snd_card_new
(
index
[
dev
],
id
[
dev
],
THIS_MODULE
,
0
);
if
(
card
==
NULL
)
return
-
ENOMEM
;
if
((
err
=
pc98_cs4231_chip_init
(
dev
))
<
0
)
{
snd_card_free
(
card
);
return
err
;
}
if
((
err
=
snd_cs4231_create
(
card
,
port
[
dev
],
-
1
,
irq
[
dev
],
dma1
[
dev
],
dma2
[
dev
],
CS4231_HW_DETECT
,
0
,
&
chip
))
<
0
)
{
snd_card_free
(
card
);
return
err
;
}
if
((
err
=
snd_cs4231_pcm
(
chip
,
0
,
&
pcm
))
<
0
)
{
snd_card_free
(
card
);
return
err
;
}
if
((
err
=
snd_cs4231_mixer
(
chip
))
<
0
)
{
snd_card_free
(
card
);
return
err
;
}
if
((
err
=
snd_cs4231_timer
(
chip
,
0
,
NULL
))
<
0
)
{
snd_card_free
(
card
);
return
err
;
}
if
(
fm_port
[
dev
]
>
0
&&
fm_port
[
dev
]
!=
SNDRV_AUTO_PORT
)
{
/* ??? */
outb
(
0x00
,
fm_port
[
dev
]
+
6
);
inb
(
fm_port
[
dev
]
+
7
);
/* Enable OPL-3 Function */
outb
(
inb
(
PC9800_SOUND_IO_ID
)
|
0x03
,
PC9800_SOUND_IO_ID
);
if
(
snd_opl3_create
(
card
,
fm_port
[
dev
],
fm_port
[
dev
]
+
2
,
OPL3_HW_OPL3_PC98
,
0
,
&
opl3
)
<
0
)
{
printk
(
KERN_ERR
IDENT
": OPL3 not detected
\n
"
);
}
else
{
if
((
err
=
snd_opl3_hwdep_new
(
opl3
,
0
,
1
,
NULL
))
<
0
)
{
snd_card_free
(
card
);
return
err
;
}
}
}
if
(
mpu_port
[
dev
]
>
0
&&
mpu_port
[
dev
]
!=
SNDRV_AUTO_PORT
)
{
err
=
pc98_mpu401_init
(
mpu_irq
[
dev
]);
if
(
!
err
)
{
err
=
snd_mpu401_uart_new
(
card
,
0
,
pc98ii
[
dev
]
?
MPU401_HW_PC98II
:
MPU401_HW_MPU401
,
mpu_port
[
dev
],
0
,
mpu_irq
[
dev
],
SA_INTERRUPT
,
NULL
);
if
(
err
<
0
)
snd_printk
(
KERN_INFO
IDENT
": MPU401 not detected
\n
"
);
}
}
strcpy
(
card
->
driver
,
pcm
->
name
);
strcpy
(
card
->
shortname
,
pcm
->
name
);
sprintf
(
card
->
longname
,
"%s at 0x%lx, irq %i, dma %i"
,
pcm
->
name
,
chip
->
port
,
irq
[
dev
],
dma1
[
dev
]);
if
(
dma2
[
dev
]
>=
0
)
sprintf
(
card
->
longname
+
strlen
(
card
->
longname
),
"&%d"
,
dma2
[
dev
]);
if
((
err
=
snd_card_register
(
card
))
<
0
)
{
snd_card_free
(
card
);
return
err
;
}
snd_pc98_cards
[
dev
]
=
card
;
return
0
;
}
static
int
__init
alsa_card_pc98_init
(
void
)
{
int
dev
,
cards
=
0
;
for
(
dev
=
0
;
dev
<
SNDRV_CARDS
;
dev
++
)
{
if
(
!
enable
[
dev
])
continue
;
if
(
snd_card_pc98_probe
(
dev
)
>=
0
)
cards
++
;
}
if
(
!
cards
)
{
#ifdef MODULE
printk
(
KERN_ERR
IDENT
" soundcard not found or device busy
\n
"
);
#endif
return
-
ENODEV
;
}
return
0
;
}
static
void
__exit
alsa_card_pc98_exit
(
void
)
{
int
idx
;
for
(
idx
=
0
;
idx
<
SNDRV_CARDS
;
idx
++
)
snd_card_free
(
snd_pc98_cards
[
idx
]);
}
module_init
(
alsa_card_pc98_init
)
module_exit
(
alsa_card_pc98_exit
)
sound/isa/cs423x/pc9801_118_magic.h
deleted
100644 → 0
View file @
bffc8f71
static
unsigned
char
Data0485_A9
[]
=
{
0x12
,
0x03
,
0x90
,
0xc2
,
0x2a
,
0x75
,
0x1e
,
0x20
,
0xe4
,
0x12
,
0x2b
,
0x9b
,
0x22
,
0xa9
,
0x16
,
0x77
,
0x33
,
0xe9
,
0x04
,
0x54
,
0x03
,
0x44
,
0xa8
,
0xf5
,
0x16
,
0xc2
,
0x2f
,
0x22
,
0xa9
,
0x16
,
0x77
,
0x42
,
0xe9
,
0x04
,
0x54
,
0x03
,
0x44
,
0xa8
,
0xf9
,
0x77
,
0xf8
,
0x04
,
0x54
,
0x03
,
0x44
,
0xa8
,
0xf5
,
0x16
,
0xc2
,
0x2f
,
0x22
,
0x90
,
0x25
,
0x9f
,
0x30
,
0x04
,
0x05
,
0xc2
,
0x04
,
0x12
,
0x1f
,
0x62
,
0x30
,
0x00
,
0x05
,
0xc2
,
0x00
,
0x12
,
0x15
,
0xe6
,
0x30
,
0x01
,
0x05
,
0xc2
,
0x01
,
0x12
,
0x29
,
0xaf
,
0x30
,
0x02
,
0x05
,
0xc2
,
0x02
,
0x12
,
0x29
,
0xaf
,
0x30
,
0x05
,
0x05
,
0xc2
,
0x05
,
0x12
,
0x16
,
0x65
,
0x30
,
0x06
,
0x08
,
0xc2
,
0x06
,
0x12
,
0x16
,
0xb1
,
0x12
,
0x29
,
0xaf
,
0x30
,
0x07
,
0x08
,
0xc2
,
0x07
,
0x12
,
0x16
,
0xe9
,
0x12
,
0x29
,
0xaf
,
0x22
,
0x20
,
0x97
,
0x09
,
0x53
,
0xa8
,
0xfb
,
0x12
,
0x04
,
0x2c
,
0x43
,
0xa8
,
0x04
,
0x22
,
0x71
,
0xb8
,
0x71
,
0xb8
,
0x71
,
0xb8
,
0x22
,
0x20
,
0x4b
,
0x04
,
0x75
,
0x4e
,
0x02
,
0x22
,
0xe5
,
0x35
,
0x24
,
0xff
,
0xf5
,
0x35
,
0xe5
,
0x36
,
0x34
,
0xff
,
0xf5
,
0x36
,
0x75
,
0x4e
,
0x02
,
0x22
,
0x10
,
0x19
,
0x02
,
0x80
,
0x08
,
0x78
,
0x00
,
0xe2
,
0x78
,
0x07
,
0xf2
,
0x61
,
0x9b
,
0x78
,
0x11
,
0xe2
,
0xc0
,
0x01
,
0xc0
,
0xf0
,
0xc0
,
0xd0
,
0xc0
,
0x02
,
0x71
,
0x14
,
0xe5
,
0x30
,
0xb4
,
0x01
,
0x02
,
0x61
,
0x93
,
0x43
,
0x08
,
0x40
,
0x12
,
0x2a
,
0x53
,
0x61
,
0x93
,
0x79
,
0x03
,
0xe3
,
0xa2
,
0xe2
,
0x92
,
0x26
,
0xa2
,
0xe3
,
0x92
,
0x27
,
0x22
,
0xad
,
0x2b
,
0xbd
,
0x04
,
0x07
,
0xf5
,
0x72
,
0x78
,
0x27
,
0x02
,
0x11
,
0x76
,
0x02
,
0x11
,
0x30
,
0x00
,
0x00
,
0x00
,
0x12
,
0x28
,
0xba
,
0x79
,
0x01
,
0xe3
,
0x75
,
0x21
,
0x3f
,
0x75
,
0x49
,
0x11
,
0x75
,
0x4c
,
0x11
,
0x31
,
0xdc
,
0x75
,
0x1a
,
0x80
,
0x51
,
0x72
,
0x75
,
0x81
,
0xe3
,
0x12
,
0x25
,
0xc9
,
0x43
,
0xa8
,
0x01
,
0x00
,
0x53
,
0xa8
,
0xfe
,
0x10
,
0x50
,
0x02
,
0x80
,
0x03
,
0x12
,
0x1a
,
0x8d
,
0xd1
,
0x28
,
0x12
,
0x03
,
0xd9
,
0xd1
,
0xf2
,
0x12
,
0x2d
,
0xf0
,
0xb0
,
0x11
,
0x92
,
0xe0
,
0xa2
,
0x2a
,
0xa0
,
0xb5
,
0x82
,
0xe0
,
0x50
,
0x03
,
0x79
,
0x0f
,
0xe3
,
0x71
,
0xca
,
0x51
,
0x1e
,
0x91
,
0xe4
,
0x53
,
0xa8
,
0xfb
,
0x10
,
0x10
,
0x02
,
0x80
,
0x26
,
0xc2
,
0x8e
,
0xd2
,
0xab
,
0xa2
,
0x1c
,
0x40
,
0x13
,
0xa2
,
0x1d
,
0x50
,
0x0a
,
0x43
,
0x08
,
0x40
,
0x12
,
0x1a
,
0x01
,
0xd1
,
0xd7
,
0x80
,
0x0b
,
0x12
,
0x26
,
0x04
,
0x61
,
0x08
,
0x43
,
0x08
,
0x40
,
0x12
,
0x1a
,
0x01
,
0xd2
,
0x1f
,
0x12
,
0x17
,
0x7f
,
0x43
,
0xa8
,
0x04
,
0x51
,
0x1e
,
0x91
,
0xe4
,
0x12
,
0x13
,
0x34
,
0x80
,
0x98
,
0xa2
,
0x17
,
0x72
,
0x16
,
0x72
,
0x15
,
0x72
,
0x2d
,
0x50
,
0x06
,
0xfa
,
0x12
,
0x13
,
0x66
,
0x80
,
0x25
,
0xc2
,
0x13
,
0x30
,
0x28
,
0x05
,
0x12
,
0x02
,
0xbe
,
0x80
,
0x1b
,
0xb4
,
0x10
,
0x12
,
0x78
,
0x00
,
0xf2
,
0xe5
,
0x30
,
0xb4
,
0x01
,
0x06
,
0x12
,
0x03
,
0x90
,
0xd2
,
0x19
,
0x22
,
0x12
,
0x00
,
0xdd
,
0x22
,
0x75
,
0x30
,
0x00
,
0x12
,
0x00
,
0xa1
,
0x22
,
0x00
,
0x00
,
0x75
,
0x1e
,
0x00
,
0x74
,
0x0c
,
0x12
,
0x2b
,
0x9b
,
0x74
,
0x40
,
0x79
,
0x05
,
0xf3
,
0x74
,
0x49
,
0x12
,
0x2b
,
0x9b
,
0x74
,
0x04
,
0x79
,
0x05
,
0xf3
,
0x75
,
0x15
,
0x04
,
0x74
,
0x10
,
0x12
,
0x2b
,
0x9b
,
0x74
,
0x00
,
0x79
,
0x05
,
0xf3
,
0x74
,
0x17
,
0x12
,
0x2b
,
0x9b
,
0x74
,
0x00
,
0x79
,
0x05
,
0xf3
,
0x74
,
0x1a
,
0x12
,
0x2b
,
0x9b
,
0x74
,
0x00
,
0x79
,
0x05
,
0xf3
,
0x74
,
0x0a
,
0x12
,
0x2b
,
0x9b
,
0x74
,
0x20
,
0x79
,
0x05
,
0xf3
,
0x79
,
0xe0
,
0x77
,
0x20
,
0x22
,
0xd0
,
0x02
,
0xd0
,
0xd0
,
0xd0
,
0xf0
,
0xd0
,
0x01
,
0xe5
,
0x5f
,
0xd0
,
0xa8
,
0x22
,
0x00
,
0x00
,
0x90
,
0x25
,
0x9f
,
0x75
,
0x26
,
0xff
,
0x75
,
0x27
,
0xff
,
0x75
,
0x28
,
0x03
,
0x75
,
0x13
,
0xff
,
0x75
,
0x1f
,
0x00
,
0x75
,
0x14
,
0xff
,
0x22
,
0x79
,
0x06
,
0xe5
,
0x29
,
0x60
,
0x0b
,
0xe3
,
0x30
,
0xe1
,
0xf8
,
0xe5
,
0x4f
,
0x64
,
0x80
,
0x79
,
0x07
,
0xf3
,
0x22
,
0x10
,
0x4c
,
0x01
,
0x22
,
0x30
,
0x4b
,
0x0a
,
0xc2
,
0x4b
,
0xe5
,
0x4d
,
0x64
,
0x80
,
0xf5
,
0x4f
,
0x80
,
0x1d
,
0xe5
,
0x15
,
0xa2
,
0xe0
,
0x82
,
0xe6
,
0x40
,
0x02
,
0x80
,
0x35
,
0x30
,
0x4a
,
0x04
,
0xb1
,
0xe6
,
0x80
,
0x0c
,
0x30
,
0x49
,
0x04
,
0x51
,
0x2b
,
0x80
,
0x05
,
0x30
,
0x48
,
0x24
,
0x91
,
0x7e
,
0x79
,
0x06
,
0xe3
,
0x30
,
0xe0
,
0x1a
,
0x79
,
0x06
,
0xf3
,
0xe5
,
0x4e
,
0x24
,
0xff
,
0x50
,
0x04
,
0xf5
,
0x4e
,
0x80
,
0x0d
,
0x79
,
0x0f
,
0xf3
,
0x20
,
0x2a
,
0x07
,
0x12
,
0x2b
,
0x32
,
0x75
,
0x29
,
0x00
,
0x22
,
0x91
,
0x1b
,
0x22
,
0x79
,
0x0f
,
0xe3
,
0xc0
,
0xa8
,
0x75
,
0xa8
,
0x00
,
0x30
,
0x2b
,
0x03
,
0xd0
,
0xa8
,
0x22
,
0x79
,
0x0e
,
0xf3
,
0xd0
,
0xa8
,
0x22
,
0x8a
,
0xf0
,
0xe5
,
0x50
,
0x10
,
0xf3
,
0x10
,
0x23
,
0x23
,
0x23
,
0x25
,
0xf0
,
0x12
,
0x2c
,
0xb8
,
0xa2
,
0xe7
,
0x92
,
0xe4
,
0xc2
,
0xe7
,
0x80
,
0x08
,
0x23
,
0x23
,
0x23
,
0x25
,
0xf0
,
0x12
,
0x2c
,
0x19
,
0x25
,
0x4f
,
0x20
,
0xd2
,
0x04
,
0xf5
,
0x4f
,
0x80
,
0x0a
,
0x40
,
0x05
,
0x75
,
0x4f
,
0x7f
,
0x80
,
0x03
,
0x75
,
0x4f
,
0xff
,
0xea
,
0x12
,
0x2c
,
0x3c
,
0x25
,
0x50
,
0x20
,
0xe7
,
0x05
,
0xb4
,
0x03
,
0x07
,
0x80
,
0x0c
,
0x75
,
0x50
,
0x00
,
0x80
,
0x09
,
0x40
,
0x05
,
0x75
,
0x50
,
0x03
,
0x80
,
0x02
,
0xf5
,
0x50
,
0x22
,
0xe5
,
0x4d
,
0xc4
,
0x54
,
0x0c
,
0x03
,
0x03
,
0xfa
,
0x91
,
0xa9
,
0x71
,
0xb8
,
0xe5
,
0x4d
,
0xc4
,
0x54
,
0x03
,
0xfa
,
0x91
,
0xa9
,
0x71
,
0xb8
,
0xe5
,
0x4d
,
0x54
,
0x0c
,
0x03
,
0x03
,
0xfa
,
0x91
,
0xa9
,
0x71
,
0xb8
,
0xe5
,
0x4d
,
0x54
,
0x03
,
0xfa
,
0x91
,
0xa9
,
0x71
,
0xb8
,
0x22
,
0x8a
,
0xf0
,
0xe5
,
0x50
,
0x23
,
0x23
,
0x25
,
0xf0
,
0x12
,
0x2b
,
0xf6
,
0x25
,
0x4f
,
0x20
,
0xd2
,
0x04
,
0xf5
,
0x4f
,
0x80
,
0x0a
,
0x40
,
0x05
,
0x75
,
0x4f
,
0x7f
,
0x80
,
0x03
,
0x75
,
0x4f
,
0xff
,
0xea
,
0x12
,
0x2c
,
0x40
,
0x25
,
0x50
,
0x20
,
0xe7
,
0x05
,
0xb4
,
0x05
,
0x07
,
0x80
,
0x0c
,
0x75
,
0x50
,
0x00
,
0x80
,
0x09
,
0x40
,
0x05
,
0x75
,
0x50
,
0x05
,
0x80
,
0x02
,
0xf5
,
0x50
,
0x22
,
0x30
,
0x26
,
0x03
,
0x12
,
0x1e
,
0xf5
,
0x30
,
0x27
,
0x03
,
0x12
,
0x1f
,
0x37
,
0x30
,
0x25
,
0x09
,
0x12
,
0x1f
,
0x4e
,
0x30
,
0x23
,
0x03
,
0x12
,
0x1f
,
0x1e
,
0x10
,
0x22
,
0x02
,
0x80
,
0x0a
,
0xe5
,
0x3b
,
0xb4
,
0xff
,
0x02
,
0xc2
,
0x20
,
0x12
,
0x1e
,
0x79
,
0x22
,
0x78
,
0x11
,
0xe2
,
0x20
,
0xe0
,
0x07
,
0xc0
,
0x01
,
0x12
,
0x28
,
0xba
,
0xd0
,
0x01
,
0x78
,
0x00
,
0xf2
,
0x61
,
0x9b
,
0x12
,
0x2b
,
0x32
,
0x12
,
0x17
,
0x7f
,
0x78
,
0x00
,
0xf2
,
0xaa
,
0x35
,
0xab
,
0x36
,
0xea
,
0x24
,
0xff
,
0xfa
,
0xeb
,
0x34
,
0xff
,
0xfb
,
0x50
,
0x03
,
0xd2
,
0x10
,
0x22
,
0x75
,
0x37
,
0x01
,
0x75
,
0x38
,
0x00
,
0x75
,
0x39
,
0x00
,
0x12
,
0x04
,
0x04
,
0xd2
,
0x8e
,
0x22
,
0xa8
,
0x2b
,
0xb8
,
0x00
,
0x02
,
0x80
,
0x03
,
0x02
,
0x11
,
0xbd
,
0xf5
,
0x74
,
0x78
,
0x2a
,
0x12
,
0x11
,
0xec
,
0xe5
,
0x74
,
0x78
,
0x29
,
0x12
,
0x11
,
0xec
,
0x22
,
0xfa
,
0xe5
,
0x2b
,
0x60
,
0x01
,
0x22
,
0xea
,
0x78
,
0x2b
,
0xf5
,
0x75
,
0x12
,
0x11
,
0xec
,
0x22
,
0x74
,
0x10
,
0x12
,
0x2b
,
0x9b
,
0x74
,
0x20
,
0x78
,
0x05
,
0xf2
,
0x74
,
0x09
,
0x12
,
0x17
,
0x75
,
0xe5
,
0x15
,
0x44
,
0x80
,
0x79
,
0x05
,
0xf3
,
0xf5
,
0x15
,
0x12
,
0x17
,
0x7f
,
0x22
,
0x12
,
0x03
,
0x84
,
0x79
,
0x0f
,
0xe3
,
0x78
,
0x00
,
0xf2
,
0x12
,
0x2b
,
0x28
,
0xe5
,
0x81
,
0x24
,
0xfc
,
0xf5
,
0x81
,
0x61
,
0x93
,
0xd2
,
0x07
,
0x78
,
0x11
,
0xe2
,
0x44
,
0x11
,
0xf5
,
0x4c
,
0xc2
,
0x0f
,
0x12
,
0x29
,
0xa3
,
0x61
,
0x93
,
0x02
,
0x1b
,
0x77
,
0x00
,
0xe1
,
0x81
,
0xe1
,
0x9a
,
0xd2
,
0x2c
,
0xa1
,
0x0c
,
0x20
,
0x20
,
0x02
,
0xd2
,
0x26
,
0x02
,
0x1e
,
0x35
,
0x02
,
0x1e
,
0x61
,
0x02
,
0x1d
,
0x8f
,
0xc2
,
0x8e
,
0x75
,
0xa8
,
0x9e
,
0x22
,
0x41
,
0x49
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x02
,
0x29
,
0x91
,
0x00
,
0x00
,
0x00
,
0xa1
,
0xbb
,
0xa1
,
0xc3
,
0x02
,
0x1e
,
0x6b
,
0xe5
,
0x4d
,
0xc4
,
0x54
,
0x0f
,
0xfa
,
0x91
,
0x2f
,
0x71
,
0xb8
,
0xe5
,
0x4d
,
0x54
,
0x0f
,
0xfa
,
0x91
,
0x2f
,
0x71
,
0xb8
,
0x22
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0xa1
,
0xc6
,
0x02
,
0x1d
,
0x8f
,
0xc2
,
0x8e
,
0xd2
,
0xab
,
0xc2
,
0x10
,
0x79
,
0x0f
,
0xf3
,
0x22
,
0x00
,
0x02
,
0x2a
,
0x84
,
0x00
,
0xe1
,
0xbc
,
0xe1
,
0xc8
,
0x02
,
0x1e
,
0x27
,
0x00
,
0x78
,
0x00
,
0xf2
,
0x78
,
0x0b
,
0xe2
,
0xf4
,
0xf5
,
0x4d
,
0xd2
,
0x4c
,
0x61
,
0x9b
,
0x30
,
0xb5
,
0x02
,
0xc2
,
0x11
,
0x22
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x79
,
0xbd
,
0xf1
,
0x3d
,
0x83
,
0x22
,
0xdd
,
0xbd
,
0xbd
,
0xbd
,
0x61
,
0xbd
,
0x8d
,
0x7a
,
0xbd
,
0xbd
,
0xbd
,
0xbd
,
0x30
,
0xbd
,
0xbd
,
0xbd
,
0x55
,
0xbd
,
0xbd
,
0xbd
,
0x52
,
0xbd
,
0xb6
,
0xb6
,
0xbd
,
0xbd
,
0xbd
,
0xbd
,
0x00
,
0xbd
,
0xbd
,
0xbd
,
0xe8
,
0xda
,
0xbd
,
0xbd
,
0xcf
,
0xb9
,
0xbd
,
0xc4
,
0xf1
,
0xbd
,
0xbd
,
0xbd
,
0xbd
,
0xbd
,
0xbd
,
0xbd
,
0x7b
,
0xbd
,
0xbd
,
0xbd
,
0xbd
,
0xbd
,
0xbd
,
0xbd
,
0x70
,
0x6a
,
0x57
,
0x47
,
0x34
,
0xbd
,
0xbd
,
0xbd
,
0xbd
,
0xbd
,
0xbd
,
0xbd
,
0xbd
,
0x29
,
0xbd
,
0xbd
,
0xbd
,
0xb6
,
0xb6
,
0xbd
,
0xbd
,
0xbd
,
0xbd
,
0xbd
,
0xbd
,
0xbd
,
0xbd
,
0xbd
,
0xbd
,
0x2e
,
0x25
,
0xbd
,
0xbd
,
0xbd
,
0xbd
,
0xbd
,
0xbd
,
0xfe
,
0xf5
,
0xbd
,
0xbd
,
0xbd
,
0xbd
,
0xbd
,
0xbd
,
0x19
,
0xbd
,
0xbd
,
0xbd
,
0xbd
,
0xbd
,
0xbd
,
0xbd
,
0x21
,
0x8f
,
0x09
,
0xbd
,
0xf9
,
0x86
,
0xbd
,
0xbd
,
0xbd
,
0xd7
,
0xbd
,
0xa9
,
0xbd
,
0xbd
,
0xbd
,
0xbd
,
0xbd
,
0x9b
,
0xd1
,
0x9d
,
0xbd
,
0xae
,
0xbd
,
0xbd
,
0xbd
,
0xcb
,
0xbd
,
0xbd
,
0xbd
,
0xbd
,
0xbd
,
0xbd
,
0xbd
,
0xbd
,
0xb6
,
0xa5
,
0xbd
,
0xc5
,
0xbd
,
0xbd
,
0xbd
,
0xc3
,
0xbd
,
0xbd
,
0xbd
,
0xbd
,
0xbd
,
0xbd
,
0x74
,
0x10
,
0x12
,
0x2b
,
0x9b
,
0xe4
,
0x78
,
0x05
,
0xf2
,
0x74
,
0x09
,
0x12
,
0x17
,
0x75
,
0xe5
,
0x15
,
0x54
,
0x7f
,
0x79
,
0x05
,
0xf3
,
0xf5
,
0x15
,
0x12
,
0x17
,
0x7f
,
0x22
,
0x30
,
0x51
,
0x01
,
0x22
,
0x53
,
0xa8
,
0xfb
,
0x12
,
0x2d
,
0xf0
,
0x50
,
0x22
,
0x79
,
0x03
,
0xe3
,
0x20
,
0xe4
,
0x1c
,
0xaa
,
0x35
,
0xab
,
0x36
,
0xea
,
0x24
,
0xf0
,
0xfa
,
0xeb
,
0x34
,
0xff
,
0xfb
,
0x50
,
0x0e
,
0x10
,
0x1f
,
0x02
,
0x80
,
0x09
,
0x20
,
0x2a
,
0x03
,
0x12
,
0x2b
,
0x32
,
0x12
,
0x2d
,
0xd6
,
0x43
,
0xa8
,
0x04
,
0x22
,
0xa2
,
0x1c
,
0x72
,
0x1d
,
0x40
,
0x07
,
0x53
,
0x08
,
0xbf
,
0x78
,
0x00
,
0xf2
,
0x22
,
0xb1
,
0x1e
,
0x22
,
0x00
,
0x79
,
0x02
,
0x12
,
0x27
,
0x3d
,
0x02
,
0x2d
,
0x37
,
0x14
,
0x54
,
0xf0
,
0x60
,
0x21
,
0xe5
,
0xf0
,
0x24
,
0xb6
,
0xe5
,
0xf0
,
0x50
,
0x16
,
0x24
,
0x8b
,
0x50
,
0x15
,
0xe5
,
0xf0
,
0x24
,
0x56
,
0xe5
,
0xf0
,
0x50
,
0x08
,
0x24
,
0x2f
,
0x50
,
0x09
,
0xe5
,
0xf0
,
0x24
,
0xd9
,
0x24
,
0xd5
,
0x24
,
0xf0
,
0x22
,
0x15
,
0x81
,
0x15
,
0x81
,
0xe9
,
0x22
,
0x78
,
0x13
,
0x74
,
0x00
,
0xf2
,
0x75
,
0x2e
,
0x01
,
0xd2
,
0x6a
,
0xc2
,
0x69
,
0xc2
,
0x68
,
0xc2
,
0x6c
,
0x90
,
0x25
,
0x9f
,
0x75
,
0xb8
,
0x07
,
0x41
,
0xa4
,
0xc0
,
0x01
,
0xc0
,
0xf0
,
0xc0
,
0xd0
,
0xc0
,
0x02
,
0xe5
,
0x3d
,
0x54
,
0x7d
,
0x03
,
0x10
,
0xe5
,
0x05
,
0x90
,
0x28
,
0x4b
,
0x80
,
0x03
,
0x90
,
0x2b
,
0x7c
,
0x73
,
0xe5
,
0x3d
,
0x30
,
0xe5
,
0x07
,
0x74
,
0xfd
,
0x78
,
0x00
,
0xf2
,
0x61
,
0x9b
,
0x90
,
0x1a
,
0x97
,
0x74
,
0xb6
,
0xc0
,
0xe0
,
0x74
,
0x27
,
0xc0
,
0xe0
,
0xc0
,
0xa8
,
0x02
,
0x1b
,
0xab
,
0x90
,
0x25
,
0x9f
,
0xd0
,
0xa8
,
0x22
,
0x90
,
0x27
,
0xb6
,
0xc0
,
0x82
,
0xc0
,
0x83
,
0xc0
,
0xa8
,
0x02
,
0x1d
,
0xa6
,
0x90
,
0x27
,
0xb6
,
0xc0
,
0x82
,
0xc0
,
0x83
,
0xc0
,
0xa8
,
0x02
,
0x1e
,
0x0a
,
0xea
,
0x24
,
0xf0
,
0xfa
,
0xeb
,
0x34
,
0xff
,
0xfb
,
0x50
,
0x2e
,
0x20
,
0x0b
,
0x05
,
0x85
,
0x44
,
0xe0
,
0x80
,
0x03
,
0x75
,
0xe0
,
0x00
,
0x30
,
0xe1
,
0x20
,
0xe5
,
0x35
,
0x24
,
0xff
,
0xf5
,
0x35
,
0xe5
,
0x36
,
0x34
,
0xff
,
0xf5
,
0x36
,
0xc3
,
0xe5
,
0x36
,
0x13
,
0xf5
,
0x36
,
0xe5
,
0x35
,
0x13
,
0xf5
,
0x35
,
0x75
,
0x3a
,
0x10
,
0x12
,
0x1a
,
0x77
,
0x02
,
0x18
,
0x77
,
0x75
,
0x3a
,
0x00
,
0x12
,
0x1a
,
0x77
,
0x02
,
0x18
,
0x1b
,
0x20
,
0x4b
,
0x04
,
0x75
,
0x4e
,
0x03
,
0x22
,
0xe5
,
0x35
,
0x24
,
0xff
,
0xf5
,
0x35
,
0xe5
,
0x36
,
0x34
,
0xff
,
0xf5
,
0x36
,
0x75
,
0x4e
,
0x03
,
0x22
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x22
,
0x02
,
0x2c
,
0x70
,
0xd2
,
0x00
,
0x78
,
0x11
,
0xe2
,
0x44
,
0x11
,
0xf5
,
0x3f
,
0xc2
,
0x08
,
0x12
,
0x29
,
0xa3
,
0x02
,
0x23
,
0x93
,
0x21
,
0x62
,
0x61
,
0x40
,
0x01
,
0x3a
,
0x01
,
0x73
,
0x21
,
0x76
,
0x61
,
0xa8
,
0x21
,
0x39
,
0x21
,
0x4a
,
0x02
,
0x2a
,
0x7b
,
0x79
,
0x06
,
0xf3
,
0xc0
,
0xd0
,
0x12
,
0x03
,
0xd9
,
0x78
,
0x00
,
0xf2
,
0xd0
,
0xd0
,
0x22
,
0x00
,
0x00
,
0x00
,
0x00
,
0x02
,
0x2c
,
0xb4
,
0x78
,
0x11
,
0xe2
,
0x44
,
0x11
,
0x54
,
0x0f
,
0xf8
,
0xc4
,
0x48
,
0xd2
,
0x05
,
0xf5
,
0x48
,
0xc2
,
0x0d
,
0x31
,
0xa3
,
0x02
,
0x23
,
0x93
,
0x20
,
0x4b
,
0x04
,
0x75
,
0x4e
,
0x01
,
0x22
,
0xe5
,
0x35
,
0x24
,
0xff
,
0xf5
,
0x35
,
0xe5
,
0x36
,
0x34
,
0xff
,
0xf5
,
0x36
,
0x75
,
0x4e
,
0x01
,
0x22
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x79
,
0xd0
,
0x77
,
0x1b
,
0x79
,
0xd1
,
0x77
,
0x18
,
0x79
,
0xd2
,
0x77
,
0x77
,
0x79
,
0xd3
,
0x77
,
0x18
,
0x22
,
0x75
,
0x29
,
0x00
,
0x75
,
0x25
,
0x00
,
0x75
,
0x34
,
0x03
,
0x75
,
0x22
,
0x00
,
0x75
,
0x23
,
0x05
,
0x75
,
0x4f
,
0x00
,
0x75
,
0x50
,
0x00
,
0x75
,
0x30
,
0x00
,
0x79
,
0xdc
,
0x77
,
0x03
,
0xc2
,
0x8e
,
0x75
,
0x17
,
0xa8
,
0x75
,
0x16
,
0xa8
,
0x74
,
0xaa
,
0x79
,
0x01
,
0xf3
,
0x79
,
0xd7
,
0x77
,
0x74
,
0x79
,
0xd8
,
0x77
,
0xff
,
0x79
,
0xd9
,
0x77
,
0x07
,
0x79
,
0xda
,
0x77
,
0x00
,
0x12
,
0x25
,
0x6f
,
0x43
,
0x08
,
0x40
,
0x71
,
0x32
,
0x79
,
0x0e
,
0xe3
,
0x10
,
0x51
,
0x1c
,
0x74
,
0x06
,
0x71
,
0x9b
,
0xe5
,
0x11
,
0x44
,
0x80
,
0x79
,
0x05
,
0xf3
,
0xf5
,
0x11
,
0x74
,
0x07
,
0x71
,
0x9b
,
0xe5
,
0x12
,
0x44
,
0x80
,
0x79
,
0x05
,
0xf3
,
0xf5
,
0x12
,
0x80
,
0x18
,
0x53
,
0x27
,
0xa0
,
0x53
,
0x28
,
0x01
,
0x75
,
0x20
,
0xf7
,
0x12
,
0x23
,
0x4c
,
0x75
,
0x11
,
0x80
,
0x75
,
0x12
,
0x80
,
0x12
,
0x1f
,
0xc0
,
0x12
,
0x21
,
0xdc
,
0x79
,
0x06
,
0xf3
,
0x22
,
0xd2
,
0x02
,
0x78
,
0x11
,
0xe2
,
0x44
,
0x11
,
0xf5
,
0x43
,
0xc2
,
0x0a
,
0x12
,
0x29
,
0xa3
,
0x02
,
0x23
,
0x93
,
0x78
,
0x11
,
0xe2
,
0x44
,
0x11
,
0xf5
,
0x44
,
0xc2
,
0x0b
,
0x12
,
0x29
,
0xa3
,
0x02
,
0x23
,
0x93
,
0x78
,
0x00
,
0xe2
,
0x90
,
0x25
,
0x9f
,
0x02
,
0x23
,
0x93
,
0x78
,
0x11
,
0xe2
,
0x75
,
0x20
,
0xf7
,
0x75
,
0x21
,
0x3f
,
0x75
,
0x49
,
0x11
,
0x75
,
0x4c
,
0x11
,
0x31
,
0xa3
,
0x02
,
0x23
,
0x93
,
0x78
,
0x11
,
0xe2
,
0x44
,
0x11
,
0x54
,
0x0f
,
0xf8
,
0xc4
,
0x48
,
0xf8
,
0xe5
,
0x49
,
0x45
,
0x3f
,
0x58
,
0xf5
,
0x49
,
0xd2
,
0x06
,
0xc2
,
0x0e
,
0x31
,
0xa3
,
0x02
,
0x23
,
0x93
,
0xc0
,
0x01
,
0x20
,
0x2a
,
0x04
,
0x71
,
0x32
,
0xc2
,
0x11
,
0x11
,
0x5e
,
0xc2
,
0x1f
,
0xd0
,
0x01
,
0x02
,
0x23
,
0x9b
,
0x12
,
0x21
,
0xdc
,
0x78
,
0x00
,
0xf2
,
0x22
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x79
,
0xda
,
0xe7
,
0x70
,
0x2b
,
0x20
,
0x0a
,
0x05
,
0x85
,
0x43
,
0xe0
,
0x80
,
0x03
,
0x75
,
0xe0
,
0x00
,
0x30
,
0xe1
,
0x1d
,
0x20
,
0xe2
,
0x1f
,
0x74
,
0xe0
,
0xca
,
0x74
,
0x00
,
0x71
,
0x9b
,
0xca
,
0x79
,
0x05
,
0xf3
,
0xf5
,
0x09
,
0xca
,
0x74
,
0x01
,
0x71
,
0x9b
,
0xca
,
0x79
,
0x05
,
0xf3
,
0xf5
,
0x0a
,
0x80
,
0x43
,
0x12
,
0x15
,
0x3e
,
0x80
,
0x3e
,
0xe5
,
0x0b
,
0xb4
,
0x17
,
0x02
,
0x80
,
0x0b
,
0x50
,
0x09
,
0x74
,
0x17
,
0xc3
,
0x95
,
0x0b
,
0x44
,
0x60
,
0x80
,
0x02
,
0x74
,
0x60
,
0xca
,
0x74
,
0x00
,
0x71
,
0x9b
,
0xca
,
0x79
,
0x05
,
0xf3
,
0xf5
,
0x09
,
0xe5
,
0x0c
,
0xb4
,
0x17
,
0x02
,
0x80
,
0x0b
,
0x50
,
0x09
,
0x74
,
0x17
,
0xc3
,
0x95
,
0x0c
,
0x44
,
0x60
,
0x80
,
0x02
,
0x74
,
0x60
,
0xca
,
0x74
,
0x01
,
0x71
,
0x9b
,
0xca
,
0x79
,
0x05
,
0xf3
,
0xf5
,
0x0a
,
0x22
,
0xd2
,
0x04
,
0x78
,
0x11
,
0xe2
,
0x44
,
0x11
,
0xf5
,
0x46
,
0xc2
,
0x0c
,
0x31
,
0xa3
,
0x02
,
0x23
,
0x93
,
0xd2
,
0x05
,
0x78
,
0x11
,
0xe2
,
0x44
,
0x11
,
0xf5
,
0x48
,
0xc2
,
0x0d
,
0x31
,
0xa3
,
0x02
,
0x23
,
0x93
,
0xd2
,
0x06
,
0x78
,
0x11
,
0xe2
,
0x44
,
0x11
,
0xf5
,
0x49
,
0xc2
,
0x0e
,
0x31
,
0xa3
,
0x02
,
0x23
,
0x93
,
0x30
,
0x1c
,
0x21
,
0x20
,
0x4d
,
0x1e
,
0xe5
,
0x29
,
0x60
,
0x1a
,
0xc2
,
0x1c
,
0x12
,
0x19
,
0xec
,
0x12
,
0x13
,
0xcf
,
0xd2
,
0x4d
,
0x12
,
0x17
,
0x7f
,
0x78
,
0x00
,
0xf2
,
0x79
,
0x06
,
0xf3
,
0x43
,
0xa8
,
0x04
,
0x12
,
0x24
,
0x1b
,
0x22
,
0x12
,
0x27
,
0x24
,
0x22
,
0x78
,
0x00
,
0xe2
,
0x90
,
0x25
,
0x9f
,
0x02
,
0x23
,
0x93
,
0x78
,
0x00
,
0xe2
,
0xa2
,
0xe7
,
0x72
,
0xe3
,
0x92
,
0xe7
,
0x02
,
0x1d
,
0x85
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x79
,
0x04
,
0xe3
,
0x54
,
0x80
,
0x70
,
0xf9
,
0x22
,
0xe5
,
0x29
,
0x79
,
0xde
,
0xf7
,
0x75
,
0x29
,
0x00
,
0x70
,
0x12
,
0xe5
,
0x15
,
0x79
,
0xdd
,
0xf7
,
0x12
,
0x2d
,
0xf0
,
0x40
,
0x08
,
0x20
,
0x1c
,
0x07
,
0x20
,
0x1d
,
0x04
,
0x80
,
0x02
,
0x71
,
0x32
,
0x30
,
0xb5
,
0x0c
,
0x79
,
0x06
,
0xf3
,
0x20
,
0x2a
,
0x06
,
0x79
,
0xdd
,
0xe7
,
0x54
,
0xfc
,
0xf7
,
0xd2
,
0x2b
,
0x12
,
0x25
,
0x6f
,
0x22
,
0x00
,
0x00
,
0x00
,
0x00
,
0xe5
,
0x15
,
0xa2
,
0xe0
,
0xb0
,
0xe6
,
0x40
,
0x31
,
0xa2
,
0xe1
,
0xb0
,
0xe7
,
0x40
,
0x38
,
0x10
,
0x2b
,
0x02
,
0x80
,
0x26
,
0x79
,
0xde
,
0xe7
,
0x70
,
0x0b
,
0x79
,
0xdd
,
0xe7
,
0x20
,
0xe0
,
0x12
,
0x20
,
0xe1
,
0x28
,
0x80
,
0x16
,
0xf5
,
0x29
,
0x30
,
0x4d
,
0x11
,
0x20
,
0x4c
,
0x0e
,
0x12
,
0x24
,
0x1b
,
0x80
,
0x09
,
0x43
,
0x08
,
0x40
,
0x12
,
0x13
,
0xcf
,
0x12
,
0x17
,
0x7f
,
0xe5
,
0x13
,
0x20
,
0xe4
,
0x05
,
0x12
,
0x18
,
0x1b
,
0x80
,
0x03
,
0x12
,
0x18
,
0x77
,
0xc2
,
0x2b
,
0x22
,
0x12
,
0x26
,
0xd7
,
0x12
,
0x13
,
0xb7
,
0x22
,
0x78
,
0x04
,
0x79
,
0x00
,
0xd9
,
0xfe
,
0xd8
,
0xfa
,
0x22
,
0x00
,
0x74
,
0x09
,
0x71
,
0x9b
,
0xe5
,
0x15
,
0x54
,
0xfc
,
0x79
,
0x05
,
0xf3
,
0xf5
,
0x15
,
0x22
,
0x78
,
0x11
,
0xe2
,
0x44
,
0x11
,
0x54
,
0x0f
,
0xf8
,
0xc4
,
0x48
,
0xf5
,
0x46
,
0xc2
,
0x0c
,
0xd2
,
0x04
,
0x31
,
0xa3
,
0x02
,
0x23
,
0x93
,
0x12
,
0x26
,
0xd7
,
0x12
,
0x00
,
0xb7
,
0x22
,
0x00
,
0x79
,
0x06
,
0xf3
,
0x74
,
0x0a
,
0x71
,
0x9b
,
0x79
,
0xe0
,
0xe7
,
0x44
,
0x02
,
0xf7
,
0x79
,
0x05
,
0xf3
,
0x22
,
0x74
,
0x0a
,
0x71
,
0x9b
,
0x79
,
0xe0
,
0xe7
,
0x54
,
0xfd
,
0xf7
,
0x79
,
0x05
,
0xf3
,
0x22
,
0x21
,
0x59
,
0x41
,
0x23
,
0x21
,
0x59
,
0x41
,
0x33
,
0x41
,
0x43
,
0x21
,
0x59
,
0x21
,
0x59
,
0x02
,
0x25
,
0x9f
,
0x00
,
0x74
,
0x0d
,
0x71
,
0x9b
,
0x74
,
0x4d
,
0x79
,
0x05
,
0xf3
,
0xd2
,
0x52
,
0x22
,
0x00
,
0x53
,
0x08
,
0x40
,
0x45
,
0x08
,
0x45
,
0x1e
,
0x79
,
0x04
,
0xf3
,
0xf5
,
0x08
,
0x22
,
0xd2
,
0x01
,
0x78
,
0x11
,
0xe2
,
0x44
,
0x11
,
0xf5
,
0x42
,
0xc2
,
0x09
,
0x31
,
0xa3
,
0x02
,
0x23
,
0x93
,
0x00
,
0x00
,
0x00
,
0x00
,
0x71
,
0x6e
,
0x74
,
0x09
,
0x12
,
0x17
,
0x75
,
0xe5
,
0x15
,
0x44
,
0x40
,
0x79
,
0x05
,
0xf3
,
0xf5
,
0x15
,
0x75
,
0x3a
,
0x00
,
0x12
,
0x1a
,
0x77
,
0x02
,
0x18
,
0x1b
,
0xf5
,
0x38
,
0xe5
,
0x37
,
0x24
,
0x01
,
0xf5
,
0x37
,
0xe5
,
0x38
,
0x34
,
0x00
,
0xf5
,
0x38
,
0x40
,
0x05
,
0x75
,
0x39
,
0x00
,
0x80
,
0x03
,
0x75
,
0x39
,
0x01
,
0x12
,
0x04
,
0x04
,
0xd2
,
0x8e
,
0x02
,
0x03
,
0x8d
,
0x00
,
0xb4
,
0x0d
,
0x03
,
0x74
,
0x14
,
0x22
,
0x04
,
0x83
,
0x22
,
0x00
,
0x02
,
0xff
,
0x01
,
0x00
,
0x05
,
0xfe
,
0xff
,
0x00
,
0x0a
,
0xfc
,
0xfe
,
0x00
,
0xc0
,
0xf8
,
0xfc
,
0x00
,
0x28
,
0xf0
,
0xf8
,
0x00
,
0x30
,
0xe0
,
0xd0
,
0x01
,
0x88
,
0x04
,
0x83
,
0x22
,
0x00
,
0xff
,
0xfe
,
0xfd
,
0xfc
,
0xfc
,
0xfb
,
0xfa
,
0xfe
,
0xfd
,
0xfb
,
0xf9
,
0xf7
,
0xf7
,
0xf5
,
0xf3
,
0xfc
,
0xfa
,
0xf6
,
0xf2
,
0xee
,
0xee
,
0xea
,
0xe6
,
0xf8
,
0xf4
,
0xec
,
0xe4
,
0xdc
,
0xd4
,
0xcc
,
0xc4
,
0x24
,
0x21
,
0x83
,
0x22
,
0x04
,
0x83
,
0x22
,
0xff
,
0x01
,
0xff
,
0x01
,
0x00
,
0x00
,
0x00
,
0x02
,
0x22
,
0x32
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0xff
,
0x00
,
0x00
,
0x00
,
0x00
,
0x01
,
0x01
,
0x01
,
0xff
,
0x00
,
0x00
,
0x00
,
0x00
,
0x01
,
0x01
,
0x01
,
0x83
,
0x22
,
0x8a
,
0x01
,
0x20
,
0x01
,
0x0b
,
0xea
,
0xf3
,
0xf9
,
0x8b
,
0x7e
,
0x6b
,
0xd5
,
0x01
,
0x00
,
0x01
,
0x00
,
0x01
,
0x00
,
0x01
,
0x00
,
0x01
,
0x00
,
0x01
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x01
,
0x3a
,
0x01
,
0x38
,
0x01
,
0x4b
,
0x01
,
0x49
,
0x01
,
0x5c
,
0x01
,
0x5a
,
0x01
,
0x08
,
0x08
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x01
,
0x15
,
0x24
,
0x48
,
0x83
,
0x22
,
0x04
,
0x83
,
0x22
,
0x00
,
0x01
,
0x02
,
0x03
,
0x04
,
0x06
,
0x07
,
0x08
,
0x00
,
0x03
,
0x05
,
0x07
,
0x09
,
0x0d
,
0x0f
,
0x81
,
0x00
,
0x06
,
0x0a
,
0x0e
,
0x82
,
0x8a
,
0x8e
,
0x22
,
0x00
,
0x0c
,
0x84
,
0x8c
,
0x24
,
0x2c
,
0xa4
,
0xac
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0xaa
,
0x35
,
0xab
,
0x36
,
0x02
,
0x27
,
0xd4
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x03
,
0x03
,
0x03
,
0x03
,
0x03
,
0x02
,
0x02
,
0x02
,
0x25
,
0x03
,
0x03
,
0x2b
,
0x03
,
0x00
,
0x03
,
0x00
,
0x03
,
0x00
,
0x03
,
0x00
,
0x03
,
0x00
,
0x03
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x03
,
0x03
,
0x03
,
0x03
,
0x03
,
0x03
,
0x03
,
0x03
,
0x03
,
0x03
,
0x03
,
0x03
,
0x03
,
0x03
,
0x03
,
0x83
,
0x22
,
0x00
,
0x02
,
0x02
,
0x02
,
0x01
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x01
,
0x02
,
0x02
,
0x02
,
0x2b
,
0x02
,
0x02
,
0x02
,
0x01
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x01
,
0x02
,
0x02
,
0x02
,
0x01
,
0x01
,
0x02
,
0x02
,
0x01
,
0x01
,
0x02
,
0x01
,
0x01
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x01
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x01
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x01
,
0x01
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x00
,
0x00
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x01
,
0x02
,
0x02
,
0x01
,
0x01
,
0x02
,
0x02
,
0x02
,
0x00
,
0x02
,
0x21
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x01
,
0x00
,
0x02
,
0x02
,
0x01
,
0x02
,
0x02
,
0x02
,
0x00
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x21
,
0x01
,
0x02
,
0x21
,
0x02
,
0x02
,
0x02
,
0x00
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x20
,
0xb5
,
0x05
,
0x79
,
0x0f
,
0xf3
,
0xc2
,
0x11
,
0x22
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0xe5
,
0x15
,
0xa2
,
0xe0
,
0xb0
,
0xe6
,
0x50
,
0x01
,
0x22
,
0xa2
,
0xe1
,
0xb0
,
0xe7
,
0x22
,
0x02
,
0x00
};
static
unsigned
char
Data0485_0C
[]
=
{
0x02
,
0x27
,
0x69
};
static
unsigned
char
Data0485_66
[]
=
{
0x02
,
0x25
,
0x47
,
0x02
,
0x25
,
0x60
};
static
unsigned
char
Data0485_60
[]
=
{
0x02
,
0x22
,
0x7e
};
static
unsigned
char
Data0485_99
[]
=
{
0xc2
,
0x53
,
0x02
,
0x12
,
0x86
};
static
unsigned
char
Data0485_9E
[]
=
{
0x70
,
0xf9
,
0x22
};
#ifdef OOKUBO_ORIGINAL
static
unsigned
char
Data0485_36
[]
=
{
0x78
,
0x00
,
0xf2
,
0xc2
,
0x53
,
0x74
,
0x86
,
0xc0
,
0xe0
,
0x74
,
0x12
,
0xc0
,
0xe0
,
0x32
};
#endif
/* OOKUBO_ORIGINAL */
sound/isa/cs423x/sound_pc9800.h
deleted
100644 → 0
View file @
bffc8f71
#ifndef _SOUND_PC9800_H_
#define _SOUND_PC9800_H_
#include <asm/io.h>
#define PC9800_SOUND_IO_ID 0xa460
/* Sound Functions ID. */
#define PC9800_SOUND_ID() ((inb(PC9800_SOUND_IO_ID) >> 4) & 0x0f)
#define PC9800_SOUND_ID_DO 0x0
/* PC-98DO+ Internal */
#define PC9800_SOUND_ID_GS 0x1
/* PC-98GS Internal */
#define PC9800_SOUND_ID_73 0x2
/* PC-9801-73 (base 0x18x) */
#define PC9800_SOUND_ID_73A 0x3
/* PC-9801-73/76 (base 0x28x) */
#define PC9800_SOUND_ID_86 0x4
/* PC-9801-86 and compatible (base 0x18x) */
#define PC9800_SOUND_ID_86A 0x5
/* PC-9801-86 (base 0x28x) */
#define PC9800_SOUND_ID_NF 0x6
/* PC-9821Nf/Np Internal */
#define PC9800_SOUND_ID_XMATE 0x7
/* X-Mate Internal and compatible */
#define PC9800_SOUND_ID_118 0x8
/* PC-9801-118 and compatible(CanBe Internal, etc.) */
#define PC9800_SOUND_ID_UNKNOWN 0xf
/* Unknown (No Sound System or PC-9801-26) */
#endif
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment