Commit e2c98881 authored by Linus Torvalds's avatar Linus Torvalds

Linux 2.2.8

Most of 2.2.8 by far is just architecture updates: arm, ppc and m68k stand
out as having been pretty much synchronized to their respective devel
trees, but there are some fixes to alpha and x86 too.

The one major fix in 2.2.8 is the SMP fix for disable_irq(), courtesy of
Andrea Arcangeli (I disagreed in details and did it differently in the
end, but all the heavy lifting was done by Andrea). This is the thing that
caused silenth deaths for some people with certain network adapters (3c509
and 8390-based cards in particular: the latter covers ne2000 clones which
are fairly common).

There are lots of smaller things (driver updates, filesystem cleanups and
some networking fixes), but the SMP irq thing is the one to kill for if
you happened to have any of the affected cards.
parent 8de4f87d
......@@ -2222,6 +2222,12 @@ S: 1507 145th Place SE #B5
S: Bellevue, Washington 98007
S: USA
N: Richard Zidlicky
E: rdzidlic@geocities.com,rdzidlic@cip.informatik.uni-erlangen.de
W: http://www.geocities.com/SiliconValley/Bay/2602/
D: Q40 port - see arch/m68k/q40/README
S: Germany
N: Werner Zimmermann
E: Werner.Zimmermann@fht-esslingen.de
D: CDROM driver "aztcd" (Aztech/Okano/Orchid/Wearnes)
......
......@@ -10170,27 +10170,11 @@ CONFIG_M68040
MC68EC040 will not work, as it does not include an MMU (Memory
Management Unit).
Use -m68040 flag for 68040 specific optimizations
CONFIG_OPTIMIZE_040
If you will only be running this kernel on a 68040-series processor,
this will make the kernel run somewhat faster. However, it will no
longer run on a 68020 or 68030, no matter whether you included 68020
and 68030 support or not. Say N unless the only processor you are
compiling support for is the 68040 (or 68LC040).
68060 support
CONFIG_M68060
If you anticipate running this kernel on a computer with a MC68060
processor, say Y. Otherwise, say N.
Use -m68060 flag for 68060 specific optimizations
CONFIG_OPTIMIZE_060
If you will only be running this kernel on a 68060-series processor,
this will make the kernel run somewhat faster. However, it will no
longer run on a 68020, 68030 or 68040, no matter whether you
included support for those processors or not. Say N unless the only
processor you are compiling support for is the 68060.
Advanced processor options
CONFIG_ADVANCED_CPU
This gives you access to some advanced options for the CPU. The
......@@ -10223,25 +10207,9 @@ CONFIG_ZORRO
Note that even if you say N here, you can still use your expansion
cards. If in doubt, say Y.
Amiga OCS chipset support
CONFIG_AMIFB_OCS
This enables support for the original Agnus and Denise video chips,
found in the Amiga 1000 and most A500's and A2000's. If you intend
to run Linux on any of these systems, say Y; otherwise say N.
Amiga ECS chipset support
CONFIG_AMIFB_ECS
This enables support for the Enhanced Chip Set, found in later
A500's, later A2000's, the A600, the A3000, the A3000T and CDTV. If
you intend to run Linux on any of these systems, say Y; otherwise
say N.
Amiga AGA chipset support
CONFIG_AMIFB_AGA
This enables support for the Advanced Graphics Architecture (also
known as the AGA or AA) Chip Set, found in the A1200, A4000, A4000T
and CD32. If you intend to run Linux on any of these systems, say Y;
otherwise say N.
CONFIG_AMIGA_PCMCIA
Include support in the kernel for pcmcia on Amiga 1200 and Amiga 600.
If you intend to use pcmcia cards say Y; otherwise say N.
Amiga GSP (TMS340x0) support
CONFIG_AMIGA_GSP
......@@ -10447,6 +10415,16 @@ CONFIG_HYDRA
want). The module is called hydra.o. If you want to compile it as a
module, say M here and read Documentation/modules.txt.
Pcmcia NE2000 compatible support
CONFIG_APNE
If you have a pcmcia ne2000 compatible adapter, say Y. Otherwise,
say N.
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you
want). The module is called apne.o. If you want to compile it as a
module, say M here and read Documentation/modules.txt.
Atari Lance support
CONFIG_ATARILANCE
Say Y to include support for several Atari Ethernet adapters based
......
......@@ -3,10 +3,10 @@
Command Line Options for Linux/m68k
===================================
Last Update: Nov 28, 1997
Linux/m68k version: 2.1.64
Last Update: 2 May 1999
Linux/m68k version: 2.2.6
Author: Roman.Hodek@informatik.uni-erlangen.de (Roman Hodek)
Update: jds@kom.auc.dk (Jes Sorensen)
Update: jds@kom.auc.dk (Jes Sorensen) and faq@linux-m68k.org (Chris Lawrence)
0) Introduction
===============
......@@ -145,7 +145,7 @@ Syntax: ro
These two options tell the kernel whether it should mount the root
filesystem read-only or read-write. The default is read-only, except
for ramdisks which are read-write.
for ramdisks, which default to read-write.
2.3) debug
......@@ -216,23 +216,10 @@ drive (with "root=").
2.7) swap=
-----------
Syntax: swap=<max_age>,<adv>,<decl>,<init_age>,<cl_fract>,<cl_min>,\
<pgout_wgt>,<bfout_wgt>
(All optional)
TODO
2.8) buff=
-----------
Syntax: buff=<max_age>,<adv>,<decl>,<init_age>,<bfout_wgt>,<mem_grace>
(All optional)
TODO
I can't find any sign of these options in 2.2.6.
3) General Device Options (Amiga and Atari)
......@@ -311,7 +298,7 @@ don't need to expand the sound.
=========================
4.1) video=
--------------
-----------
Syntax: video=<fbname>:<sub-options...>
......@@ -322,8 +309,8 @@ below.
NB: Please notice that this option was renamed from `atavideo' to
`video' during the development of the 1.3.x kernels, thus you
might need to update your boot-scripts if upgrading to 2.0.x from
an 1.2.13ply kernel.
might need to update your boot-scripts if upgrading to 2.x from
an 1.2.x kernel.
NBB: The behavior of video= was changed in 2.1.57 so the recommended
option is to specify the name of the frame buffer.
......@@ -705,10 +692,11 @@ down).
Syntax: video=<fbname>:<sub-options...>
The <fbname> parameter specifies the name of the frame buffer, valid
options are `amifb', `cyberfb', `retz3' and `clgen', provided that the
respective frame buffer devices have been compiled into the kernel (or
compiled as loadable modules). The behavior of the <fbname> option was
changed in 2.1.57 so it is now recommended to specify this option.
options are `amifb', `cyber', 'virge', `retz3' and `clgen', provided
that the respective frame buffer devices have been compiled into the
kernel (or compiled as loadable modules). The behavior of the <fbname>
option was changed in 2.1.57 so it is now recommended to specify this
option.
The <sub-options> is a comma-separated list of the sub-options listed
below. This option is organized similar to the Atari version of the
......@@ -762,8 +750,8 @@ Specify the number of bit-planes for the selected video-mode.
5.1.3) inverse
--------------
Use inverted display. Functionally the same as the "inverse"
sub-option for the Atari.
Use inverted display (black on white). Functionally the same as the
"inverse" sub-option for the Atari.
5.1.4) font
-----------
......@@ -787,7 +775,7 @@ the color frame buffer uses the settings of "monitorcap:".
your monitor can work with, in Hz. <hmin> and <hmax> are the same for
the horizontal frequency, in kHz.
The defaults are 50;90;15;38 (Generic Amiga monitor).
The defaults are 50;90;15;38 (Generic Amiga multisync monitor).
5.2) fd_def_df0=
......@@ -804,6 +792,9 @@ hexadecimal with "0x" prefix.
Syntax: wd33c93=<sub-options...>
These options affect the A590/A2091, A3000 and GVP Series II SCSI
controllers.
The <sub-options> is a comma-separated list of the sub-options listed
below.
......@@ -861,7 +852,7 @@ hostadapters.
-----------
No argument. Used to separate blocks of keywords when there's more
than one host adapter in the system.
than one wd33c93-based host adapter in the system.
5.3.7) nodma
------------
......@@ -905,6 +896,69 @@ controller and should be autodetected by the driver. An example is the
24 bit region which is specified by a mask of 0x00fffffe.
5.5) 53c7xx=
------------
Syntax: 53c7xx=<sub-options...>
These options affect the A4000T, A4091, WarpEngine, Blizzard 603e+,
and GForce 040/060 SCSI controllers on the Amiga, as well as the
builtin MVME 16x SCSI controller.
The <sub-options> is a comma-separated list of the sub-options listed
below.
5.5.1) nosync
-------------
Syntax: nosync:0
Disables sync negotiation for all devices. Any value after the
colon is acceptable (and has the same effect).
5.5.2) noasync
--------------
Syntax: noasync:0
Disables async and sync negotiation for all devices. Any value
after the colon is acceptable (and has the same effect).
5.5.3) nodisconnect
-------------------
Syntax: nodisconnect:0
Disables SCSI disconnects. Any value after the colon is acceptable
(and has the same effect).
5.5.4) validids
---------------
Syntax: validids:0xNN
Specify which SCSI ids the driver should pay attention to. This is
a bitmask (i.e. to only pay attention to ID#4, you'd use 0x10).
Default is 0x7f (devices 0-6).
5.5.5) opthi
5.5.6) optlo
------------
Syntax: opthi:M,optlo:N
Specify options for "hostdata->options". The acceptable definitions
are listed in drivers/scsi/53c7xx.h; the 32 high bits should be in
opthi and the 32 low bits in optlo. They must be specified in the
order opthi=M,optlo=N.
5.5.7) next
-----------
No argument. Used to separate blocks of keywords when there's more
than one 53c7xx host adapter in the system.
/* Local Variables: */
/* mode: text */
/* End: */
......@@ -56,6 +56,11 @@ SUBDIRS += arch/m68k/kernel arch/m68k/mm arch/m68k/lib
CORE_FILES := arch/m68k/kernel/kernel.o arch/m68k/mm/mm.o $(CORE_FILES)
LIBS += arch/m68k/lib/lib.a
ifdef CONFIG_Q40
CORE_FILES := $(CORE_FILES) arch/m68k/q40/q40.o
SUBDIRS := $(SUBDIRS) arch/m68k/q40
endif
ifdef CONFIG_AMIGA
CORE_FILES := $(CORE_FILES) arch/m68k/amiga/amiga.o
SUBDIRS := $(SUBDIRS) arch/m68k/amiga
......@@ -81,6 +86,11 @@ CORE_FILES := $(CORE_FILES) arch/m68k/apollo/apollo.o
SUBDIRS := $(SUBDIRS) arch/m68k/apollo
endif
ifdef CONFIG_MVME147
CORE_FILES := $(CORE_FILES) arch/m68k/mvme147/mvme147.o
SUBDIRS := $(SUBDIRS) arch/m68k/mvme147
endif
ifdef CONFIG_MVME16x
CORE_FILES := $(CORE_FILES) arch/m68k/mvme16x/mvme16x.o
SUBDIRS := $(SUBDIRS) arch/m68k/mvme16x
......@@ -91,6 +101,11 @@ CORE_FILES := $(CORE_FILES) arch/m68k/bvme6000/bvme6000.o
SUBDIRS := $(SUBDIRS) arch/m68k/bvme6000
endif
ifdef CONFIG_SUN3X
CORE_FILES := $(CORE_FILES) arch/m68k/sun3x/sun3x.o
SUBDIRS := $(SUBDIRS) arch/m68k/sun3x
endif
ifdef CONFIG_M68040
CORE_FILES := $(CORE_FILES) arch/m68k/fpsp040/fpsp.o
SUBDIRS := $(SUBDIRS) arch/m68k/fpsp040
......
......@@ -417,10 +417,10 @@ void bvme6000_init_console_port (struct console *co, int cflag)
static void scc_delay (void)
{
int n;
char i;
volatile int trash;
for (n = 0; n < 20; n++)
i = *(volatile char *)0;
trash = n;
}
static void scc_write (char ch)
......
......@@ -37,6 +37,7 @@ fi
bool 'Apollo support' CONFIG_APOLLO
bool 'VME (Motorola and BVM) support' CONFIG_VME
if [ "$CONFIG_VME" = "y" ]; then
bool 'MVME147 support' CONFIG_MVME147
bool 'MVME162, 166 and 167 support' CONFIG_MVME16x
bool 'BVME4000 and BVME6000 support' CONFIG_BVME6000
fi
......@@ -44,10 +45,13 @@ bool 'HP9000/300 support' CONFIG_HP300
if [ "$CONFIG_HP300" = "y" ]; then
bool 'DIO bus support' CONFIG_DIO
fi
bool 'Sun3x support' CONFIG_SUN3X
define_bool CONFIG_SUN3 n
if [ "$CONFIG_PCI" = "y" ]; then
bool 'Backward-compatible /proc/pci' CONFIG_PCI_OLD_PROC
fi
bool 'Q40/Q60 support' CONFIG_Q40
comment 'Processor type'
bool '68020 support' CONFIG_M68020
......@@ -94,6 +98,29 @@ else
fi
fi
bool '/proc/hardware support' CONFIG_PROC_HARDWARE
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
tristate 'Parallel port support (EXPERIMENTAL, disables old lp driver!)' CONFIG_PARPORT
if [ "$CONFIG_PARPORT" != "n" ]; then
if [ "$CONFIG_AMIGA" != "n" ]; then
dep_tristate ' Amiga builtin port' CONFIG_PARPORT_AMIGA $CONFIG_PARPORT
if [ "$CONFIG_ZORRO" != "n" ]; then
dep_tristate ' Multiface III parallel port' CONFIG_PARPORT_MFC3 $CONFIG_PARPORT
fi
fi
if [ "$CONFIG_Q40" != "n" ]; then
tristate ' Q40 Parallel port' CONFIG_PARPORT
if [ "$CONFIG_PARPORT" != "n" ]; then
define_bool CONFIG_PARPORT_PC y
fi
fi
fi
if [ "$CONFIG_ATARI" == "y" ]; then
dep_tristate ' Atari builtin port' CONFIG_PARPORT_ATARI $CONFIG_PARPORT
fi
fi
endmenu
source drivers/block/Config.in
......@@ -147,6 +174,7 @@ if [ "$CONFIG_ZORRO" = "y" ]; then
bool 'A4091 SCSI support' CONFIG_A4091_SCSI
bool 'WarpEngine SCSI support' CONFIG_WARPENGINE_SCSI
bool 'Blizzard PowerUP 603e+ SCSI' CONFIG_BLZ603EPLUS_SCSI
dep_tristate 'BSC Oktagon SCSI support' CONFIG_OKTAGON_SCSI $CONFIG_SCSI
bool 'Cyberstorm Mk III SCSI support' CONFIG_CYBERSTORMIII_SCSI
# bool 'GVP Turbo 040/060 SCSI support' CONFIG_GVP_TURBO_SCSI
fi
......@@ -167,6 +195,10 @@ if [ "$CONFIG_MAC" = "y" ]; then
fi
#dep_tristate 'SCSI debugging host adapter' CONFIG_SCSI_DEBUG $CONFIG_SCSI
if [ "$CONFIG_VME" = "y" -a "$CONFIG_MVME147" = "y" ]; then
bool 'WD33C93 SCSI driver for MVME147' CONFIG_MVME147_SCSI
fi
if [ "$CONFIG_VME" = "y" -a "$CONFIG_MVME16x" = "y" ]; then
bool 'NCR53C710 SCSI driver for MVME16x' CONFIG_MVME16x_SCSI
fi
......@@ -175,6 +207,10 @@ if [ "$CONFIG_VME" = "y" -a "$CONFIG_BVME6000" = "y" ]; then
bool 'NCR53C710 SCSI driver for BVME6000' CONFIG_BVME6000_SCSI
fi
if [ "$CONFIG_SUN3X" = "y" ]; then
bool 'ESP SCSI driver' CONFIG_SUN3X_ESP
fi
endmenu
fi
......@@ -219,6 +255,9 @@ if [ "$CONFIG_MAC" = "y" ]; then
# bool 'Macintosh (AV) onboard MACE ethernet' CONFIG_MACMACE
bool 'Macintosh (Quadra) onboard SONIC ethernet' CONFIG_MACSONIC
fi
if [ "$CONFIG_VME" = "y" -a "$CONFIG_MVME147" = "y" ]; then
tristate 'MVME147 (Lance) Ethernet support' CONFIG_MVME147_NET
fi
if [ "$CONFIG_VME" = "y" -a "$CONFIG_MVME16x" = "y" ]; then
tristate 'MVME16x Ethernet support' CONFIG_MVME16x_NET
fi
......@@ -232,9 +271,17 @@ if [ "$CONFIG_ATARI" = "y" ]; then
tristate 'PAMsNet support' CONFIG_ATARI_PAMSNET
fi
fi
if [ "$CONFIG_SUN3X" = "y" ]; then
bool 'Sun3x Lance support' CONFIG_SUNLANCE
fi
if [ "$CONFIG_HP300" = "y" ]; then
bool 'HP on-board LANCE support' CONFIG_HPLANCE
fi
if [ "$CONFIG_Q40" = "y" ]; then
if [ ! "$CONFIG_PARPORT" = "n" ]; then
dep_tristate 'PLIP (parallel port) support' CONFIG_PLIP $CONFIG_PARPORT
fi
fi
fi
endmenu
......@@ -243,6 +290,23 @@ fi
mainmenu_option next_comment
comment 'Character devices'
if [ "$CONFIG_Q40" = "y" ]; then
tristate 'Q40 Standard/generic serial support' CONFIG_SERIAL
fi
if [ "$CONFIG_SERIAL" = "y" ]; then
bool ' Support for console on serial port' CONFIG_SERIAL_CONSOLE
bool 'Extended dumb serial driver options' CONFIG_SERIAL_EXTENDED
fi
if [ "$CONFIG_SERIAL_EXTENDED" = "y" ]; then
bool ' Support more than 4 serial ports' CONFIG_SERIAL_MANY_PORTS
bool ' Support for sharing serial interrupts' CONFIG_SERIAL_SHARE_IRQ
# bool ' Autodetect IRQ - do not yet enable !!' CONFIG_SERIAL_DETECT_IRQ
bool ' Support special multiport boards' CONFIG_SERIAL_MULTIPORT
bool ' Support the Bell Technologies HUB6 card' CONFIG_HUB6
fi
if [ "$CONFIG_VME" = "n" ]; then
define_bool CONFIG_VT y
if [ "$CONFIG_VT" = "y" ]; then
......@@ -254,10 +318,17 @@ if [ "$CONFIG_ATARI" = "y" ]; then
define_bool CONFIG_NVRAM y
fi
tristate 'Parallel printer support' CONFIG_M68K_PRINTER
if [ "$CONFIG_ZORRO" = "y" ]; then
dep_tristate 'Multiface Card III parallel support' CONFIG_MULTIFACE_III_LP $CONFIG_M68K_PRINTER
fi
if [ "$CONFIG_PARPORT" = "n" ]; then
tristate 'Parallel printer support' CONFIG_M68K_PRINTER
if [ "$CONFIG_ZORRO" = "y" ]; then
dep_tristate 'Multiface Card III parallel support' CONFIG_MULTIFACE_III_LP $CONFIG_M68K_PRINTER
fi
else
dep_tristate 'Parallel printer support' CONFIG_PRINTER $CONFIG_PARPORT
if [ "$CONFIG_PRINTER" != "n" ]; then
bool ' Support IEEE1284 status readback' CONFIG_PRINTER_READBACK
fi
fi
if [ "$CONFIG_AMIGA" = "y" ]; then
tristate 'Amiga mouse support' CONFIG_AMIGAMOUSE
fi
......@@ -280,13 +351,17 @@ if [ "$CONFIG_ATARI" = "y" ]; then
fi
if [ "$CONFIG_AMIGA" = "y" ]; then
tristate 'Amiga builtin serial support' CONFIG_AMIGA_BUILTIN_SERIAL
bool 'Hisoft Whippet PCMCIA serial support' CONFIG_WHIPPET
if [ "$CONFIG_AMIGA_PCMCIA" = "y" ]; then
tristate 'Hisoft Whippet PCMCIA serial support' CONFIG_WHIPPET_SERIAL
fi
fi
if [ "$CONFIG_ZORRO" = "y" ]; then
tristate 'GVP IO-Extender support' CONFIG_GVPIOEXT
dep_tristate 'GVP IO-Extender parallel printer support' CONFIG_GVPIOEXT_LP $CONFIG_GVPIOEXT
dep_tristate 'GVP IO-Extender PLIP support' CONFIG_GVPIOEXT_PLIP $CONFIG_GVPIOEXT
tristate 'Multiface Card III serial support' CONFIG_MULTIFACE_III_TTY
if [ "$CONFIG_PARPORT" = "n" ]; then
if [ "$CONFIG_ZORRO" = "y" ]; then
tristate 'GVP IO-Extender support' CONFIG_GVPIOEXT
dep_tristate 'GVP IO-Extender parallel printer support' CONFIG_GVPIOEXT_LP $CONFIG_GVPIOEXT
dep_tristate 'GVP IO-Extender PLIP support' CONFIG_GVPIOEXT_PLIP $CONFIG_GVPIOEXT
tristate 'Multiface Card III serial support' CONFIG_MULTIFACE_III_TTY
fi
fi
if [ "$CONFIG_MAC" = "y" ]; then
bool 'Mac SCC serial support' CONFIG_MAC_SCC
......@@ -294,18 +369,32 @@ fi
if [ "$CONFIG_HP300" = "y" -a "$CONFIG_DIO" = "y" ]; then
tristate 'HP DCA serial support' CONFIG_HPDCA
fi
if [ "$CONFIG_SUN3X" = "y" ]; then
bool 'Sun3x builtin serial support' CONFIG_SUN3X_ZS
if [ "$CONFIG_SUN3X_ZS" = "y" ]; then
bool 'Sun keyboard support' CONFIG_SUN_KEYBOARD
bool 'Sun mouse support' CONFIG_SUN_MOUSE
define_bool CONFIG_SBUS y
define_bool CONFIG_SBUSCHAR y
define_bool CONFIG_SUN_SERIAL y
fi
fi
if [ "$CONFIG_AMIGA" = "y" -o "$CONFIG_ATARI" = "y" -o \
"$CONFIG_MAC" = "y" -o "$CONFIG_HP300" = "y" ]; then
"$CONFIG_MAC" = "y" -o "$CONFIG_HP300" = "y" -o \
"$CONFIG_SUN3X" = "y" ]; then
if [ "$CONFIG_ATARI_MFPSER" = "y" -o "$CONFIG_ATARI_SCC" = "y" -o \
"$CONFIG_ATARI_MIDI" = "y" -o "$CONFIG_MAC_SCC" = "y" -o \
"$CONFIG_AMIGA_BUILTIN_SERIAL" = "y" -o \
"$CONFIG_GVPIOEXT" = "y" -o "$CONFIG_MULTIFACE_III_TTY" = "y" -o \
"$CONFIG_HPDCA" = "y" ]; then
"$CONFIG_HPDCA" = "y" -o "$CONFIG_SUN3X_ZS" = "y" ]; then
bool 'Support for serial port console' CONFIG_SERIAL_CONSOLE
fi
fi
if [ "$CONFIG_VME" = "y" ]; then
define_bool CONFIG_SERIAL_CONSOLE y
if [ "$CONFIG_MVME147" = "y" ]; then
bool 'SCC support for MVME147 serial ports' CONFIG_MVME147_SCC
fi
if [ "$CONFIG_MVME16x" = "y" ]; then
bool 'CD2401 support for MVME166/7 serial ports' CONFIG_SERIAL167
bool 'SCC support for MVME162 serial ports' CONFIG_MVME162_SCC
......
......@@ -164,8 +164,17 @@ SYMBOL_NAME_LABEL(inthandler)
movel %sp,%sp@-
movel %d0,%sp@- | put vector # on stack
#if defined(MACH_Q40_ONLY) && defined(CONFIG_BLK_DEV_FD)
btstb #4,0xff000000 | Q40 floppy needs very special treatment ...
jbeq 1f
btstb #3,0xff000004
jbeq 1f
jbsr SYMBOL_NAME(floppy_hardint)
jbra 3f
1:
#endif
jbsr SYMBOL_NAME(process_int)| process the IRQ
addql #8,%sp | pop parameters off stack
3: addql #8,%sp | pop parameters off stack
SYMBOL_NAME_LABEL(ret_from_interrupt)
subql #1,SYMBOL_NAME(local_irq_count)
......@@ -295,6 +304,8 @@ SYMBOL_NAME_LABEL(resume)
2: fmovemx %fp0-%fp7,%a0@(TASK_TSS+TSS_FPREG)
fmoveml %fpcr/%fpsr/%fpiar,%a0@(TASK_TSS+TSS_FPCNTL)
3:
/* Return previous task in %d1 */
movel %curptr,%d1
/* switch to new task (a1 contains new task) */
movel %a1,%curptr
......@@ -320,8 +331,15 @@ SYMBOL_NAME_LABEL(resume)
movec %d0,%cacr
/* switch the root pointer */
#ifdef CPU_M68030_ONLY
.chip 68030
pmovefd %a1@(TASK_TSS+TSS_CRP),%crp
.chip 68k
pflush #0,#4
#else
pmove %a1@(TASK_TSS+TSS_CRP),%crp
#endif
#endif
#if defined(CPU_M68020_OR_M68030) && defined(CPU_M68040_OR_M68060)
jra 2f /* skip m68040 stuff */
......
......@@ -23,6 +23,7 @@
** 98/04/25 Phil Blundell: added HP300 support
** 1998/08/30 David Kilzer: Added support for fbcon_font_desc structures
** for linux-2.1.115
** 9/02/11 Richard Zidlicky: added Q40 support (initial vesion 99/01/01)
**
** This file is subject to the terms and conditions of the GNU General Public
** License. See the file README.legal in the main directory of this archive
......@@ -303,6 +304,12 @@
.globl SYMBOL_NAME(availmem)
.globl SYMBOL_NAME(m68k_pgtable_cachemode)
.globl SYMBOL_NAME(m68k_supervisor_cachemode)
#ifdef CONFIG_MVME16x
.globl SYMBOL_NAME(mvme_bdid_ptr)
#endif
#ifdef CONFIG_Q40
.globl SYMBOL_NAME(q40_mem_cptr)
#endif
CPUTYPE_040 = 1 /* indicates an 040 */
CPUTYPE_060 = 2 /* indicates an 060 */
......@@ -512,13 +519,15 @@ func_define putn,1
#endif
.endm
#define is_not_amiga(lab) cmpl &MACH_AMIGA,%pc@(m68k_machtype); jne lab
#define is_not_atari(lab) cmpl &MACH_ATARI,%pc@(m68k_machtype); jne lab
#define is_not_mac(lab) cmpl &MACH_MAC,%pc@(m68k_machtype); jne lab
#define is_not_mvme147(lab) cmpl &MACH_MVME147,%pc@(m68k_machtype); jne lab
#define is_not_mvme16x(lab) cmpl &MACH_MVME16x,%pc@(m68k_machtype); jne lab
#define is_not_bvme6000(lab) cmpl &MACH_BVME6000,%pc@(m68k_machtype); jne lab
#define is_not_hp300(lab) cmpl &MACH_HP300,%pc@(m68k_machtype); jne lab
#define is_not_q40(lab) cmpl &MACH_Q40,%pc@(m68k_machtype); jne lab
#define is_not_sun3x(lab) cmpl &MACH_SUN3X,%pc@(m68k_machtype); jne lab
#define is_040_or_060(lab) btst &CPUTYPE_0460,%pc@(L(cputype)+3); jne lab
#define is_not_040_or_060(lab) btst &CPUTYPE_0460,%pc@(L(cputype)+3); jeq lab
......@@ -552,9 +561,11 @@ ENTRY(_stext)
.long BOOTINFOV_MAGIC
.long MACH_AMIGA, AMIGA_BOOTI_VERSION
.long MACH_ATARI, ATARI_BOOTI_VERSION
.long MACH_MVME147, MVME147_BOOTI_VERSION
.long MACH_MVME16x, MVME16x_BOOTI_VERSION
.long MACH_BVME6000, BVME6000_BOOTI_VERSION
.long MACH_MAC, MAC_BOOTI_VERSION
.long MACH_Q40, Q40_BOOTI_VERSION
.long 0
1: jra SYMBOL_NAME(__start)
......@@ -859,7 +870,12 @@ L(mmu_init_amiga):
/*
* 040: Map the 16Meg range physical 0x0 upto logical 0x8000.0000
*/
mmu_map #0x80000000,#0,#0x01000000,#_PAGE_NOCACHE_S
mmu_map #0x80000000,#0,#0x01000000,#_PAGE_NOCACHE_S
/*
* Map the Zorro III I/O space with transparent translation
* for frame buffer memory etc.
*/
mmu_map_tt #1,#0x40000000,#0x20000000,#_PAGE_NOCACHE_S
jbra L(mmu_init_done)
......@@ -867,7 +883,8 @@ L(mmu_init_amiga):
/*
* 030: Map the 32Meg range physical 0x0 upto logical 0x8000.0000
*/
mmu_map #0x80000000,#0,#0x02000000,#_PAGE_NOCACHE030
mmu_map #0x80000000,#0,#0x02000000,#_PAGE_NOCACHE030
mmu_map_tt #1,#0x40000000,#0x20000000,#_PAGE_NOCACHE030
jbra L(mmu_init_done)
......@@ -926,6 +943,25 @@ L(spata68040):
L(mmu_init_not_atari):
#endif
#ifdef CONFIG_Q40
is_not_q40(L(notq40))
/*
* add transparent mapping for 0xff00 0000 - 0xffff ffff
* non-cached serialized etc..
* this includes master chip, DAC, RTC and ISA ports
* 0xfe000000-0xfeffffff is for screen and ROM
*/
putc 'Q'
mmu_map_tt #0,#0xfe000000,#0x01000000,#_PAGE_CACHE040W
mmu_map_tt #1,#0xff000000,#0x01000000,#_PAGE_NOCACHE_S
jbra L(mmu_init_done)
L(notq40):
#endif
#ifdef CONFIG_HP300
is_not_hp300(L(nothp300))
......@@ -940,6 +976,24 @@ L(nothp300):
#endif
#ifdef CONFIG_MVME147
is_not_mvme147(L(not147))
/*
* On MVME147 we have already created kernel page tables for
* 4MB of RAM at address 0, so now need to do a transparent
* mapping of the top of memory space. Make it 0.5GByte for now,
* so we can access on-board i/o areas.
*/
mmu_map_tt #1,#0xe0000000,#0x20000000,#_PAGE_NOCACHE030
jbra L(mmu_init_done)
L(not147):
#endif /* CONFIG_MVME147 */
#ifdef CONFIG_MVME16x
is_not_mvme16x(L(not16x))
......@@ -965,7 +1019,7 @@ L(nothp300):
* 0xffe00000->0xffe1ffff.
*/
mmu_map_tt 1,#0xe0000000,#0x20000000,#_PAGE_NOCACHE_S
mmu_map_tt #1,#0xe0000000,#0x20000000,#_PAGE_NOCACHE_S
jbra L(mmu_init_done)
......@@ -985,7 +1039,7 @@ L(not16x):
* clash with User code virtual address space.
*/
mmu_map_tt 1,#0xe0000000,#0x20000000,#_PAGE_NOCACHE_S
mmu_map_tt #1,#0xe0000000,#0x20000000,#_PAGE_NOCACHE_S
jbra L(mmu_init_done)
......@@ -1052,13 +1106,23 @@ L(mmu_init_mac):
mmu_map_eq #0x50000000,#0x02000000,%d3
mmu_map_eq #0x60000000,#0x00400000,%d3
mmu_map_eq #0x9c000000,#0x00400000,%d3
mmu_map_tt 1,#0xf8000000,#0x08000000,%d3
mmu_map_tt #1,#0xf8000000,#0x08000000,%d3
jbra L(mmu_init_done)
L(mmu_init_not_mac):
#endif
#ifdef CONFIG_SUN3X
is_not_sun3x(L(notsun3x))
/* setup tt1 for I/O */
mmu_map_tt #1,#0x40000000,#0x40000000,#_PAGE_NOCACHE_S
L(notsun3x):
jbra L(mmu_init_done)
#endif
L(mmu_init_done):
putc 'G'
......@@ -1214,6 +1278,14 @@ L(mmu_fixup_done):
1:
#endif
#ifdef CONFIG_SUN3X
is_not_sun3x(1f)
/* enable copro */
oriw #0x4000,0x61000000
1:
#endif
/*
* Fixup the addresses for the kernel pointer table and availmem.
* Convert them from physical addresses to virtual addresses.
......@@ -1780,7 +1852,7 @@ func_start mmu_map_tt,%d0/%d1/%a0,4
/* Extract the highest bit set
*/
bfffo ARG3{#0,#32},%d1
cmpw #8,%d0
cmpw #8,%d1
jcc L(do_map)
/* And get the mask
......@@ -2155,7 +2227,9 @@ func_start mmu_temp_map,%d0/%d1/%a0/%a1
/* Temporary allocate a page table and insert it into the ptr table
*/
movel %a1@,%d0
addl #PTR_TABLE_SIZE*4,%a1@
/* The 512 should be PAGE_TABLE_SIZE*4, but that violates the
alignment restriction for pointer tables on the '0[46]0. */
addl #512,%a1@
orw #_PAGE_TABLE+_PAGE_ACCESSED,%d0
movel %d0,%a0@
dputs " (new)"
......@@ -2703,6 +2777,31 @@ func_start serial_init,%d0/%d1/%a0/%a1
L(serial_init_not_mac):
#endif /* CONFIG_MAC */
#ifdef CONFIG_Q40
is_not_q40(2f)
/* debug output goes into SRAM, so we don't do it unless requested
- check for '%LX$' signature in SRAM */
lea %pc@(SYMBOL_NAME(q40_mem_cptr)),%a1
move.l #0xff020010,%a1@ /* must be inited - also used by debug=mem */
move.l #0xff020000,%a1
cmp.b #'%',%a1@
bne 2f /*nodbg*/
addq.w #4,%a1
cmp.b #'L',%a1@
bne 2f /*nodbg*/
addq.w #4,%a1
cmp.b #'X',%a1@
bne 2f /*nodbg*/
addq.w #4,%a1
cmp.b #'$',%a1@
bne 2f /*nodbg*/
/* signature OK */
lea %pc@(L(q40_do_debug)),%a1
tas %a1@
/*nodbg: q40_do_debug is 0 by default*/
2:
#endif
L(serial_init_done):
func_return serial_init
......@@ -2792,6 +2891,15 @@ func_start serial_putc,%d0/%d1/%a0/%a1
4:
#endif /* CONFIG_ATARI */
#ifdef CONFIG_MVME147
is_not_mvme147(2f)
1: btst #2,M147_SCC_CTRL_A
jeq 1b
moveb %d0,M147_SCC_DATA_A
jbra L(serial_putc_done)
2:
#endif
#ifdef CONFIG_MVME16x
is_not_mvme16x(2f)
/*
......@@ -2805,7 +2913,7 @@ func_start serial_putc,%d0/%d1/%a0/%a1
moveml %sp@+,%d0-%d7/%a2-%a6
jbra L(serial_putc_done)
2:
#endif CONFIG_MVME162 | CONFIG_MVME167
#endif CONFIG_MVME16x
#ifdef CONFIG_BVME6000
is_not_bvme6000(2f)
......@@ -2819,6 +2927,18 @@ func_start serial_putc,%d0/%d1/%a0/%a1
2:
#endif
#ifdef CONFIG_Q40
is_not_q40(2f)
tst.l %pc@(L(q40_do_debug)) /* only debug if requested */
beq 2f
lea %pc@(SYMBOL_NAME(q40_mem_cptr)),%a1
move.l %a1@,%a0
move.b %d0,%a0@
addq.l #4,%a0
move.l %a0,%a1@
2:
#endif
L(serial_putc_done):
func_return serial_putc
......@@ -3472,6 +3592,10 @@ L(kernel_pgdir_ptr):
L(temp_mmap_mem):
.long 0
#if defined (CONFIG_MVME147)
M147_SCC_CTRL_A = 0xfffe3002
M147_SCC_DATA_A = 0xfffe3003
#endif
#if defined (CONFIG_BVME6000)
BVME_SCC_CTRL_A = 0xffb0000b
......@@ -3509,3 +3633,9 @@ SYMBOL_NAME_LABEL(m68k_supervisor_cachemode)
SYMBOL_NAME_LABEL(mvme_bdid_ptr)
.long 0
#endif
#if defined(CONFIG_Q40)
SYMBOL_NAME_LABEL(q40_mem_cptr)
.long 0
L(q40_do_debug):
.long 0
#endif
......@@ -38,6 +38,10 @@
#include <asm/page.h>
#include <asm/machdep.h>
#ifdef CONFIG_Q40
#include <asm/q40ints.h>
#endif
/* table for system interrupt handlers */
static irq_handler_t irq_list[SYS_IRQS];
......@@ -177,14 +181,24 @@ void sys_free_irq(unsigned int irq, void *dev_id)
/*
* Do we need these probe functions on the m68k?
*
* ... may be usefull with ISA devices
*/
unsigned long probe_irq_on (void)
{
#ifdef CONFIG_Q40
if (MACH_IS_Q40)
return q40_probe_irq_on();
#endif
return 0;
}
int probe_irq_off (unsigned long irqs)
{
#ifdef CONFIG_Q40
if (MACH_IS_Q40)
return q40_probe_irq_off(irqs);
#endif
return 0;
}
......
......@@ -3,6 +3,47 @@
*/
#define TS_MAGICKEY 0x5a5a5a5a
#define TS_TSS 482
#define TS_ESP0 502
#define TS_FPU 506
#define TASK_STATE 0
#define TASK_FLAGS 4
#define TASK_SIGPENDING 8
#define TASK_NEEDRESCHED 20
#define TASK_TSS 470
#define TASK_MM 622
#define TSS_KSP 0
#define TSS_USP 4
#define TSS_SR 8
#define TSS_FS 10
#define TSS_CRP 12
#define TSS_ESP0 20
#define TSS_FPREG 24
#define TSS_FPCNTL 120
#define TSS_FPSTATE 132
#define PT_D0 32
#define PT_ORIG_D0 36
#define PT_SR 44
#define PT_VECTOR 50
#define IRQ_HANDLER 0
#define IRQ_DEVID 8
#define IRQ_NEXT 16
#define STAT_IRQ 120
#define BIR_TAG 0
#define BIR_SIZE 2
#define BIR_DATA 4
#define FBCON_FONT_DESC_IDX 0
#define FBCON_FONT_DESC_NAME 4
#define FBCON_FONT_DESC_WIDTH 8
#define FBCON_FONT_DESC_HEIGHT 12
#define FBCON_FONT_DESC_DATA 16
#define FBCON_FONT_DESC_PREF 20
#define CUSTOMBASE -2132807680
#define C_INTENAR 28
#define C_INTREQR 30
#define C_INTENA 154
#define C_INTREQ 156
#define C_SERDATR 24
#define C_SERDAT 48
#define C_SERPER 50
#define CIAABASE -2134908927
#define CIABBASE -2134913024
#define C_PRA 0
#define ZTWOBASE -2147483648
......@@ -18,6 +18,7 @@
#include <asm/checksum.h>
#include <asm/hardirq.h>
#include <asm/softirq.h>
#include <asm/m68kserial.h>
asmlinkage long long __ashrdi3 (long long, int);
extern char m68k_debug_device[];
......@@ -54,6 +55,8 @@ EXPORT_SYMBOL(enable_irq);
EXPORT_SYMBOL(disable_irq);
EXPORT_SYMBOL(kernel_set_cachemode);
EXPORT_SYMBOL(kernel_thread);
EXPORT_SYMBOL(register_serial);
EXPORT_SYMBOL(unregister_serial);
/* Networking helper routines. */
EXPORT_SYMBOL(csum_partial_copy);
......@@ -69,4 +72,5 @@ EXPORT_SYMBOL_NOVERS(memcmp);
EXPORT_SYMBOL_NOVERS(__down_failed);
EXPORT_SYMBOL_NOVERS(__down_failed_interruptible);
EXPORT_SYMBOL_NOVERS(__down_failed_trylock);
EXPORT_SYMBOL_NOVERS(__up_wakeup);
......@@ -169,15 +169,7 @@ asmlinkage int m68k_fork(struct pt_regs *regs)
asmlinkage int m68k_vfork(struct pt_regs *regs)
{
int child;
struct semaphore sem = MUTEX_LOCKED;
child = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs);
if (child > 0)
down(&sem);
return child;
return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs);
}
asmlinkage int m68k_clone(struct pt_regs *regs)
......@@ -190,7 +182,7 @@ asmlinkage int m68k_clone(struct pt_regs *regs)
newsp = regs->d2;
if (!newsp)
newsp = rdusp();
return do_fork(clone_flags & ~CLONE_VFORK, newsp, regs);
return do_fork(clone_flags, newsp, regs);
}
int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
......
......@@ -312,6 +312,7 @@ static int write_long(struct task_struct * tsk, unsigned long addr,
asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
{
struct task_struct *child;
unsigned long flags;
int ret;
lock_kernel();
......@@ -343,21 +344,22 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
(current->uid != child->uid) ||
(current->gid != child->egid) ||
(current->gid != child->sgid) ||
(!cap_issubset(child->cap_permitted, current->cap_permitted)) ||
(current->gid != child->gid)) && !capable(CAP_SYS_PTRACE))
goto out;
/* the same process cannot be attached many times */
if (child->flags & PF_PTRACED)
goto out;
child->flags |= PF_PTRACED;
if (child->p_pptr != current) {
unsigned long flags;
write_lock_irqsave(&tasklist_lock, flags);
write_lock_irqsave(&tasklist_lock, flags);
if (child->p_pptr != current) {
REMOVE_LINKS(child);
child->p_pptr = current;
SET_LINKS(child);
write_unlock_irqrestore(&tasklist_lock, flags);
}
write_unlock_irqrestore(&tasklist_lock, flags);
send_sig(SIGSTOP, child, 1);
ret = 0;
goto out;
......@@ -502,7 +504,6 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
}
case PTRACE_DETACH: { /* detach a process that was attached. */
unsigned long flags;
long tmp;
ret = -EIO;
......
......@@ -77,10 +77,26 @@ int (*mach_hwclk) (int, struct hwclk_time*) = NULL;
int (*mach_set_clock_mmss) (unsigned long) = NULL;
void (*mach_reset)( void );
long mach_max_dma_address = 0x00ffffff; /* default set to the lower 16MB */
#if defined(CONFIG_AMIGA_FLOPPY) || defined(CONFIG_ATARI_FLOPPY)
#if defined(CONFIG_AMIGA_FLOPPY) || defined(CONFIG_ATARI_FLOPPY) || defined(CONFIG_BLK_DEV_FD)
void (*mach_floppy_setup) (char *, int *) __initdata = NULL;
void (*mach_floppy_eject) (void) = NULL;
#endif
struct serial_struct;
#ifdef CONFIG_SERIAL
long serial_rs_init(void);
int serial_register_serial(struct serial_struct *);
void serial_unregister_serial(int);
long ser_console_init(long, long );
#endif
#if defined(CONFIG_USERIAL)||defined(CONFIG_BVME6000_SCC)||defined(CONFIG_MVME162_SCC)||defined(CONFIG_HPDCA)||defined(CONFIG_WHIPPET_SERIAL)||defined(CONFIG_MULTIFACE_III_TTY)||defined(CONFIG_GVPIOEXT)||defined(CONFIG_AMIGA_BUILTIN_SERIAL)||defined(CONFIG_MAC_SCC)||defined(CONFIG_ATARI_MIDI)||defined(CONFIG_ATARI_SCC)||defined(CONFIG_ATARI_MFPSER)
#define M68K_SERIAL
#endif
#ifdef M68K_SERIAL
long m68k_rs_init(void);
int m68k_register_serial(struct serial_struct *);
void m68k_unregister_serial(int);
long m68k_serial_console_init(long, long );
#endif
#ifdef CONFIG_HEARTBEAT
void (*mach_heartbeat) (int) = NULL;
#endif
......@@ -97,15 +113,19 @@ char *mach_sysrq_xlate = NULL;
extern int amiga_parse_bootinfo(const struct bi_record *);
extern int atari_parse_bootinfo(const struct bi_record *);
extern int mac_parse_bootinfo(const struct bi_record *);
extern int q40_parse_bootinfo(const struct bi_record *);
extern void config_amiga(void);
extern void config_atari(void);
extern void config_mac(void);
extern void config_sun3(void);
extern void config_apollo(void);
extern void config_mvme147(void);
extern void config_mvme16x(void);
extern void config_bvme6000(void);
extern void config_hp300(void);
extern void config_q40(void);
extern void config_sun3x(void);
#define MASK_256K 0xfffc0000
......@@ -149,6 +169,8 @@ __initfunc(static void m68k_parse_bootinfo(const struct bi_record *record))
unknown = atari_parse_bootinfo(record);
else if (MACH_IS_MAC)
unknown = mac_parse_bootinfo(record);
else if (MACH_IS_Q40)
unknown = q40_parse_bootinfo(record);
else
unknown = 1;
}
......@@ -258,6 +280,11 @@ __initfunc(void setup_arch(char **cmdline_p, unsigned long * memory_start_p,
config_apollo();
break;
#endif
#ifdef CONFIG_MVME147
case MACH_MVME147:
config_mvme147();
break;
#endif
#ifdef CONFIG_MVME16x
case MACH_MVME16x:
config_mvme16x();
......@@ -272,6 +299,16 @@ __initfunc(void setup_arch(char **cmdline_p, unsigned long * memory_start_p,
case MACH_HP300:
config_hp300();
break;
#endif
#ifdef CONFIG_Q40
case MACH_Q40:
config_q40();
break;
#endif
#ifdef CONFIG_SUN3X
case MACH_SUN3X:
config_sun3x();
break;
#endif
default:
panic ("No configuration setup");
......@@ -384,7 +421,52 @@ int get_hardware_list(char *buffer)
return(len);
}
#if defined(CONFIG_AMIGA_FLOPPY) || defined(CONFIG_ATARI_FLOPPY)
#if defined(CONFIG_SERIAL) || defined(M68K_SERIAL)
int rs_init(void)
{
#ifdef CONFIG_SERIAL
if (MACH_IS_Q40)
return serial_rs_init();
#endif
#ifdef M68K_SERIAL
return m68k_rs_init();
#endif
}
int register_serial(struct serial_struct *p)
{
#ifdef CONFIG_SERIAL
if (MACH_IS_Q40)
return serial_register_serial(p);
#endif
#ifdef M68K_SERIAL
return m68k_register_serial(p);
#endif
}
void unregister_serial(int i)
{
#ifdef CONFIG_SERIAL
if (MACH_IS_Q40)
serial_unregister_serial(i);
#endif
#ifdef M68K_SERIAL
m68k_unregister_serial(i);
#endif
}
#ifdef CONFIG_SERIAL_CONSOLE
long serial_console_init(long kmem_start, long kmem_end)
{
#ifdef CONFIG_SERIAL
if (MACH_IS_Q40)
return ser_console_init(kmem_start, kmem_end);
#endif
#if defined(M68K_SERIAL) && defined(CONFIG_SERIAL_CONSOLE)
return m68k_serial_console_init(kmem_start, kmem_end);
#endif
}
#endif
#endif
#if defined(CONFIG_AMIGA_FLOPPY) || defined(CONFIG_ATARI_FLOPPY) || defined(CONFIG_BLK_DEV_FD)
__initfunc(void floppy_setup(char *str, int *ints))
{
if (mach_floppy_setup)
......@@ -399,7 +481,7 @@ void floppy_eject(void)
#endif
/* for "kbd-reset" cmdline param */
void __init kbd_reset_setup(char *str, int *ints)
__initfunc(void kbd_reset_setup(char *str, int *ints))
{
}
......
......@@ -200,5 +200,5 @@ void do_settimeofday(struct timeval *tv)
time_status |= STA_UNSYNC;
time_maxerror = NTP_PHASE_LIMIT;
time_esterror = NTP_PHASE_LIMIT;
sti();
write_unlock_irq(&xtime_lock);
}
......@@ -32,6 +32,16 @@ ENTRY(__down_failed_interruptible)
movel (%sp)+,%a0
rts
ENTRY(__down_failed_trylock)
movel %a0,-(%sp)
movel %d1,-(%sp)
movel %a1,-(%sp)
jbsr SYMBOL_NAME(__down_trylock)
movel (%sp)+,%a1
movel (%sp)+,%d1
movel (%sp)+,%a0
rts
ENTRY(__up_wakeup)
moveml %a0/%d0/%d1,-(%sp)
movel %a1,-(%sp)
......
......@@ -123,7 +123,7 @@ void show_mem(void)
unsigned long mm_cachebits = 0;
#endif
static pte_t *__init kernel_page_table(unsigned long *memavailp)
__initfunc(static pte_t * kernel_page_table(unsigned long *memavailp))
{
pte_t *ptablep;
......@@ -140,15 +140,19 @@ static pte_t *__init kernel_page_table(unsigned long *memavailp)
static pmd_t *last_pgtable __initdata = NULL;
static pmd_t *__init kernel_ptr_table(unsigned long *memavailp)
__initfunc(static pmd_t * kernel_ptr_table(unsigned long *memavailp))
{
if (!last_pgtable) {
unsigned long pmd, last;
int i;
/* Find the last ptr table that was used in head.S and
* reuse the remaining space in that page for further
* ptr tables.
*/
last = (unsigned long)kernel_pg_dir;
for (i = 0; i < PTRS_PER_PGD; i++) {
if (!pgd_val(kernel_pg_dir[i]))
if (!pgd_present(kernel_pg_dir[i]))
continue;
pmd = pgd_page(kernel_pg_dir[i]);
if (pmd > last)
......@@ -175,8 +179,8 @@ static pmd_t *__init kernel_ptr_table(unsigned long *memavailp)
return last_pgtable;
}
static unsigned long __init
map_chunk (unsigned long addr, long size, unsigned long *memavailp)
__initfunc(static unsigned long
map_chunk (unsigned long addr, long size, unsigned long *memavailp))
{
#define PTRTREESIZE (256*1024)
#define ROOTTREESIZE (32*1024*1024)
......@@ -282,8 +286,8 @@ extern char __init_begin, __init_end;
* paging_init() continues the virtual memory environment setup which
* was begun by the code in arch/head.S.
*/
unsigned long __init paging_init(unsigned long start_mem,
unsigned long end_mem)
__initfunc(unsigned long paging_init(unsigned long start_mem,
unsigned long end_mem))
{
int chunk;
unsigned long mem_avail = 0;
......@@ -392,7 +396,7 @@ unsigned long __init paging_init(unsigned long start_mem,
return PAGE_ALIGN(free_area_init(start_mem, end_mem));
}
void __init mem_init(unsigned long start_mem, unsigned long end_mem)
__initfunc(void mem_init(unsigned long start_mem, unsigned long end_mem))
{
int codepages = 0;
int datapages = 0;
......@@ -443,7 +447,7 @@ void __init mem_init(unsigned long start_mem, unsigned long end_mem)
/* insert pointer tables allocated so far into the tablelist */
init_pointer_table((unsigned long)kernel_pg_dir);
for (i = 0; i < PTRS_PER_PGD; i++) {
if (pgd_val(kernel_pg_dir[i]))
if (pgd_present(kernel_pg_dir[i]))
init_pointer_table(pgd_page(kernel_pg_dir[i]));
}
......
......@@ -116,6 +116,14 @@ void *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag)
if (!size || size > physaddr + size)
return NULL;
#ifdef CONFIG_AMIGA
if (MACH_IS_AMIGA) {
if ((physaddr >= 0x40000000) && (physaddr + size < 0x60000000)
&& (cacheflag == IOMAP_NOCACHE_SER))
return (void *)physaddr;
}
#endif
#ifdef DEBUG
printk("ioremap: 0x%lx,0x%lx(%d) - ", physaddr, size, cacheflag);
#endif
......@@ -174,7 +182,7 @@ void *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag)
}
}
while (size > 0) {
while ((long)size > 0) {
#ifdef DEBUG
if (!(virtaddr & (PTRTREESIZE-1)))
printk ("\npa=%#lx va=%#lx ", physaddr, virtaddr);
......@@ -187,7 +195,7 @@ void *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag)
}
if (CPU_IS_020_OR_030) {
pmd_dir->pmd[(virtaddr/PTRTREESIZE)&-16] = physaddr;
pmd_dir->pmd[(virtaddr/PTRTREESIZE) & 15] = physaddr;
physaddr += PTRTREESIZE;
virtaddr += PTRTREESIZE;
size -= PTRTREESIZE;
......@@ -217,7 +225,14 @@ void *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag)
*/
void iounmap(void *addr)
{
#ifdef CONFIG_AMIGA
if ((!MACH_IS_AMIGA) ||
(((unsigned long)addr < 0x40000000) ||
((unsigned long)addr > 0x60000000)))
free_io_area(addr);
#else
free_io_area(addr);
#endif
}
/*
......@@ -232,7 +247,7 @@ void __iounmap(void *addr, unsigned long size)
pmd_t *pmd_dir;
pte_t *pte_dir;
while (size > 0) {
while ((long)size > 0) {
pgd_dir = pgd_offset_k(virtaddr);
if (pgd_bad(*pgd_dir)) {
printk("iounmap: bad pgd(%08lx)\n", pgd_val(*pgd_dir));
......@@ -242,7 +257,7 @@ void __iounmap(void *addr, unsigned long size)
pmd_dir = pmd_offset(pgd_dir, virtaddr);
if (CPU_IS_020_OR_030) {
int pmd_off = (virtaddr/PTRTREESIZE) & -16;
int pmd_off = (virtaddr/PTRTREESIZE) & 15;
if ((pmd_dir->pmd[pmd_off] & _DESCTYPE_MASK) == _PAGE_PRESENT) {
pmd_dir->pmd[pmd_off] = 0;
......@@ -308,7 +323,7 @@ void kernel_set_cachemode(void *addr, unsigned long size, int cmode)
}
}
while (size > 0) {
while ((long)size > 0) {
pgd_dir = pgd_offset_k(virtaddr);
if (pgd_bad(*pgd_dir)) {
printk("iocachemode: bad pgd(%08lx)\n", pgd_val(*pgd_dir));
......@@ -318,7 +333,7 @@ void kernel_set_cachemode(void *addr, unsigned long size, int cmode)
pmd_dir = pmd_offset(pgd_dir, virtaddr);
if (CPU_IS_020_OR_030) {
int pmd_off = (virtaddr/PTRTREESIZE) & -16;
int pmd_off = (virtaddr/PTRTREESIZE) & 15;
if ((pmd_dir->pmd[pmd_off] & _DESCTYPE_MASK) == _PAGE_PRESENT) {
pmd_dir->pmd[pmd_off] = (pmd_dir->pmd[pmd_off] &
......
......@@ -11,6 +11,7 @@
#include <linux/types.h>
#include <linux/malloc.h>
#include <linux/init.h>
#include <linux/pagemap.h>
#include <asm/setup.h>
#include <asm/segment.h>
......@@ -93,12 +94,11 @@ typedef struct page ptable_desc;
static ptable_desc ptable_list = { &ptable_list, &ptable_list };
#define PD_MARKBITS(dp) (*(unsigned char *)&(dp)->offset)
#define PD_PAGE(dp) (PAGE_OFFSET + ((dp)->map_nr << PAGE_SHIFT))
#define PAGE_PD(page) ((ptable_desc *)&mem_map[MAP_NR(page)])
#define PTABLE_SIZE (PTRS_PER_PMD * sizeof(pmd_t))
void __init init_pointer_table(unsigned long ptable)
__initfunc(void init_pointer_table(unsigned long ptable))
{
ptable_desc *dp;
unsigned long page = ptable & PAGE_MASK;
......@@ -166,7 +166,7 @@ pmd_t *get_pointer_table (void)
(dp->next = last->next)->prev = dp;
(dp->prev = last)->next = dp;
}
return (pmd_t *) (PD_PAGE(dp) + off);
return (pmd_t *) (page_address(dp) + off);
}
int free_pointer_table (pmd_t *ptable)
......@@ -215,8 +215,8 @@ static unsigned long transp_transl_matches( unsigned long regval,
/* function code match? */
base = (regval >> 4) & 7;
mask = ~(regval & 7);
if ((SUPER_DATA & mask) != (base & mask))
return( 0 );
if (((SUPER_DATA ^ base) & mask) != 0)
return 0;
}
else {
/* must not be user-only */
......@@ -226,8 +226,8 @@ static unsigned long transp_transl_matches( unsigned long regval,
/* address match? */
base = regval & 0xff000000;
mask = ~((regval << 8) & 0xff000000);
return( (vaddr & mask) == (base & mask) );
mask = ~(regval << 8) & 0xff000000;
return ((vaddr ^ base) & mask) == 0;
}
#ifndef CONFIG_SINGLE_MEMORY_CHUNK
......
/*
* arch/m68k/mvme147/147ints.c
*
* Copyright (C) 1997 Richard Hirst [richard@sleepie.demon.co.uk]
*
* based on amiints.c -- Amiga Linux interrupt handling code
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file README.legal in the main directory of this archive
* for more details.
*
*/
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <asm/ptrace.h>
#include <asm/system.h>
#include <asm/irq.h>
#include <asm/traps.h>
static void mvme147_defhand (int irq, void *dev_id, struct pt_regs *fp);
/*
* This should ideally be 4 elements only, for speed.
*/
static struct {
void (*handler)(int, void *, struct pt_regs *);
unsigned long flags;
void *dev_id;
const char *devname;
unsigned count;
} irq_tab[256];
/*
* void mvme147_init_IRQ (void)
*
* Parameters: None
*
* Returns: Nothing
*
* This function is called during kernel startup to initialize
* the mvme147 IRQ handling routines.
*/
void mvme147_init_IRQ (void)
{
int i;
for (i = 0; i < 256; i++) {
irq_tab[i].handler = mvme147_defhand;
irq_tab[i].flags = IRQ_FLG_STD;
irq_tab[i].dev_id = NULL;
irq_tab[i].devname = NULL;
irq_tab[i].count = 0;
}
}
int mvme147_request_irq(unsigned int irq,
void (*handler)(int, void *, struct pt_regs *),
unsigned long flags, const char *devname, void *dev_id)
{
if (irq > 255) {
printk("%s: Incorrect IRQ %d from %s\n", __FUNCTION__, irq, devname);
return -ENXIO;
}
if (!(irq_tab[irq].flags & IRQ_FLG_STD)) {
if (irq_tab[irq].flags & IRQ_FLG_LOCK) {
printk("%s: IRQ %d from %s is not replaceable\n",
__FUNCTION__, irq, irq_tab[irq].devname);
return -EBUSY;
}
if (flags & IRQ_FLG_REPLACE) {
printk("%s: %s can't replace IRQ %d from %s\n",
__FUNCTION__, devname, irq, irq_tab[irq].devname);
return -EBUSY;
}
}
irq_tab[irq].handler = handler;
irq_tab[irq].flags = flags;
irq_tab[irq].dev_id = dev_id;
irq_tab[irq].devname = devname;
return 0;
}
void mvme147_free_irq(unsigned int irq, void *dev_id)
{
if (irq > 255) {
printk("%s: Incorrect IRQ %d\n", __FUNCTION__, irq);
return;
}
if (irq_tab[irq].dev_id != dev_id)
printk("%s: Removing probably wrong IRQ %d from %s\n",
__FUNCTION__, irq, irq_tab[irq].devname);
irq_tab[irq].handler = mvme147_defhand;
irq_tab[irq].flags = IRQ_FLG_STD;
irq_tab[irq].dev_id = NULL;
irq_tab[irq].devname = NULL;
}
void mvme147_process_int (unsigned long vec, struct pt_regs *fp)
{
if (vec > 255)
printk ("mvme147_process_int: Illegal vector %ld\n", vec);
else
{
irq_tab[vec].count++;
irq_tab[vec].handler(vec, irq_tab[vec].dev_id, fp);
}
}
int mvme147_get_irq_list (char *buf)
{
int i, len = 0;
for (i = 0; i < 256; i++) {
if (irq_tab[i].count)
len += sprintf (buf+len, "Vec 0x%02x: %8d %s\n",
i, irq_tab[i].count,
irq_tab[i].devname ? irq_tab[i].devname : "free");
}
return len;
}
static void mvme147_defhand (int irq, void *dev_id, struct pt_regs *fp)
{
printk ("Unknown interrupt 0x%02x\n", irq);
}
void mvme147_enable_irq (unsigned int irq)
{
}
void mvme147_disable_irq (unsigned int irq)
{
}
#
# Makefile for Linux arch/m68k/mvme147 source directory
#
# Note! Dependencies are done automagically by 'make dep', which also
# removes any old dependencies. DON'T put your own dependencies here
# unless it's something special (ie not a .c file).
#
O_TARGET := mvme147.o
O_OBJS := config.o 147ints.o
include $(TOPDIR)/Rules.make
/*
* arch/m68k/mvme147/config.c
*
* Copyright (C) 1996 Dave Frascone [chaos@mindspring.com]
* Cloned from Richard Hirst [richard@sleepie.demon.co.uk]
*
* Based on:
*
* Copyright (C) 1993 Hamish Macdonald
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file README.legal in the main directory of this archive
* for more details.
*/
#include <linux/config.h>
#include <stdarg.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/kd.h>
#include <linux/tty.h>
#include <linux/console.h>
#include <linux/linkage.h>
#include <linux/init.h>
#include <linux/major.h>
#include <asm/system.h>
#include <asm/pgtable.h>
#include <asm/setup.h>
#include <asm/irq.h>
#include <asm/traps.h>
#include <asm/machdep.h>
#include <asm/mvme147hw.h>
extern void mvme147_process_int (int level, struct pt_regs *regs);
extern void mvme147_init_IRQ (void);
extern void mvme147_free_irq (unsigned int, void *);
extern int mvme147_get_irq_list (char *);
extern void mvme147_enable_irq (unsigned int);
extern void mvme147_disable_irq (unsigned int);
static void mvme147_get_model(char *model);
static int mvme147_get_hardware_list(char *buffer);
extern int mvme147_request_irq (unsigned int irq, void (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id);
extern void mvme147_sched_init(void (*handler)(int, void *, struct pt_regs *));
extern int mvme147_keyb_init(void);
extern int mvme147_kbdrate (struct kbd_repeat *);
extern unsigned long mvme147_gettimeoffset (void);
extern void mvme147_gettod (int *year, int *mon, int *day, int *hour,
int *min, int *sec);
extern int mvme147_hwclk (int, struct hwclk_time *);
extern int mvme147_set_clock_mmss (unsigned long);
extern void mvme147_check_partition (struct gendisk *hd, unsigned int dev);
extern void mvme147_reset (void);
extern void mvme147_waitbut(void);
static int bcd2int (unsigned char b);
/* Save tick handler routine pointer, will point to do_timer() in
* kernel/sched.c, called via mvme147_process_int() */
void (*tick_handler)(int, void *, struct pt_regs *);
int mvme147_kbdrate (struct kbd_repeat *k)
{
return 0;
}
void mvme147_reset()
{
printk ("\r\n\nCalled mvme147_reset\r\n");
m147_pcc->watchdog = 0x0a; /* Clear timer */
m147_pcc->watchdog = 0xa5; /* Enable watchdog - 100ms to reset */
while (1)
;
}
static void mvme147_get_model(char *model)
{
sprintf(model, "Motorola MVME147");
}
static int mvme147_get_hardware_list(char *buffer)
{
*buffer = '\0';
return 0;
}
__initfunc(void config_mvme147(void))
{
mach_sched_init = mvme147_sched_init;
mach_keyb_init = mvme147_keyb_init;
mach_kbdrate = mvme147_kbdrate;
mach_init_IRQ = mvme147_init_IRQ;
mach_gettimeoffset = mvme147_gettimeoffset;
mach_gettod = mvme147_gettod;
mach_hwclk = mvme147_hwclk;
mach_set_clock_mmss = mvme147_set_clock_mmss;
mach_reset = mvme147_reset;
mach_free_irq = mvme147_free_irq;
mach_process_int = mvme147_process_int;
mach_get_irq_list = mvme147_get_irq_list;
mach_request_irq = mvme147_request_irq;
enable_irq = mvme147_enable_irq;
disable_irq = mvme147_disable_irq;
mach_get_model = mvme147_get_model;
mach_get_hardware_list = mvme147_get_hardware_list;
}
/* Using pcc tick timer 1 */
static void mvme147_timer_int (int irq, void *dev_id, struct pt_regs *fp)
{
m147_pcc->t1_int_cntrl = PCC_TIMER_INT_CLR;
m147_pcc->t1_int_cntrl = PCC_INT_ENAB|PCC_LEVEL_TIMER1;
tick_handler(irq, dev_id, fp);
}
void mvme147_sched_init (void (*timer_routine)(int, void *, struct pt_regs *))
{
tick_handler = timer_routine;
request_irq (PCC_IRQ_TIMER1, mvme147_timer_int,
IRQ_FLG_REPLACE, "timer 1", NULL);
/* Init the clock with a value */
/* our clock goes off every 6.25us */
m147_pcc->t1_preload = PCC_TIMER_PRELOAD;
m147_pcc->t1_cntrl = 0x0; /* clear timer */
m147_pcc->t1_cntrl = 0x3; /* start timer */
m147_pcc->t1_int_cntrl = PCC_TIMER_INT_CLR; /* clear pending ints */
m147_pcc->t1_int_cntrl = PCC_INT_ENAB|PCC_LEVEL_TIMER1;
}
/* This is always executed with interrupts disabled. */
/* XXX There are race hazards in this code XXX */
unsigned long mvme147_gettimeoffset (void)
{
volatile unsigned short *cp = (volatile unsigned short *)0xfffe1012;
unsigned short n;
n = *cp;
while (n != *cp)
n = *cp;
n -= PCC_TIMER_PRELOAD;
return (unsigned long)n * 25 / 4;
}
extern void mvme147_gettod (int *year, int *mon, int *day, int *hour,
int *min, int *sec)
{
m147_rtc->ctrl = RTC_READ;
*year = bcd2int (m147_rtc->bcd_year);
*mon = bcd2int (m147_rtc->bcd_mth);
*day = bcd2int (m147_rtc->bcd_dom);
*hour = bcd2int (m147_rtc->bcd_hr);
*min = bcd2int (m147_rtc->bcd_min);
*sec = bcd2int (m147_rtc->bcd_sec);
m147_rtc->ctrl = 0;
}
static int bcd2int (unsigned char b)
{
return ((b>>4)*10 + (b&15));
}
int mvme147_hwclk(int op, struct hwclk_time *t)
{
return 0;
}
int mvme147_set_clock_mmss (unsigned long nowtime)
{
return 0;
}
int mvme147_keyb_init (void)
{
return 0;
}
/*------------------- Serial console stuff ------------------------*/
void m147_scc_write(struct console *co, const char *str, unsigned cnt);
void mvme147_init_console_port (struct console *co, int cflag)
{
co->write = m147_scc_write;
}
static void scc_delay (void)
{
int n;
volatile int trash;
for (n = 0; n < 20; n++)
trash = n;
}
static void scc_write (char ch)
{
volatile char *p = (volatile char *)M147_SCC_A_ADDR;
do {
scc_delay();
}
while (!(*p & 4));
scc_delay();
*p = 8;
scc_delay();
*p = ch;
}
void m147_scc_write (struct console *co, const char *str, unsigned count)
{
unsigned long flags;
save_flags(flags);
cli();
while (count--)
{
if (*str == '\n')
scc_write ('\r');
scc_write (*str++);
}
restore_flags(flags);
}
......@@ -335,10 +335,10 @@ void mvme16x_init_console_port (struct console *co, int cflag)
static void scc_delay (void)
{
int n;
char i;
volatile int trash;
for (n = 0; n < 20; n++)
i = *(volatile char *)0;
trash = n;
}
static void scc_write (char ch)
......
#
# Makefile for Linux arch/m68k/q40 source directory
#
# Note! Dependencies are done automagically by 'make dep', which also
# removes any old dependencies. DON'T put your own dependencies here
# unless it's something special (ie not a .c file).
#
# Note 2! The CFLAGS definitions are now in the main makefile...
O_TARGET := q40.o
O_OBJS := config.o q40ints.o
include $(TOPDIR)/Rules.make
Linux for the Q40
=================
You may try http://www.geocities.com/SiliconValley/Bay/2602/ for
some up to date information. Booter and other tools will be also
available from this place and ftp.uni-erlangen.de/linux/680x0/q40/
and mirrors.
Hints to documentation usually refer to the linux source tree in
/usr/src/linux unless URL given.
It seems IRQ unmasking can't be safely done on a Q40. Autoprobing is
not yet implemented - do not try it! (See below)
For a list of kernel commandline options read the documentation for the
particular device drivers.
The floppy imposes a very high interrupt load on the CPU, approx 30K/s.
When something blocks interrupts (HD) it will loose some of them, so far
this is not known to have caused any data loss. On hihgly loaded systems
it can make the floppy very slow. Other Q40 OS' simply poll the floppy
for this reason - something that can't be done in Linux.
Only possible cure is getting a 82072 contoler with fifo instead of
the 8272A
drivers used by the Q40, appart from the very obvious (console etc.):
drivers/char/q40_keyb.c # use PC keymaps for national keyboards
serial.c # normal PC driver - any speed
lp.c # printer driver
char/joystick/* # most of this should work
block/q40ide.c # startup for ide
ide* # see Documentation/ide.txt
floppy.c # normal PC driver, DMA emu in asm/floppy.h
# and arch/m68k/kernel/entry.S
# see drivers/block/README.fd
video/q40fb.c
misc/parport_pc.c
Various other PC drivers can be enabled simply by adding them to
arch/m68k/config.in, especially 8 bit devices should be without any
problems. For cards using 16bit io/mem more care is required, like
checking byteorder issues, hacking memcpy_*_io etc.
Debugging
=========
Upon startup the kernel will usually output "ABCQGHIJ" into the SRAM,
preceded by the booter signature. This is a trace just in case something
went wrong during earliest setup stages.
*Changed* to preserve SRAM contents by default, this is only done when
requested - SRAM must start with '%LX$' signature to do this. '-d' option
to 'lxx' loader enables this.
SRAM can also be used as additional console device, use debug=mem.
This will save kernel startup msgs into SRAM, the screen will display
only the penguin - and shell prompt if it gets that far..
Serial console works and can also be used for debugging, provided serial
initialisation works.
Most problems seem to be caused by fawlty or badly configured io-cards or
harddrives anyway..there are so many things that can go wrong here.
Make sure to configure the parallel port as SPP for first testing..the
Q40 may have trouble with parallel interrupts.
Q40 Hardware Description
========================
This is just an overview, see asm-m68k/* for details ask if you have any
questions.
The Q40 consists of a 68040@40 MHz, 1MB video RAM, up to 32MB RAM, AT-style
keyboard interface, 1 Programmable LED, 2 8bit DACs and up to 1MB ROM, 1MB
shadow ROM.
Most interfacing like floppy, hd, serial, parallel ports is done via ISA
slots. The ISA io and mem range is mapped (sparse&byteswapped!) into separate
regions of the memory.
The main interrupt register IIRQ_REG will indicate whether an IRQ was internal
or from some ISA devices, EIRQ_REG can distinguish up to 8 ISA IRQs.
The Q40 custom chip is programmable to provide 2 periodic timers:
- 50 or 200 Hz - level 2, !!THIS CANT BE DISABLED!!
- 10 or 20 KHz - level 4 (and possibly 6 - hardware decoding..)
Linux uses the 200 Hz interrupt for timer and beep by default.
Interrupts
==========
q40 master chip handles only level triggered interrupts :-((
further limitation is no disabling etc. Unless someone finds
some ingenious clue this means autoprobing will never work.
Parallel port interrupts cause most trouble..
IRQ sharing is not yet implemented.
Keyboard
========
q40 receives AT make/break codes from the keyboard, these are translated to
the PC scancodes x86 Linux uses. So by theory every national keyboard should
work just by loading the apropriate x86 keytable - see any national-HOWTO.
Unfortunately the AT->PC translation isn't quite trivial and even worse, my
documentation of it is absolutely minimal - thus some exotic keys may not
behave exactly as expected.
There is still hope that it can be fixed completely though. If you encounter
problems, email me idealy this:
- exact keypress/release sequence
- 'showkey -s' run on q40, non-X session
- 'showkey -s' run on a PC, non-X session
- AT codes as displayed by the q40 debuging ROM
btw if the showkey output from PC and Q40 doesn't differ then you have some
classic configuration problem - don't send me anything in this case
This diff is collapsed.
/*
* arch/m68k/q40/q40ints.c
*
* Copyright (C) 1999 Richard Zidlicky
*
* 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.
*
* losely based on bvme6000ints.c
*
*/
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <asm/ptrace.h>
#include <asm/system.h>
#include <asm/irq.h>
#include <asm/traps.h>
#include <asm/q40_master.h>
#include <asm/q40ints.h>
/*
* Q40 IRQs are defined as follows:
* 3,4,5,6,7,10,11,14,15 : ISA dev IRQs
* 16-31: reserved
* 32 : keyboard int
* 33 : frame int (50 Hz periodic timer)
* 34 : sample int (10/20 KHz periodic timer)
*
*/
extern int ints_inited;
void q40_irq2_handler (int, void *, struct pt_regs *fp);
extern void (*q40_sys_default_handler[]) (int, void *, struct pt_regs *); /* added just for debugging */
static void q40_defhand (int irq, void *dev_id, struct pt_regs *fp);
static void sys_default_handler(int lev, void *dev_id, struct pt_regs *regs);
/*
* This should ideally be 4 elements only, for speed.
*/
#define DEVNAME_SIZE 24
static struct {
void (*handler)(int, void *, struct pt_regs *);
unsigned long flags;
void *dev_id;
char devname[DEVNAME_SIZE];
unsigned count;
} irq_tab[Q40_IRQ_MAX+1];
/*
* void q40_init_IRQ (void)
*
* Parameters: None
*
* Returns: Nothing
*
* This function is called during kernel startup to initialize
* the q40 IRQ handling routines.
*/
void q40_init_IRQ (void)
{
int i;
for (i = 0; i <= Q40_IRQ_MAX; i++) {
irq_tab[i].handler = q40_defhand;
irq_tab[i].flags = IRQ_FLG_STD;
irq_tab[i].dev_id = NULL;
irq_tab[i].devname[0] = 0;
irq_tab[i].count = 0;
}
/* setup handler for ISA ints */
sys_request_irq(IRQ2,q40_irq2_handler, IRQ_FLG_LOCK, "q40 ISA and master chip", NULL);
/* now enable some ints.. */
#if 0 /* has been abandoned */
master_outb(1,SER_ENABLE_REG);
#endif
master_outb(1,EXT_ENABLE_REG);
/* would be spurious ints by now, q40kbd_init_hw() does that */
master_outb(0,KEY_IRQ_ENABLE_REG);
}
int q40_request_irq(unsigned int irq,
void (*handler)(int, void *, struct pt_regs *),
unsigned long flags, const char *devname, void *dev_id)
{
/*printk("q40_request_irq %d, %s\n",irq,devname);*/
if (irq > Q40_IRQ_MAX || (irq>15 && irq<32)) {
printk("%s: Incorrect IRQ %d from %s\n", __FUNCTION__, irq, devname);
return -ENXIO;
}
/* test for ISA ints not implemented by HW */
if (irq<15)
{
switch (irq){
case 1: case 2: case 8: case 9:
case 12: case 13:
printk("%s: ISA IRQ %d from %s not implemented by HW\n", __FUNCTION__, irq, devname);
return -ENXIO;
default:
}
}
if (irq<Q40_IRQ_TIMER)
{
if (irq==11) {
printk("warning IRQ 10 and 11 not distinguishable\n");
irq=10;
}
if (!(irq_tab[irq].flags & IRQ_FLG_STD))
{
if (irq_tab[irq].flags & IRQ_FLG_LOCK)
{
printk("%s: IRQ %d from %s is not replaceable\n",
__FUNCTION__, irq, irq_tab[irq].devname);
return -EBUSY;
}
if (flags & IRQ_FLG_REPLACE)
{
printk("%s: %s can't replace IRQ %d from %s\n",
__FUNCTION__, devname, irq, irq_tab[irq].devname);
return -EBUSY;
}
}
/*printk("IRQ %d set to handler %p\n",irq,handler);*/
irq_tab[irq].handler = handler;
irq_tab[irq].flags = flags;
irq_tab[irq].dev_id = dev_id;
strncpy(irq_tab[irq].devname,devname,DEVNAME_SIZE);
return 0;
}
else {
/* Q40_IRQ_TIMER :somewhat special actions required here ..*/
sys_request_irq(4,handler,flags,devname,dev_id);
sys_request_irq(6,handler,flags,devname,dev_id);
return 0;
}
}
void q40_free_irq(unsigned int irq, void *dev_id)
{
if (irq > Q40_IRQ_MAX || (irq>15 && irq<32)) {
printk("%s: Incorrect IRQ %d, dev_id %x \n", __FUNCTION__, irq, (unsigned)dev_id);
return;
}
/* test for ISA ints not implemented by HW */
if (irq<15) {
switch (irq){
case 1: case 2: case 8: case 9:
case 12: case 13:
printk("%s: ISA IRQ %d from %x illegal\n", __FUNCTION__, irq, (unsigned)dev_id);
return;
default:
}
}
if (irq<Q40_IRQ_TIMER){
if (irq==11) irq=10;
if (irq_tab[irq].dev_id != dev_id)
printk("%s: Removing probably wrong IRQ %d from %s\n",
__FUNCTION__, irq, irq_tab[irq].devname);
irq_tab[irq].handler = q40_defhand;
irq_tab[irq].flags = IRQ_FLG_STD;
irq_tab[irq].dev_id = NULL;
/* irq_tab[irq].devname = NULL; */
} else { /* == Q40_IRQ_TIMER */
sys_free_irq(4,dev_id);
sys_free_irq(6,dev_id);
}
}
#if 1
void q40_process_int (int level, struct pt_regs *fp)
{
printk("unexpected interrupt %x\n",level);
}
#endif
/*
* tables to translate bits into IRQ numbers
* it is a good idea to order the entries by priority
*
*/
struct IRQ_TABLE{ unsigned mask; int irq ;};
static struct IRQ_TABLE iirqs[]={
{IRQ_FRAME_MASK,Q40_IRQ_FRAME},
{IRQ_KEYB_MASK,Q40_IRQ_KEYBOARD},
{0,0}};
static struct IRQ_TABLE eirqs[]={
{IRQ3_MASK,3}, /* ser 1 */
{IRQ4_MASK,4}, /* ser 2 */
{IRQ14_MASK,14}, /* IDE 1 */
{IRQ15_MASK,15}, /* IDE 2 */
{IRQ6_MASK,6}, /* floppy */
{IRQ7_MASK,7}, /* par */
{IRQ5_MASK,5},
{IRQ10_MASK,10},
{0,0}};
/* complaiun only this many times about spurious ints : */
static int ccleirq=60; /* ISA dev IRQ's*/
static int cclirq=60; /* internal */
/* FIX: add IRQ_INPROGRESS,mask,unmask,probing.... */
void q40_irq2_handler (int vec, void *devname, struct pt_regs *fp)
{
/* got level 2 interrupt, dispatch to ISA or keyboard IRQs */
unsigned mir=master_inb(IIRQ_REG);
unsigned mer;
int irq,i;
/*
* more than 1 bit might be set, must handle atmost 1 int source,
* - handle only those with explicitly set handler
*/
if ((mir&IRQ_SER_MASK) || (mir&IRQ_EXT_MASK))
{
/* some ISA dev caused the int */
mer=master_inb(EIRQ_REG);
for (i=0; eirqs[i].mask; i++)
{
if (mer&(eirqs[i].mask))
{
irq=eirqs[i].irq;
irq_tab[irq].count++;
if (irq_tab[irq].handler == q40_defhand )
continue; /* ignore uninited INTs :-( */
irq_tab[irq].handler(irq,irq_tab[irq].dev_id,fp);
return;
}
}
if (ccleirq>0)
printk("ISA interrupt from unknown source? EIRQ_REG = %x\n",mer),ccleirq--;
}
else
{
/* internal */
for (i=0; iirqs[i].mask; i++)
{
if (mir&(iirqs[i].mask))
{
irq=iirqs[i].irq;
irq_tab[irq].count++;
if (irq_tab[irq].handler == q40_defhand )
continue; /* ignore uninited INTs :-( */
irq_tab[irq].handler(irq,irq_tab[irq].dev_id,fp);
return;
}
}
if (cclirq>0)
printk("internal level 2 interrupt from unknown source ? IIRQ_REG=%x\n",mir),cclirq--;
}
}
int q40_get_irq_list (char *buf)
{
int i, len = 0;
for (i = 0; i <= Q40_IRQ_MAX; i++) {
if (irq_tab[i].count)
len += sprintf (buf+len, "Vec 0x%02x: %8d %s%s\n",
i, irq_tab[i].count,
irq_tab[i].devname[0] ? irq_tab[i].devname : "?",
irq_tab[i].handler == q40_defhand ?
" (now unassigned)" : "");
}
return len;
}
static void q40_defhand (int irq, void *dev_id, struct pt_regs *fp)
{
#if 0
printk ("Unknown q40 interrupt 0x%02x\n", irq);
#endif
}
static void sys_default_handler(int lev, void *dev_id, struct pt_regs *regs)
{
#if 0
if (ints_inited)
#endif
printk ("Uninitialised interrupt level %d\n", lev);
#if 0
else
printk ("Interrupt before interrupt initialisation\n");
#endif
}
void (*q40_sys_default_handler[SYS_IRQS]) (int, void *, struct pt_regs *) = {
sys_default_handler,sys_default_handler,sys_default_handler,sys_default_handler,
sys_default_handler,sys_default_handler,sys_default_handler,sys_default_handler
};
void q40_enable_irq (unsigned int irq)
{
}
void q40_disable_irq (unsigned int irq)
{
}
unsigned long q40_probe_irq_on (void)
{
printk("sorry, irq probing not yet implemented - reconfigure the driver to avoid this\n");
return 0;
}
int q40_probe_irq_off (unsigned long irqs)
{
return -1;
}
#
# Makefile for Linux arch/m68k/sun3x source directory
#
# Note! Dependencies are done automagically by 'make dep', which also
# removes any old dependencies. DON'T put your own dependencies here
# unless it's something special (ie not a .c file).
#
# Note 2! The CFLAGS definitions are now in the main makefile...
O_TARGET := sun3x.o
O_OBJS := config.o time.o dvma.o sbus.o
OX_OBJS :=
include $(TOPDIR)/Rules.make
/*
* Setup kernel for a Sun3x machine
*
* (C) 1999 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
*
* based on code from Oliver Jowett <oliver@jowett.manawatu.gen.nz>
*/
#include <linux/types.h>
#include <linux/mm.h>
#include <linux/console.h>
#include <linux/init.h>
#include <asm/system.h>
#include <asm/machdep.h>
#include <asm/irq.h>
#include <asm/sun3x.h>
#include "time.h"
static volatile unsigned char *sun3x_intreg = (unsigned char *)SUN3X_INTREG;
extern int serial_console;
void sun3x_halt(void)
{
/* Disable interrupts */
cli();
/* we can't drop back to PROM, so we loop here */
for (;;);
}
void sun3x_reboot(void)
{
/* This never returns, don't bother saving things */
cli();
/* no idea, whether this works */
asm ("reset");
}
__initfunc(int sun3x_keyb_init(void))
{
return 0;
}
int sun3x_kbdrate(struct kbd_repeat *r)
{
return 0;
}
void sun3x_kbd_leds(unsigned int i)
{
}
static void sun3x_badint (int irq, void *dev_id, struct pt_regs *fp)
{
printk ("received spurious interrupt %d\n",irq);
num_spurious += 1;
}
void (*sun3x_default_handler[SYS_IRQS])(int, void *, struct pt_regs *) = {
sun3x_badint, sun3x_badint, sun3x_badint, sun3x_badint,
sun3x_badint, sun3x_badint, sun3x_badint, sun3x_badint
};
void sun3x_enable_irq(unsigned int irq)
{
*sun3x_intreg |= (1 << irq);
}
void sun3x_disable_irq(unsigned int irq)
{
*sun3x_intreg &= ~(1 << irq);
}
__initfunc(void sun3x_init_IRQ(void))
{
/* disable all interrupts initially */
*sun3x_intreg = 1; /* master enable only */
}
int sun3x_get_irq_list(char *buf)
{
return 0;
}
/*
* Setup the sun3x configuration info
*/
__initfunc(void config_sun3x(void))
{
mach_get_irq_list = sun3x_get_irq_list;
mach_max_dma_address = 0xffffffff; /* we can DMA anywhere, whee */
mach_keyb_init = sun3x_keyb_init;
mach_kbdrate = sun3x_kbdrate;
mach_kbd_leds = sun3x_kbd_leds;
mach_sched_init = sun3x_sched_init;
mach_init_IRQ = sun3x_init_IRQ;
enable_irq = sun3x_enable_irq;
disable_irq = sun3x_disable_irq;
mach_request_irq = sys_request_irq;
mach_free_irq = sys_free_irq;
mach_default_handler = &sun3x_default_handler;
mach_gettimeoffset = sun3x_gettimeoffset;
mach_reset = sun3x_reboot;
mach_gettod = sun3x_gettod;
switch (*(unsigned char *)SUN3X_EEPROM_CONS) {
case 0x10:
serial_console = 1;
conswitchp = NULL;
break;
case 0x11:
serial_console = 2;
conswitchp = NULL;
break;
default:
serial_console = 0;
conswitchp = &dummy_con;
break;
}
}
/*
* Virtual DMA allocation
*
* (C) 1999 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/bitops.h>
#include <linux/mm.h>
#include <asm/sun3x.h>
#include <asm/dvma.h>
#include <asm/io.h>
#include <asm/page.h>
/* IOMMU support */
#define IOMMU_ENTRIES 2048
#define IOMMU_ADDR_MASK 0x03ffe000
#define IOMMU_CACHE_INHIBIT 0x00000040
#define IOMMU_FULL_BLOCK 0x00000020
#define IOMMU_MODIFIED 0x00000010
#define IOMMU_USED 0x00000008
#define IOMMU_WRITE_PROTECT 0x00000004
#define IOMMU_DT_MASK 0x00000003
#define IOMMU_DT_INVALID 0x00000000
#define IOMMU_DT_VALID 0x00000001
#define IOMMU_DT_BAD 0x00000002
#define DVMA_PAGE_SHIFT 13
#define DVMA_PAGE_SIZE (1UL << DVMA_PAGE_SHIFT)
#define DVMA_PAGE_MASK (~(DVMA_PAGE_SIZE-1))
static volatile unsigned long *iommu_pte = (unsigned long *)SUN3X_IOMMU;
static unsigned long iommu_use[IOMMU_ENTRIES];
static unsigned long iommu_bitmap[IOMMU_ENTRIES/32];
#define dvma_entry_paddr(index) (iommu_pte[index] & IOMMU_ADDR_MASK)
#define dvma_entry_vaddr(index,paddr) ((index << DVMA_PAGE_SHIFT) | \
(paddr & (DVMA_PAGE_SIZE-1)))
#define dvma_entry_set(index,addr) (iommu_pte[index] = \
(addr & IOMMU_ADDR_MASK) | \
IOMMU_DT_VALID)
#define dvma_entry_clr(index) (iommu_pte[index] = IOMMU_DT_INVALID)
#define dvma_entry_use(index) (iommu_use[index])
#define dvma_entry_inc(index) (iommu_use[index]++)
#define dvma_entry_dec(index) (iommu_use[index]--)
#define dvma_entry_hash(addr) ((addr >> DVMA_PAGE_SHIFT) ^ \
((addr & 0x03c00000) >> \
(DVMA_PAGE_SHIFT+4)))
#define dvma_map iommu_bitmap
#define dvma_map_size (IOMMU_ENTRIES/2)
#define dvma_slow_offset (IOMMU_ENTRIES/2)
#define dvma_is_slow(addr) ((addr) & \
(dvma_slow_offset << DVMA_PAGE_SHIFT))
static int fixed_dvma;
void __init dvma_init(void)
{
unsigned long tmp;
if ((unsigned long)high_memory < (IOMMU_ENTRIES << DVMA_PAGE_SHIFT)) {
printk ("Sun3x fixed DVMA mapping\n");
fixed_dvma = 1;
for (tmp = 0; tmp < (unsigned long)high_memory; tmp += DVMA_PAGE_SIZE)
dvma_entry_set (tmp >> DVMA_PAGE_SHIFT, virt_to_phys((void *)tmp));
fixed_dvma = 1;
} else {
printk ("Sun3x variable DVMA mapping\n");
for (tmp = 0; tmp < IOMMU_ENTRIES; tmp++)
dvma_entry_clr (tmp);
fixed_dvma = 0;
}
}
unsigned long dvma_slow_alloc (unsigned long paddr, int npages)
{
int scan, base;
scan = 0;
for (;;) {
scan = find_next_zero_bit(dvma_map, dvma_map_size, scan);
if ((base = scan) + npages > dvma_map_size) {
printk ("dvma_slow_alloc failed for %d pages\n",npages);
return 0;
}
for (;;) {
if (scan >= base + npages) goto found;
if (test_bit(scan, dvma_map)) break;
scan++;
}
}
found:
for (scan = base; scan < base+npages; scan++) {
dvma_entry_set(scan+dvma_slow_offset, paddr);
paddr += DVMA_PAGE_SIZE;
set_bit(scan, dvma_map);
}
return (dvma_entry_vaddr((base+dvma_slow_offset),paddr));
}
unsigned long dvma_alloc (unsigned long paddr, unsigned long size)
{
int index;
int pages = ((paddr & ~DVMA_PAGE_MASK) + size + (DVMA_PAGE_SIZE-1)) >>
DVMA_PAGE_SHIFT;
if (fixed_dvma)
return ((unsigned long)phys_to_virt (paddr));
if (pages > 1) /* multi page, allocate from slow pool */
return dvma_slow_alloc (paddr, pages);
index = dvma_entry_hash (paddr);
if (dvma_entry_use(index)) {
if (dvma_entry_paddr(index) == (paddr & DVMA_PAGE_MASK)) {
dvma_entry_inc(index);
return dvma_entry_vaddr(index,paddr);
}
/* collision, allocate from slow pool */
return dvma_slow_alloc (paddr, pages);
}
dvma_entry_set(index,paddr);
dvma_entry_inc(index);
return dvma_entry_vaddr(index,paddr);
}
void dvma_free (unsigned long dvma_addr, unsigned long size)
{
int npages;
int index;
if (fixed_dvma)
return;
if (!dvma_is_slow(dvma_addr)) {
index = (dvma_addr >> DVMA_PAGE_SHIFT);
if (dvma_entry_use(index) == 0) {
printk ("dvma_free: %lx entry already free\n",dvma_addr);
return;
}
dvma_entry_dec(index);
if (dvma_entry_use(index) == 0)
dvma_entry_clr(index);
return;
}
/* free in slow pool */
npages = ((dvma_addr & ~DVMA_PAGE_MASK) + size + (DVMA_PAGE_SIZE-1)) >>
DVMA_PAGE_SHIFT;
for (index = (dvma_addr >> DVMA_PAGE_SHIFT); npages--; index++) {
dvma_entry_clr(index);
clear_bit (index,dvma_map);
}
}
/*
* SBus helper functions
*
* Sun3x don't have a sbus, but many of the used devices are also
* used on Sparc machines with sbus. To avoid having a lot of
* duplicate code, we provide necessary glue stuff to make using
* of the sbus driver code possible.
*
* (C) 1999 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
*/
#include <linux/types.h>
#include <linux/init.h>
__initfunc(void sbus_init(void))
{
}
void *sparc_alloc_io (u32 address, void *virtual, int len, char *name,
u32 bus_type, int rdonly)
{
return (void *)address;
}
int prom_getintdefault(int node, char *property, int deflt)
{
return deflt;
}
int prom_getbool (int node, char *prop)
{
return 1;
}
void prom_printf(char *fmt, ...)
{
}
void prom_halt (void)
{
}
/*
* linux/arch/m68k/sun3x/time.c
*
* Sun3x-specific time handling
*/
#include <linux/config.h>
#include <linux/types.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/kernel_stat.h>
#include <linux/interrupt.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/system.h>
#include <asm/traps.h>
#include <asm/sun3x.h>
#include "time.h"
#define M_CONTROL 0xf8
#define M_SEC 0xf9
#define M_MIN 0xfa
#define M_HOUR 0xfb
#define M_DAY 0xfc
#define M_DATE 0xfd
#define M_MONTH 0xfe
#define M_YEAR 0xff
#define C_WRITE 0x80
#define C_READ 0x40
#define C_SIGN 0x20
#define C_CALIB 0x1f
#define BCD_TO_BIN(val) (((val)&15) + ((val)>>4)*10)
/* Read the Mostek */
void sun3x_gettod (int *yearp, int *monp, int *dayp,
int *hourp, int *minp, int *secp)
{
volatile unsigned char *eeprom = (unsigned char *)SUN3X_EEPROM;
/* Stop updates */
*(eeprom + M_CONTROL) |= C_READ;
/* Read values */
*yearp = BCD_TO_BIN(*(eeprom + M_YEAR));
*monp = BCD_TO_BIN(*(eeprom + M_MONTH));
*dayp = BCD_TO_BIN(*(eeprom + M_DATE));
*hourp = BCD_TO_BIN(*(eeprom + M_HOUR));
*minp = BCD_TO_BIN(*(eeprom + M_MIN));
*secp = BCD_TO_BIN(*(eeprom + M_SEC));
/* Restart updates */
*(eeprom + M_CONTROL) &= ~C_READ;
}
/* Not much we can do here */
unsigned long sun3x_gettimeoffset (void)
{
return 0L;
}
static void sun3x_timer_tick(int irq, void *dev_id, struct pt_regs *regs)
{
void (*vector)(int, void *, struct pt_regs *) = dev_id;
/* Clear the pending interrupt - pulse the enable line low */
disable_irq(5);
enable_irq(5);
vector(irq, NULL, regs);
}
__initfunc(void sun3x_sched_init(void (*vector)(int, void *, struct pt_regs *)))
{
sys_request_irq(5, sun3x_timer_tick, IRQ_FLG_STD, "timer tick", vector);
/* Pulse enable low to get the clock started */
disable_irq(5);
enable_irq(5);
}
#ifndef SUN3X_TIME_H
#define SUN3X_TIME_H
void sun3x_gettod (int *yearp, int *monp, int *dayp,
int *hourp, int *minp, int *secp);
unsigned long sun3x_gettimeoffset (void);
void sun3x_sched_init(void (*vector)(int, void *, struct pt_regs *));
#endif
/*
* misc.c
*
* $Id: misc.c,v 1.63 1999/04/05 21:48:20 cort Exp $
* $Id: misc.c,v 1.64 1999/04/30 05:52:46 cort Exp $
*
* Adapted for PowerPC by Gary Thomas
*
......@@ -362,8 +362,9 @@ decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum,
*/
if (board_type == 0xe0) {
base_mod = inb(0x803);
/* if a MVME2300 or a MCME2400 then no keyboard */
if((base_mod == 0x9) || (base_mod == 0xF9)) {
/* if a MVME2300/2400 or a Sitka then no keyboard */
if((base_mod == 0x9) || (base_mod == 0xF9) ||
(base_mod == 0xE1)) {
keyb_present = 0; /* no keyboard */
}
}
......@@ -471,6 +472,7 @@ decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum,
{
puts("initrd at: "); puthex(initrd_start);
puts(" "); puthex(initrd_end); puts("\n");
#ifdef OMIT
avail_ram = (char *)PAGE_ALIGN(
(unsigned long)zimage_size+(unsigned long)zimage_start);
memcpy ((void *)avail_ram, (void *)initrd_start, INITRD_SIZE );
......@@ -478,6 +480,7 @@ decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum,
initrd_end = initrd_start + INITRD_SIZE;
puts("relocated to: "); puthex(initrd_start);
puts(" "); puthex(initrd_end); puts("\n");
#endif
}
avail_ram = (char *)0x00400000;
......
......@@ -14,7 +14,7 @@ CONFIG_6xx=y
CONFIG_ALL_PPC=y
# CONFIG_APUS is not set
# CONFIG_MBX is not set
CONFIG_SMP=y
# CONFIG_SMP is not set
#
# General setup
......@@ -42,6 +42,7 @@ CONFIG_PMAC_PBOOK=y
CONFIG_MAC_KEYBOARD=y
CONFIG_MAC_FLOPPY=y
CONFIG_MAC_SERIAL=y
# CONFIG_SERIAL_CONSOLE is not set
CONFIG_ADBMOUSE=y
CONFIG_PROC_DEVICETREE=y
# CONFIG_TOTALMP is not set
......@@ -336,7 +337,7 @@ CONFIG_FONT_SUN12x22=y
#
CONFIG_VT=y
CONFIG_VT_CONSOLE=y
# CONFIG_SERIAL is not set
CONFIG_SERIAL=m
# CONFIG_SERIAL_EXTENDED is not set
# CONFIG_SERIAL_NONSTANDARD is not set
CONFIG_UNIX98_PTYS=y
......@@ -474,6 +475,6 @@ CONFIG_DMASOUND=y
#
# Kernel hacking
#
# CONFIG_MAGIC_SYSRQ is not set
CONFIG_MAGIC_SYSRQ=y
# CONFIG_KGDB is not set
# CONFIG_XMON is not set
# $Id: config.in,v 1.91 1999/04/09 07:07:47 cort Exp $
# $Id: config.in,v 1.92 1999/04/30 05:41:43 cort Exp $
# For a description of the syntax of this configuration file,
# see the Configure script.
#
......@@ -89,9 +89,9 @@ bool 'Support for TotalImpact TotalMP' CONFIG_TOTALMP
bool 'Support for early boot text console (BootX only)' CONFIG_BOOTX_TEXT
bool 'Support for Motorola Hot Swap' CONFIG_MOTOROLA_HOTSWAP
if [ "$CONFIG_PREP" = "y" -o "$CONFIG_ALL_PPC" = "y" ]; then
bool 'PReP bootloader ernel arguments' CONFIG_CMDLINE_BOOL n
bool 'PReP bootloader kernel arguments' CONFIG_CMDLINE_BOOL y
if [ "$CONFIG_CMDLINE_BOOL" = "y" ] ; then
string 'Initial kernel command string' CONFIG_CMDLINE ""
string 'Initial kernel command string' CONFIG_CMDLINE console=ttyS0,9600 console=tty0 root=/dev/sda2
fi
fi
......
......@@ -8,13 +8,12 @@
CONFIG_PPC=y
CONFIG_6xx=y
# CONFIG_8xx is not set
CONFIG_PMAC=y
# CONFIG_PMAC is not set
# CONFIG_PREP is not set
# CONFIG_CHRP is not set
# CONFIG_ALL_PPC is not set
CONFIG_ALL_PPC=y
# CONFIG_APUS is not set
# CONFIG_MBX is not set
CONFIG_MACH_SPECIFIC=y
# CONFIG_SMP is not set
#
......@@ -36,20 +35,20 @@ CONFIG_KERNEL_ELF=y
CONFIG_BINFMT_MISC=m
# CONFIG_BINFMT_JAVA is not set
# CONFIG_PARPORT is not set
# CONFIG_VGA_CONSOLE is not set
CONFIG_VGA_CONSOLE=y
CONFIG_FB=y
CONFIG_FB_COMPAT_XPMAC=y
CONFIG_PMAC_PBOOK=y
CONFIG_MAC_KEYBOARD=y
CONFIG_MAC_FLOPPY=y
CONFIG_MAC_SERIAL=y
# CONFIG_SERIAL_CONSOLE is not set
CONFIG_ADBMOUSE=y
CONFIG_BLK_DEV_IDE_PMAC=y
CONFIG_PROC_DEVICETREE=y
# CONFIG_KGDB is not set
# CONFIG_XMON is not set
# CONFIG_TOTALMP is not set
CONFIG_BOOTX_TEXT=y
# CONFIG_MOTOROLA_HOTSWAP is not set
# CONFIG_CMDLINE_BOOL is not set
#
# Plug and Play support
......@@ -76,15 +75,13 @@ CONFIG_BLK_DEV_IDEFLOPPY=y
# CONFIG_BLK_DEV_IDEPCI is not set
# CONFIG_BLK_DEV_SL82C105 is not set
CONFIG_BLK_DEV_IDE_PMAC=y
CONFIG_BLK_DEV_IDEDMA_PMAC=y
CONFIG_BLK_DEV_IDEDMA=y
CONFIG_PMAC_IDEDMA_AUTO=y
# CONFIG_BLK_DEV_IDEDMA_PMAC is not set
# CONFIG_IDE_CHIPSETS is not set
#
# Additional Block Devices
#
# CONFIG_BLK_DEV_LOOP is not set
CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_MD is not set
CONFIG_BLK_DEV_RAM=y
......@@ -119,7 +116,6 @@ CONFIG_IP_ALIAS=y
# (it is safe to leave these untouched)
#
CONFIG_INET_RARP=y
CONFIG_IP_NOSR=y
CONFIG_SKB_LARGE=y
# CONFIG_IPV6 is not set
......@@ -155,12 +151,12 @@ CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_ST=y
CONFIG_BLK_DEV_SR=y
CONFIG_BLK_DEV_SR_VENDOR=y
# CONFIG_CHR_DEV_SG is not set
CONFIG_CHR_DEV_SG=y
#
# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
#
# CONFIG_SCSI_MULTI_LUN is not set
CONFIG_SCSI_MULTI_LUN=y
CONFIG_SCSI_CONSTANTS=y
# CONFIG_SCSI_LOGGING is not set
......@@ -188,16 +184,28 @@ CONFIG_AIC7XXX_RESET_DELAY=15
# CONFIG_SCSI_FUTURE_DOMAIN is not set
# CONFIG_SCSI_GDTH is not set
# CONFIG_SCSI_GENERIC_NCR5380 is not set
# CONFIG_SCSI_G_NCR5380_PORT is not set
# CONFIG_SCSI_G_NCR5380_MEM is not set
# CONFIG_SCSI_INITIO is not set
# CONFIG_SCSI_INIA100 is not set
# CONFIG_SCSI_NCR53C406A is not set
# CONFIG_SCSI_SYM53C416 is not set
# CONFIG_SCSI_NCR53C7xx is not set
# CONFIG_SCSI_NCR53C8XX is not set
CONFIG_SCSI_NCR53C8XX=y
# CONFIG_SCSI_SYM53C8XX is not set
CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8
CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32
CONFIG_SCSI_NCR53C8XX_SYNC=20
# CONFIG_SCSI_NCR53C8XX_PROFILE is not set
# CONFIG_SCSI_NCR53C8XX_IOMAPPED is not set
# CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT is not set
# CONFIG_SCSI_PAS16 is not set
# CONFIG_SCSI_PCI2000 is not set
# CONFIG_SCSI_PCI2220I is not set
# CONFIG_SCSI_PSI240I is not set
# CONFIG_SCSI_QLOGIC_FAS is not set
# CONFIG_SCSI_QLOGIC_ISP is not set
# CONFIG_SCSI_QLOGIC_FC is not set
# CONFIG_SCSI_SEAGATE is not set
# CONFIG_SCSI_DC390T is not set
# CONFIG_SCSI_T128 is not set
......@@ -228,7 +236,7 @@ CONFIG_BMAC=y
# CONFIG_ACENIC is not set
# CONFIG_NET_ISA is not set
CONFIG_NET_EISA=y
# CONFIG_PCNET32 is not set
CONFIG_PCNET32=y
# CONFIG_AC3200 is not set
# CONFIG_APRICOT is not set
# CONFIG_CS89x0 is not set
......@@ -275,7 +283,7 @@ CONFIG_PPP=y
# CONFIG_ISDN is not set
#
# CD-ROM drivers (not for SCSI or IDE/ATAPI drives)
# Old CD-ROM drivers (not SCSI, not IDE)
#
# CONFIG_CD_NO_IDESCSI is not set
......@@ -283,22 +291,37 @@ CONFIG_PPP=y
# Console drivers
#
CONFIG_DUMMY_CONSOLE=y
# CONFIG_FB_PM2 is not set
CONFIG_FB_OF=y
CONFIG_FB_CONTROL=y
CONFIG_FB_PLATINUM=y
CONFIG_FB_VALKYRIE=y
CONFIG_FB_ATY=y
# CONFIG_FB_ATY is not set
CONFIG_FB_IMSTT=y
CONFIG_FB_CT65550=y
# CONFIG_FB_S3TRIO is not set
# CONFIG_FB_MATROX is not set
CONFIG_FB_ATY=y
CONFIG_FB_MATROX=y
CONFIG_FB_MATROX_MILLENIUM=y
CONFIG_FB_MATROX_MYSTIQUE=y
CONFIG_FB_MATROX_G100=y
# CONFIG_FB_MATROX_MULTIHEAD is not set
# CONFIG_FB_ATY is not set
# CONFIG_FB_VIRTUAL is not set
# CONFIG_FBCON_ADVANCED is not set
CONFIG_FBCON_ADVANCED=y
# CONFIG_FBCON_MFB is not set
# CONFIG_FBCON_CFB2 is not set
# CONFIG_FBCON_CFB4 is not set
CONFIG_FBCON_CFB8=y
CONFIG_FBCON_CFB16=y
CONFIG_FBCON_CFB24=y
CONFIG_FBCON_CFB32=y
# CONFIG_FBCON_AFB is not set
# CONFIG_FBCON_ILBM is not set
# CONFIG_FBCON_IPLAN2P2 is not set
# CONFIG_FBCON_IPLAN2P4 is not set
# CONFIG_FBCON_IPLAN2P8 is not set
# CONFIG_FBCON_MAC is not set
# CONFIG_FBCON_VGA is not set
# CONFIG_FBCON_FONTWIDTH8_ONLY is not set
CONFIG_FBCON_FONTS=y
# CONFIG_FONT_8x8 is not set
......@@ -314,15 +337,25 @@ CONFIG_FONT_SUN12x22=y
#
CONFIG_VT=y
CONFIG_VT_CONSOLE=y
# CONFIG_SERIAL is not set
CONFIG_SERIAL=m
# CONFIG_SERIAL_EXTENDED is not set
# CONFIG_SERIAL_NONSTANDARD is not set
CONFIG_UNIX98_PTYS=y
CONFIG_UNIX98_PTY_COUNT=256
# CONFIG_MOUSE is not set
CONFIG_MOUSE=y
#
# Mice
#
# CONFIG_ATIXL_BUSMOUSE is not set
# CONFIG_BUSMOUSE is not set
# CONFIG_MS_BUSMOUSE is not set
CONFIG_PSMOUSE=y
# CONFIG_82C710_MOUSE is not set
# CONFIG_PC110_PAD is not set
# CONFIG_QIC02_TAPE is not set
# CONFIG_WATCHDOG is not set
CONFIG_NVRAM=y
# CONFIG_NVRAM is not set
# CONFIG_RTC is not set
#
......@@ -334,11 +367,20 @@ CONFIG_NVRAM=y
# Joystick support
#
# CONFIG_JOYSTICK is not set
# CONFIG_DTLK is not set
#
# Ftape, the floppy tape device driver
#
# CONFIG_FTAPE is not set
# CONFIG_FT_NORMAL_DEBUG is not set
# CONFIG_FT_FULL_DEBUG is not set
# CONFIG_FT_NO_TRACE is not set
# CONFIG_FT_NO_TRACE_AT_ALL is not set
# CONFIG_FT_STD_FDC is not set
# CONFIG_FT_MACH2 is not set
# CONFIG_FT_PROBE_FC10 is not set
# CONFIG_FT_ALT_FDC is not set
#
# Filesystems
......@@ -429,3 +471,10 @@ CONFIG_DMASOUND=y
# CONFIG_SOUND_MSNDCLAS is not set
# CONFIG_SOUND_MSNDPIN is not set
# CONFIG_SOUND_OSS is not set
#
# Kernel hacking
#
CONFIG_MAGIC_SYSRQ=y
# CONFIG_KGDB is not set
# CONFIG_XMON is not set
......@@ -96,11 +96,12 @@ int gg2_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn,
#define python_config_data(bus) ((0xfef00000+0xf8010)-(bus*0x100000))
#define PYTHON_CFA(b, d, o) (0x80 | ((b<<6) << 8) | ((d) << 16) \
| (((o) & ~3) << 24))
unsigned int python_busnr = 1;
int python_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn,
unsigned char offset, unsigned char *val)
{
if (bus > 2) {
if (bus > python_busnr) {
*val = 0xff;
return PCIBIOS_DEVICE_NOT_FOUND;
}
......@@ -112,7 +113,7 @@ int python_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn,
int python_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn,
unsigned char offset, unsigned short *val)
{
if (bus > 2) {
if (bus > python_busnr) {
*val = 0xffff;
return PCIBIOS_DEVICE_NOT_FOUND;
}
......@@ -125,7 +126,7 @@ int python_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn,
int python_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn,
unsigned char offset, unsigned int *val)
{
if (bus > 2) {
if (bus > python_busnr) {
*val = 0xffffffff;
return PCIBIOS_DEVICE_NOT_FOUND;
}
......@@ -137,7 +138,7 @@ int python_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn,
int python_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn,
unsigned char offset, unsigned char val)
{
if (bus > 2)
if (bus > python_busnr)
return PCIBIOS_DEVICE_NOT_FOUND;
out_be32( python_config_address( bus ), PYTHON_CFA(bus,dev_fn,offset));
out_8((volatile unsigned char *)python_config_data(bus) + (offset&3), val);
......@@ -147,7 +148,7 @@ int python_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn,
int python_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn,
unsigned char offset, unsigned short val)
{
if (bus > 2)
if (bus > python_busnr)
return PCIBIOS_DEVICE_NOT_FOUND;
out_be32( python_config_address( bus ), PYTHON_CFA(bus,dev_fn,offset));
out_le16((volatile unsigned short *)python_config_data(bus) + (offset&3),
......@@ -158,7 +159,7 @@ int python_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn,
int python_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn,
unsigned char offset, unsigned int val)
{
if (bus > 2)
if (bus > python_busnr)
return PCIBIOS_DEVICE_NOT_FOUND;
out_be32( python_config_address( bus ), PYTHON_CFA(bus,dev_fn,offset));
out_le32((unsigned *)python_config_data(bus) + (offset&3), val);
......@@ -217,9 +218,9 @@ chrp_pcibios_fixup(void)
{
struct pci_dev *dev;
/* get the other 2 busses on the F50 */
if ( !strncmp("F5", get_property(find_path_device("/"),
"ibm,model-class", NULL),2) )
/* some of IBM chrps have > 1 bus */
if ( !strncmp("IBM", get_property(find_path_device("/"),
"name", NULL),3) )
{
pci_scan_peer_bridge(1);
pci_scan_peer_bridge(2);
......@@ -258,6 +259,8 @@ decl_config_access_method(indirect);
void __init
chrp_setup_pci_ptrs(void)
{
struct device_node *py;
if ( !strncmp("MOT",
get_property(find_path_device("/"), "model", NULL),3) )
{
......@@ -268,16 +271,28 @@ chrp_setup_pci_ptrs(void)
}
else
{
if ( find_compatible_devices( "pci", "IBM,python" ) )
if ( (py = find_compatible_devices( "pci", "IBM,python" )) )
{
/* find out how many pythons */
while ( (py = py->next) ) python_busnr++;
set_config_access_method(python);
/*
* We assume these values but should someday get them
* from the device tree or python itself instead -- Cort
* We base these values on the machine type but should
* try to read them from the python controller itself.
* -- Cort
*/
pci_dram_offset = 0x80000000;
isa_mem_base = 0xa0000000;
isa_io_base = 0x88000000;
set_config_access_method(python);
if ( !strncmp("IBM,7025-F50", get_property(find_path_device("/"), "name", NULL),12) )
{
pci_dram_offset = 0x80000000;
isa_mem_base = 0xa0000000;
isa_io_base = 0x88000000;
} else if ( !strncmp("IBM,7043-260",
get_property(find_path_device("/"), "name", NULL),12) )
{
pci_dram_offset = 0x80000000;
isa_mem_base = 0xc0000000;
isa_io_base = 0xf8000000;
}
}
else
{
......
......@@ -400,7 +400,10 @@ chrp_do_IRQ(struct pt_regs *regs,
*
* This should go in the above mask/ack code soon. -- Cort
*/
irq = *chrp_int_ack_special;
if ( chrp_int_ack_special )
irq = *chrp_int_ack_special;
else
irq = i8259_irq(0);
/*
* Acknowledge as soon as possible to allow i8259
* interrupt nesting */
......
/*
* arch/ppc/kernel/head.S
*
* $Id: head.S,v 1.127 1999/04/07 07:26:55 paulus Exp $
* $Id: head.S,v 1.130 1999/05/09 19:16:43 cort Exp $
*
* PowerPC version
* Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
......@@ -2045,8 +2045,9 @@ _GLOBAL(_switch)
stw r0,GPR0(r1)
lwz r0,0(r1)
stw r0,GPR1(r1)
SAVE_10GPRS(2, r1)
SAVE_10GPRS(12, r1)
/* r3-r13 are caller saved -- Cort */
SAVE_GPR(2, r1)
SAVE_8GPRS(14, r1)
SAVE_10GPRS(22, r1)
mflr r20 /* Return to switch caller */
mfmsr r22
......@@ -2069,6 +2070,8 @@ _GLOBAL(_switch)
mtspr SPRG3,r0 /* Update current TSS phys addr */
SYNC
lwz r1,KSP(r4) /* Load new stack pointer */
/* save the old current 'last' for return value */
mr r3,r2
addi r2,r4,-TSS /* Update current */
#ifndef CONFIG_8xx
/* Set up segment registers for new task */
......@@ -2076,39 +2079,62 @@ _GLOBAL(_switch)
addis r5,r5,0x6000 /* Set Ks, Ku bits */
li r0,12 /* TASK_SIZE / SEGMENT_SIZE */
mtctr r0
li r3,0
3: mtsrin r5,r3
li r9,0
3: mtsrin r5,r9
addi r5,r5,1 /* next VSID */
addis r3,r3,0x1000 /* address of next segment */
addis r9,r9,0x1000 /* address of next segment */
bdnz 3b
#else
/* On the MPC8xx, we place the physical address of the new task
* page directory loaded into the MMU base register, and set the
* ASID compare register with the new "context".
*/
lwz r3,MM-TSS(r4) /* Get virtual address of mm */
lwz r3,PGD(r3) /* get new->mm->pgd */
addis r3,r3,-KERNELBASE@h /* convert to phys addr */
mtspr M_TWB, r3 /* Update MMU base address */
lwz r9,MM-TSS(r4) /* Get virtual address of mm */
lwz r9,PGD(r9) /* get new->mm->pgd */
addis r9,r9,-KERNELBASE@h /* convert to phys addr */
mtspr M_TWB, r9 /* Update MMU base address */
mtspr M_CASID, r5 /* Update context */
tlbia
#endif
SYNC
/* FALL THROUGH into int_return */
#ifdef __SMP__
/* call schedule_tail if this is the first time for a child process */
lwz r5,TSS_SMP_FORK_RET(r4)
cmpi 0,r5,0
beq+ int_return
li r3,0
stw r3,TSS_SMP_FORK_RET(r4)
bl schedule_tail
#endif /* __SMP__ */
2: lwz r9,_MSR(r1) /* Returning to user mode? */
andi. r9,r9,MSR_PR
beq+ 10f /* if not, don't adjust kernel stack */
8: addi r4,r1,INT_FRAME_SIZE+STACK_UNDERHEAD /* size of frame */
stw r4,TSS+KSP(r2) /* save kernel stack pointer */
tophys(r9,r1,r9)
mtspr SPRG2,r9 /* phys exception stack pointer */
10: lwz r2,_CTR(r1)
lwz r0,_LINK(r1)
mtctr r2
mtlr r0
lwz r2,_XER(r1)
lwz r0,_CCR(r1)
mtspr XER,r2
mtcrf 0xFF,r0
/* r3-r13 are destroyed -- Cort */
REST_GPR(14, r1)
REST_8GPRS(15, r1)
REST_8GPRS(23, r1)
REST_GPR(31, r1)
lwz r2,_NIP(r1) /* Restore environment */
lwz r0,_MSR(r1)
mtspr SRR0,r2
mtspr SRR1,r0
lwz r0,GPR0(r1)
lwz r2,GPR2(r1)
lwz r1,GPR1(r1)
SYNC
rfi
/*
* Trap exit.
*/
#ifdef __SMP__
.globl ret_from_smpfork
ret_from_smpfork:
bl schedule_tail
#endif
.globl ret_from_syscall
ret_from_syscall:
.globl int_return
......
......@@ -10,6 +10,40 @@ unsigned char cached_8259[2] = { 0xff, 0xff };
#define cached_A1 (cached_8259[0])
#define cached_21 (cached_8259[1])
int i8259_irq(int cpu)
{
int irq;
/*
* Perform an interrupt acknowledge cycle on controller 1
*/
outb(0x0C, 0x20);
irq = inb(0x20) & 7;
if (irq == 2)
{
/*
* Interrupt is cascaded so perform interrupt
* acknowledge on controller 2
*/
outb(0x0C, 0xA0);
irq = (inb(0xA0) & 7) + 8;
}
else if (irq==7)
{
/*
* This may be a spurious interrupt
*
* Read the interrupt status register. If the most
* significant bit is not set then there is no valid
* interrupt
*/
outb(0x0b, 0x20);
if(~inb(0x20)&0x80)
return -1;
}
return irq;
}
static void i8259_mask_and_ack_irq(unsigned int irq_nr)
{
if ( irq_nr >= i8259_pic.irq_offset )
......
......@@ -7,5 +7,6 @@
extern struct hw_interrupt_type i8259_pic;
void i8259_init(void);
int i8259_irq(int);
#endif /* _PPC_KERNEL_i8259_H */
......@@ -103,7 +103,7 @@ int indirect_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn,
}
int indirect_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn,
unsigned char offset, unsigned short val)
unsigned char offset, unsigned int val)
{
unsigned flags;
......
......@@ -48,7 +48,6 @@ main(void)
DEFINE(NEED_RESCHED, offsetof(struct task_struct, need_resched));
DEFINE(TSS_FPR0, offsetof(struct thread_struct, fpr[0]));
DEFINE(TSS_FPSCR, offsetof(struct thread_struct, fpscr));
DEFINE(TSS_SMP_FORK_RET, offsetof(struct thread_struct, smp_fork_ret));
/* Interrupt register frame */
DEFINE(TASK_UNION_SIZE, sizeof(union task_union));
DEFINE(STACK_FRAME_OVERHEAD, STACK_FRAME_OVERHEAD);
......
......@@ -14,13 +14,13 @@ void openpic_ipi_action(int cpl, void *dev_id, struct pt_regs *regs)
}
#endif /* __SMP__ */
void __openfirmware chrp_mask_and_ack_irq(unsigned int irq_nr)
void chrp_mask_and_ack_irq(unsigned int irq_nr)
{
if (is_8259_irq(irq_nr))
i8259_pic.mask_and_ack(irq_nr);
}
static void __openfirmware chrp_mask_irq(unsigned int irq_nr)
static void chrp_mask_irq(unsigned int irq_nr)
{
if (is_8259_irq(irq_nr))
i8259_pic.disable(irq_nr);
......@@ -28,7 +28,7 @@ static void __openfirmware chrp_mask_irq(unsigned int irq_nr)
openpic_disable_irq(irq_to_openpic(irq_nr));
}
static void __openfirmware chrp_unmask_irq(unsigned int irq_nr)
static void chrp_unmask_irq(unsigned int irq_nr)
{
if (is_8259_irq(irq_nr))
i8259_pic.enable(irq_nr);
......
#include <linux/config.h>
#include <linux/stddef.h>
#include <linux/init.h>
#include <linux/sched.h>
......
......@@ -75,7 +75,9 @@ extern int mackbd_translate(unsigned char scancode, unsigned char *keycode,
extern char mackbd_unexpected_up(unsigned char keycode);
extern void mackbd_leds(unsigned char leds);
extern void mackbd_init_hw(void);
extern unsigned char mackbd_sysrq_xlate[128];
#ifdef CONFIG_MAGIC_SYSRQ
unsigned char mackbd_sysrq_xlate[128];
#endif /* CONFIG_MAGIC_SYSRQ */
extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode);
extern int pckbd_getkeycode(unsigned int scancode);
extern int pckbd_translate(unsigned char scancode, unsigned char *keycode,
......@@ -575,7 +577,7 @@ pmac_init(unsigned long r3, unsigned long r4, unsigned long r5,
ppc_md.get_rtc_time = pmac_get_rtc_time;
ppc_md.calibrate_decr = pmac_calibrate_decr;
#ifdef CONFIG_VT
#if defined(CONFIG_VT) && defined(CONFIG_MAC_KEYBOARD)
ppc_md.kbd_setkeycode = mackbd_setkeycode;
ppc_md.kbd_getkeycode = mackbd_getkeycode;
ppc_md.kbd_translate = mackbd_translate;
......@@ -584,7 +586,7 @@ pmac_init(unsigned long r3, unsigned long r4, unsigned long r5,
ppc_md.kbd_init_hw = mackbd_init_hw;
#ifdef CONFIG_MAGIC_SYSRQ
ppc_md.kbd_sysrq_xlate = mackbd_sysrq_xlate;
#endif
#endif
#endif
#if defined(CONFIG_BLK_DEV_IDE_PMAC)
......
This diff is collapsed.
......@@ -45,6 +45,8 @@
#include <asm/machdep.h>
#include <asm/mk48t59.h>
#include <asm/prep_nvram.h>
#include <asm/raven.h>
#include "time.h"
#include "local_irq.h"
......@@ -82,15 +84,7 @@ extern void pckbd_init_hw(void);
extern unsigned char pckbd_sysrq_xlate[128];
extern void prep_setup_pci_ptrs(void);
/* these need to be here since PReP uses them for OpenPIC support */
/* Maybe move these to a 'openpic_irq.c' file instead? --Troy */
extern void chrp_mask_and_ack_irq(unsigned int irq_nr);
extern void chrp_mask_irq(unsigned int irq_nr);
extern void chrp_unmask_irq(unsigned int irq_nr);
extern void chrp_do_IRQ(struct pt_regs *regs, int cpu, int isfake);
extern volatile unsigned char *chrp_int_ack_special;
extern char saved_command_line[256];
int _prep_type;
......@@ -355,6 +349,8 @@ prep_setup_arch(unsigned long * memory_start_p, unsigned long * memory_end_p))
request_region(0x80,0x10,"dma page reg");
request_region(0xc0,0x20,"dma2");
raven_init();
#ifdef CONFIG_VGA_CONSOLE
/* remap the VGA memory */
vgacon_remap_base = 0xf0000000;
......@@ -595,39 +591,13 @@ void
prep_do_IRQ(struct pt_regs *regs, int cpu, int isfake)
{
int irq;
/*
* Perform an interrupt acknowledge cycle on controller 1
*/
outb(0x0C, 0x20);
irq = inb(0x20) & 7;
if (irq == 2)
{
/*
* Interrupt is cascaded so perform interrupt
* acknowledge on controller 2
*/
outb(0x0C, 0xA0);
irq = (inb(0xA0) & 7) + 8;
}
else if (irq==7)
{
/*
* This may be a spurious interrupt
*
* Read the interrupt status register. If the most
* significant bit is not set then there is no valid
* interrupt
*/
outb(0x0b, 0x20);
if(~inb(0x20)&0x80)
{
printk(KERN_DEBUG "Bogus interrupt from PC = %lx\n",
regs->nip);
ppc_spurious_interrupts++;
return;
}
if ( (irq = i8259_irq(0)) < 0 )
{
printk(KERN_DEBUG "Bogus interrupt from PC = %lx\n",
regs->nip);
ppc_spurious_interrupts++;
return;
}
ppc_irq_dispatch_handler( regs, irq );
}
......@@ -637,9 +607,19 @@ prep_init_IRQ(void))
{
int i;
if (OpenPIC != NULL) {
for ( i = 16 ; i < 36 ; i++ )
irq_desc[i].ctl = &open_pic;
openpic_init(1);
}
for ( i = 0 ; i < 16 ; i++ )
irq_desc[i].ctl = &i8259_pic;
i8259_init();
#ifdef __SMP__
request_irq(openpic_to_irq(OPENPIC_VEC_SPURIOUS), openpic_ipi_action,
0, "IPI0", 0);
#endif /* __SMP__ */
}
#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
......@@ -728,8 +708,6 @@ __initfunc(void
prep_init(unsigned long r3, unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7))
{
int tmp;
/* make a copy of residual data */
if ( r3 )
{
......@@ -784,27 +762,15 @@ prep_init(unsigned long r3, unsigned long r4, unsigned long r5,
strcpy(cmd_line, (char *)(r6+KERNELBASE));
}
if ( is_powerplus ) { /* look for a Raven OpenPIC */
pcibios_read_config_dword(0, 0, 0, &tmp);
if (tmp == PCI_VENDOR_ID_MOTOROLA + (PCI_DEVICE_ID_MOTOROLA_RAVEN<<16)) {
pcibios_read_config_dword(0, 0, PCI_BASE_ADDRESS_1, &tmp);
if (tmp) {
OpenPIC=(volatile struct OpenPIC *)
(tmp + isa_mem_base);
/* printk("OpenPIC found at %p: \n", OpenPIC);*/
}
} else {
printk ("prep_init: WARNING: can't find an OpenPIC on what looks like a PowerPlus board\n");
}
}
ppc_md.setup_arch = prep_setup_arch;
ppc_md.setup_residual = prep_setup_residual;
ppc_md.get_cpuinfo = prep_get_cpuinfo;
ppc_md.irq_cannonicalize = prep_irq_cannonicalize;
ppc_md.init_IRQ = prep_init_IRQ;
ppc_md.do_IRQ = prep_do_IRQ;
if ( !OpenPIC )
ppc_md.do_IRQ = prep_do_IRQ;
else
ppc_md.do_IRQ = chrp_do_IRQ;
ppc_md.init = NULL;
ppc_md.restart = prep_restart;
......@@ -858,9 +824,8 @@ prep_init(unsigned long r3, unsigned long r4, unsigned long r5,
ppc_ide_md.release_region = prep_ide_release_region;
ppc_ide_md.fix_driveid = prep_ide_fix_driveid;
ppc_ide_md.ide_init_hwif = prep_ide_init_hwif_ports;
ppc_ide_md.io_base = _IO_BASE;
#endif
ppc_ide_md.io_base = _IO_BASE;
#ifdef CONFIG_VT
ppc_md.kbd_setkeycode = pckbd_setkeycode;
......
/*
* $Id: process.c,v 1.78 1999/04/07 07:27:00 paulus Exp $
* $Id: process.c,v 1.83 1999/05/10 04:43:43 cort Exp $
*
* linux/arch/ppc/kernel/process.c
*
......@@ -43,10 +43,7 @@
#include <asm/prom.h>
int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpregs);
void switch_to(struct task_struct *, struct task_struct *);
extern unsigned long _get_SP(void);
extern spinlock_t scheduler_lock;
struct task_struct *last_task_used_math = NULL;
static struct vm_area_struct init_mmap = INIT_MMAP;
......@@ -160,7 +157,8 @@ int check_stack(struct task_struct *tsk)
}
void
switch_to(struct task_struct *prev, struct task_struct *new)
_switch_to(struct task_struct *prev, struct task_struct *new,
struct task_struct **last)
{
struct thread_struct *new_tss, *old_tss;
int s = _disable_interrupts();
......@@ -170,10 +168,10 @@ switch_to(struct task_struct *prev, struct task_struct *new)
#endif
#ifdef SHOW_TASK_SWITCHES
printk("%s/%d -> %s/%d NIP %08lx cpu %d lock %x root %x/%x\n",
printk("%s/%d -> %s/%d NIP %08lx cpu %d root %x/%x\n",
prev->comm,prev->pid,
new->comm,new->pid,new->tss.regs->nip,new->processor,
scheduler_lock.lock,new->fs->root,prev->fs->root);
new->fs->root,prev->fs->root);
#endif
#ifdef __SMP__
/* avoid complexity of lazy save/restore of fpu
......@@ -181,7 +179,8 @@ switch_to(struct task_struct *prev, struct task_struct *new)
* this task used the fpu during the last quantum.
*
* If it tries to use the fpu again, it'll trap and
* reload its fp regs.
* reload its fp regs. So we don't have to do a restore
* every switch, just a save.
* -- Cort
*/
if (prev->tss.regs && (prev->tss.regs->msr & MSR_FP))
......@@ -192,7 +191,7 @@ switch_to(struct task_struct *prev, struct task_struct *new)
#endif /* __SMP__ */
new_tss = &new->tss;
old_tss = &current->tss;
_switch(old_tss, new_tss, new->mm->context);
*last = _switch(old_tss, new_tss, new->mm->context);
_enable_interrupts(s);
}
......@@ -278,8 +277,12 @@ int
copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
struct task_struct * p, struct pt_regs * regs)
{
struct pt_regs * childregs;
struct pt_regs * childregs, *kregs;
#ifdef __SMP__
extern void ret_from_smpfork(void);
#else
extern void ret_from_syscall(void);
#endif
/* Copy registers */
childregs = ((struct pt_regs *)
((unsigned long)p + sizeof(union task_union)
......@@ -288,8 +291,19 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
if ((childregs->msr & MSR_PR) == 0)
childregs->gpr[2] = (unsigned long) p; /* `current' in new task */
childregs->gpr[3] = 0; /* Result from fork() */
p->tss.regs = childregs;
p->tss.ksp = (unsigned long) childregs - STACK_FRAME_OVERHEAD;
p->tss.regs = childregs;
p->tss.ksp -= sizeof(struct pt_regs ) + STACK_FRAME_OVERHEAD;
kregs = (struct pt_regs *)(p->tss.ksp + STACK_FRAME_OVERHEAD);
#ifdef __SMP__
kregs->nip = (unsigned long)ret_from_smpfork;
#else
kregs->nip = (unsigned long)ret_from_syscall;
#endif
kregs->msr = MSR_KERNEL;
kregs->gpr[1] = (unsigned long)childregs - STACK_FRAME_OVERHEAD;
kregs->gpr[2] = (unsigned long)p;
if (usp >= (unsigned long) regs) {
/* Stack is in kernel space - must adjust */
childregs->gpr[1] = (unsigned long)(childregs + 1);
......@@ -311,8 +325,6 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
childregs->msr &= ~MSR_FP;
#ifdef __SMP__
if ( (p->pid != 0) || !(clone_flags & CLONE_PID) )
p->tss.smp_fork_ret = 1;
p->last_processor = NO_PROC_ID;
#endif /* __SMP__ */
return 0;
......@@ -379,11 +391,6 @@ asmlinkage int sys_clone(int p1, int p2, int p3, int p4, int p5, int p6,
int res;
lock_kernel();
res = do_fork(clone_flags, regs->gpr[1], regs);
/*
* only parent returns here, child returns to either
* syscall_ret_1() or kernel_thread()
* -- Cort
*/
#ifdef __SMP__
/* When we clone the idle task we keep the same pid but
* the return value of 0 for both causes problems.
......@@ -403,7 +410,6 @@ asmlinkage int sys_fork(int p1, int p2, int p3, int p4, int p5, int p6,
int res;
res = do_fork(SIGCHLD, regs->gpr[1], regs);
/* only parent returns here */
#ifdef __SMP__
/* When we clone the idle task we keep the same pid but
* the return value of 0 for both causes problems.
......
/*
* $Id: prom.c,v 1.53 1999/04/22 22:45:42 cort Exp $
* $Id: prom.c,v 1.54 1999/05/10 04:43:46 cort Exp $
*
* Procedures for interfacing to the Open Firmware PROM on
* Power Macintosh computers.
......@@ -457,7 +457,7 @@ prom_init(int r3, int r4, prom_entry pp)
* a holding pattern controlled by the kernel (not OF) before
* we destroy the OF.
*
* This used a chunk of high memory, puts some holding pattern
* This uses a chunk of high memory, puts some holding pattern
* code there and sends the other processors off to there until
* smp_boot_cpus tells them to do something. We do that by using
* physical address 0x0. The holding pattern checks that address
......
......@@ -140,7 +140,8 @@ void do_page_fault(struct pt_regs *regs, unsigned long address,
if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
goto bad_area;
}
handle_mm_fault(current, vma, address, error_code & 0x02000000);
if (!handle_mm_fault(current, vma, address, error_code & 0x02000000))
goto bad_area;
up(&mm->mmap_sem);
/*
* keep track of tlb+htab misses that are good addrs but
......
/*
* $Id: init.c,v 1.163 1999/04/09 06:37:13 cort Exp $
* $Id: init.c,v 1.164 1999/05/05 17:33:55 cort Exp $
*
* PowerPC version
* Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
......@@ -119,12 +119,19 @@ extern struct task_struct *current_set[NR_CPUS];
PTE *Hash, *Hash_end;
unsigned long Hash_size, Hash_mask;
#ifndef CONFIG_8xx
#ifdef CONFIG_PPC64
unsigned long long _SDR1;
#else
unsigned long _SDR1;
#endif
static void hash_init(void);
union ubat { /* BAT register values to be loaded */
BAT bat;
P601_BAT bat_601;
#ifdef CONFIG_PPC64
u64 word[2];
#else
u32 word[2];
#endif
} BATS[4][2]; /* 4 pairs of IBAT, DBAT */
struct batrange { /* stores address ranges mapped by BATs */
......@@ -146,7 +153,6 @@ int __map_without_bats = 0;
/* optimization for 603 to load the tlb directly from the linux table -- Cort */
#define NO_RELOAD_HTAB 1 /* change in kernel/head.S too! */
void __bad_pte(pmd_t *pmd)
{
printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd));
......@@ -354,7 +360,6 @@ __ioremap(unsigned long addr, unsigned long size, unsigned long flags)
return NULL;
#ifndef CONFIG_8xx
#if 0
/*
* Is it already mapped? Perhaps overlapped by a previous
* BAT mapping. If the whole area is mapped then we're done,
......@@ -368,7 +373,6 @@ __ioremap(unsigned long addr, unsigned long size, unsigned long flags)
*/
if ( (v = p_mapped_by_bats(addr)) /*&& p_mapped_by_bats(addr+(size-1))*/ )
goto out;
#endif
#endif /* CONFIG_8xx */
if (mem_init_done) {
......@@ -397,7 +401,8 @@ __ioremap(unsigned long addr, unsigned long size, unsigned long flags)
for (i = 0; i < size; i += PAGE_SIZE)
map_page(&init_task, v+i, p+i, flags);
return (void *) (v + (addr & ~PAGE_MASK));
out:
return (void *) (v + (p & ~PAGE_MASK));
}
void iounmap(void *addr)
......@@ -1500,10 +1505,18 @@ __initfunc(static void hash_init(void))
* up to a maximum of 2MB.
*/
ramsize = (ulong)end_of_DRAM - KERNELBASE;
#ifdef CONFIG_PPC64
Hash_mask = 0;
for (h = 256<<10; h < ramsize / 256 && h < 4<<20; h *= 2, Hash_mask++)
;
Hash_size = h;
Hash_mask << 10; /* so setting _SDR1 works the same -- Cort */
#else
for (h = 64<<10; h < ramsize / 256 && h < 2<<20; h *= 2)
;
Hash_size = h;
Hash_mask = (h >> 6) - 1;
#endif
#ifdef NO_RELOAD_HTAB
/* shrink the htab since we don't use it on 603's -- Cort */
......
/* $Id: entry.S,v 1.158 1999/04/27 14:35:07 davem Exp $
/* $Id: entry.S,v 1.159 1999/05/08 03:00:03 davem Exp $
* arch/sparc/kernel/entry.S: Sparc trap low-level entry points.
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
......@@ -1476,7 +1476,7 @@ C_LABEL(ret_from_smpfork):
wr %l0, PSR_ET, %psr
WRITE_PAUSE
call schedule_tail
nop
mov %g3, %o0
b C_LABEL(ret_sys_call)
ld [%sp + REGWIN_SZ + PT_I0], %o0
#endif
......
/* $Id: process.c,v 1.136 1999/04/16 01:20:33 anton Exp $
/* $Id: process.c,v 1.137 1999/05/08 03:00:10 davem Exp $
* linux/arch/sparc/kernel/process.c
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
......@@ -63,6 +63,8 @@ asmlinkage int sys_idle(void)
/* endless idle loop with no priority at all */
current->priority = 0;
current->counter = -100;
init_idle();
for (;;) {
if (ARCH_SUN4C_SUN4) {
static int count = HZ;
......@@ -111,6 +113,8 @@ int cpu_idle(void *unused)
/* endless idle loop with no priority at all */
current->priority = 0;
current->counter = -100;
init_idle();
while(1) {
if(current->need_resched) {
schedule();
......
......@@ -190,6 +190,7 @@ __initfunc(void smp4d_boot_cpus(void))
current->processor = boot_cpu_id;
smp_store_cpu_info(boot_cpu_id);
smp_setup_percpu_timer();
init_idle();
local_flush_cache_all();
if(linux_num_cpus == 1)
return; /* Not an MP box. */
......@@ -211,6 +212,7 @@ __initfunc(void smp4d_boot_cpus(void))
p = task[++cpucount];
p->processor = i;
p->has_cpu = 1; /* we schedule the first task manually */
current_set[i] = p;
for (no = 0; no < linux_num_cpus; no++)
......
......@@ -161,6 +161,7 @@ __initfunc(void smp4m_boot_cpus(void))
smp_store_cpu_info(boot_cpu_id);
set_irq_udt(mid_xlate[boot_cpu_id]);
smp_setup_percpu_timer();
init_idle();
local_flush_cache_all();
if(linux_num_cpus == 1)
return; /* Not an MP box. */
......@@ -180,6 +181,7 @@ __initfunc(void smp4m_boot_cpus(void))
p = task[++cpucount];
p->processor = i;
p->has_cpu = 1; /* we schedule the first task manually */
current_set[i] = p;
/* See trampoline.S for details... */
......
/* $Id: sys_sparc.c,v 1.51 1999/03/20 22:02:00 davem Exp $
/* $Id: sys_sparc.c,v 1.52 1999/05/08 08:09:48 anton Exp $
* linux/arch/sparc/kernel/sys_sparc.c
*
* This file contains various random system calls that
......@@ -231,7 +231,7 @@ c_sys_nis_syscall (struct pt_regs *regs)
if (count++ > 5) return -ENOSYS;
lock_kernel();
printk ("Unimplemented SPARC system call %d\n",(int)regs->u_regs[1]);
printk ("%s[%d]: Unimplemented SPARC system call %d\n", current->comm, current->pid, (int)regs->u_regs[1]);
#ifdef DEBUG_UNIMP_SYSCALL
show_regs (regs);
#endif
......
This diff is collapsed.
......@@ -65,7 +65,7 @@ __initfunc(void cpu_probe(void))
long ver, fpu_vers;
long fprs;
cpuid = smp_processor_id();
cpuid = hard_smp_processor_id();
fprs = fprs_read ();
fprs_write (FPRS_FEF);
......
......@@ -73,6 +73,9 @@ device_scan(unsigned long mem_start))
prom_cpu_nodes[0] = prom_node_cpu;
mem_start = central_probe(mem_start);
cpu_probe();
return central_probe(mem_start);
return mem_start;
}
/* $Id: ebus.c,v 1.35 1999/01/26 14:34:11 jj Exp $
/* $Id: ebus.c,v 1.36 1999/05/04 03:21:42 davem Exp $
* ebus.c: PCI to EBus bridge device.
*
* Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be)
......@@ -35,9 +35,6 @@ extern void prom_ebus_intmap_init(struct linux_ebus *);
#ifdef CONFIG_SUN_OPENPROMIO
extern int openprom_init(void);
#endif
#ifdef CONFIG_SPARCAUDIO
extern int sparcaudio_init(void);
#endif
#ifdef CONFIG_SUN_AUXIO
extern void auxio_probe(void);
#endif
......@@ -399,9 +396,6 @@ __initfunc(void ebus_init(void))
#ifdef CONFIG_SUN_OPENPROMIO
openprom_init();
#endif
#ifdef CONFIG_SPARCAUDIO
sparcaudio_init();
#endif
#ifdef CONFIG_SUN_BPP
bpp_init();
#endif
......
/* $Id: entry.S,v 1.102 1999/03/29 12:38:09 jj Exp $
/* $Id: entry.S,v 1.103 1999/05/08 03:00:21 davem Exp $
* arch/sparc64/kernel/entry.S: Sparc64 trap low-level entry points.
*
* Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu)
......@@ -766,6 +766,7 @@ ret_from_syscall:
*/
#ifdef __SMP__
andn %o7, 0x100, %l0
mov %g5, %o0 /* 'prev' */
call schedule_tail
sth %l0, [%g6 + AOFF_task_tss + AOFF_thread_flags]
#else
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/* $Id: sparc64_ksyms.c,v 1.57 1999/03/14 20:51:28 davem Exp $
/* $Id: sparc64_ksyms.c,v 1.58 1999/05/08 03:00:31 davem Exp $
* arch/sparc64/kernel/sparc64_ksyms.c: Sparc64 specific ksyms support.
*
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
......@@ -90,7 +90,6 @@ extern int __ashrdi3(int, int);
extern void dump_thread(struct pt_regs *, struct user *);
#ifdef __SMP__
extern spinlock_t scheduler_lock;
extern spinlock_t kernel_flag;
extern int smp_num_cpus;
#ifdef SPIN_LOCK_DEBUG
......@@ -120,7 +119,6 @@ __attribute__((section("__ksymtab"))) = \
/* used by various drivers */
#ifdef __SMP__
/* Kernel wide locking */
EXPORT_SYMBOL(scheduler_lock);
EXPORT_SYMBOL(kernel_flag);
/* Software-IRQ BH locking */
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment