Commit 8e16a50d authored by Linus Torvalds's avatar Linus Torvalds

Import 2.1.96pre1

parent 6cfe08d0
......@@ -2398,74 +2398,64 @@ CONFIG_SCSI_AHA1740
want to compile it as a module, say M here and read
Documentation/modules.txt.
Adaptec AIC7xxx support (includes 274x/284x/294x)
Adaptec AIC7xxx chipset SCSI controller support
CONFIG_SCSI_AIC7XXX
Information about this SCSI host adapter is contained in
drivers/scsi/README.aic7xxx and in the SCSI-HOWTO, available via ftp
(user: anonymous) at sunsite.unc.edu:/pub/Linux/docs/HOWTO. Note
that the AHA2920 SCSI host adapter is *not* supported by this
driver; choose "Future Domain 16xx SCSI support" instead. If you
want to compile this driver as a module ( = code which can be
inserted in and removed from the running kernel whenever you want),
say M here and read Documentation/ modules.txt. The module will be
called aic7xxx.o.
Enable tagged command queueing
CONFIG_AIC7XXX_TAGGED_QUEUEING
This option allows you to enable tagged command queueing for this
driver. Some SCSI devices do not properly support this feature.
Tagged command queueing will improve performance.
This is support for the various aic7xxx based Adaptec SCSI controllers.
These include the 274x EISA cards, 284x VLB cards, 294x PCI cards,
394x PCI cards, 3985 PCI card, and several versions of the Adaptec
built-in SCSI controllers on various PC motherboards. Information on
the configuration options for this controller can be found by checking
the README.aic7xxx file, usually in /usr/src/linux/drivers/scsi.
Override driver defaults for commands per LUN
CONFIG_OVERRIDE_CMDS
This option allows you to set the maximum number of SCSI commands
queued per LUN (Logical Unit Number - some physical SCSI devices,
e.g. CD jukeboxes, act logically as several logical units). If you
say N here, the driver will attempt to set the commands per LUN
using its own reasonable heuristic. If you say Y, you can specify
your preference in the next question. If unsure, say N.
Use this option to allow you to override the default maximum number of
commands that a single device on the aic7xxx controller is allowed to have
active at one time. This option only effects tagged queueing capable
devices. The driver uses a "failsafe" value of 8 by default. This is
much lower than many devices can handle, but left in place for safety sake.
NOTE: This does not actually enabled tagged queueing on any particular
device. The driver has changed in this respect. Please see the file
README.aic7xxx in /usr/src/linux/drivers/scsi for more information on how
to get particular devices to use tagged command queueing.
Default: N
Maximum number of commands per LUN
CONFIG_AIC7XXX_CMDS_PER_LUN
By default, we limit the commands per LUN to 2 with or without
tagged queueing enabled. If tagged queueing is enabled, the
sequencer in the host adapter will attempt to send the 2nd command
block to the device while the first command block is still executing
and the device is disconnected. If the devices don't complain, you
can thus try to increase the number of SCSI commands per LUN to more
than 2 in this case. If tagged queueing is disabled, the sequencer
in the host adapter will keep the 2nd command in its input queue
until the first one completes - so it is OK to have more than 1
command queued. However, for host adapters limited to 4 command
blocks (SCB's), you may want to actually decrease the commands per
LUN to 1, if you often have more than 2 devices active at the same
time. This will ensure that there will always be a free SCB for up
to 4 devices active at the same time. When SCB paging is enabled,
set the commands per LUN to 8 or higher (see "SCB paging support"
below). If unsure, go with the default for now.
Enable SCB paging
CONFIG_AIC7XXX_PAGE_ENABLE
This option enables SCB paging. This will increase performance when
tagged queueing is enabled. Note that, if you say Y here, you
should increase the "Maximum number of commands per LUN"
(AIC7XXX_CMDS_PER_LUN) above to 8 as most tagged queueing devices
allow at least this many. Note that EISA and VLB controllers do not
support SCB paging due to chip limitations; enabling it on these
controllers has no effect.
Specify the maximum number of commands per lun you would like to allocate
per device. Reasonable figures are in the range of 14 to 32 commands per
device, but depending on hardware could be increased or decreased from
that figure. If the number is too high for any particular device, the
driver will automatically compensate usually after only 10 minutes of
uptime and will issue a message to alert you to the fact that the number
of commands for that device has been reduced. It will not hinder
performance if a portion of your devices eventually have their commands
per lun reduced, but is a waste of memory if all of your devices end
up reducing this number down to a more reasonable figure. Default: 24
Collect statistics to report in /proc
CONFIG_AIC7XXX_PROC_STATS
This option enables collection of SCSI transfer statistics for the
/proc filesystem. This does affect performance since it has to
maintain statistics. The statistics will appear under
/proc/scsi/aic7xxx. This will only work if you also enable the "proc
filesystem", below.
This option tells the driver to keep track of how many commands have been
sent to each particular device and report that information to the user
via the /proc/scsi/aic7xxx/x file, where x is the number of the aic7xxx
controller you want the information on. This adds a small amount of
overhead to each and every SCSI command the aic7xxx driver handles, so if
you aren't really interested in this information, it is best to leave it
disabled. Default: N
Delay in seconds after SCSI bus reset
CONFIG_AIC7XXX_RESET_DELAY
This option sets the delay in seconds after a SCSI bus reset. If you
don't know what you are doing, go with the default.
This sets how long the driver will wait after resetting the SCSI bus before
attempting to communicate with the devices on the SCSI bus again. This
delay will be used during the reset phase at bootup time as well as after
any reset that might occur during normal operation. Reasonable numbers
range anywhere from 5 to 15 seconds depending on your devices. DAT tape
drives are notorious for needing more time after a bus reset to be
ready for the next command, but most hard drives and CD-ROM devices are
ready in only a few seconds. This option has a maximum upper limit of
20 seconds to avoid bad interactions between the aic7xxx driver and the
rest of the linux kernel. The default value has been reduced. If this
doesn't work with your hardware, try increasing this value. Default: 5
BusLogic SCSI support
CONFIG_SCSI_BUSLOGIC
......
......@@ -5,11 +5,15 @@ drivers.
You can pass parameters to the parport code to override its automatic
detection of your hardware. This is particularly useful if you want
to use IRQs, since in general these can't be autoprobed successfully.
By default IRQs are not used even if they _can_ be probed. This is
because there are a lot of people using the same IRQ for their
parallel port and a sound card or network card.
The parport code is split into two parts: generic (which deals with
port-sharing) and architecture-dependent (which deals with actually
using the port).
Parport as modules
==================
......@@ -20,31 +24,33 @@ If you load the parport code as a module, say
to load the generic parport code. You then must load the
architecture-dependent code with (for example):
# insmod parport_pc.o io=0x378,0x278 irq=7,5
# insmod parport_pc.o io=0x3bc,0x378,0x278 irq=none,7,auto
to tell the parport code that you want three PC-style ports, one at
0x3bc with no IRQ, one at 0x378 using IRQ 7, and one at 0x278 with an
auto-detected IRQ. Currently, PC-style (parport_pc) and Sun Ultra/AX
(parport_ax) hardware is supported; more is in the works.
to tell the parport code that you want two PC-style ports, one at
0x378 using IRQ 7, and one at 0x278 using IRQ 5. Currently, PC-style
(parport_pc) and ARC onboard (parport_arc) parallel ports are
supported.
Kerneld
-------
KMod
----
If you use kerneld, you will find it useful to edit /etc/conf.modules.
If you use kmod, you will find it useful to edit /etc/conf.modules.
Here is an example of the lines that need to be added:
alias parport_lowlevel parport_pc
options parport_pc io=0x378,0x278 irq=7,5
options parport_pc io=0x378,0x278 irq=7,auto
KMod will then automatically load parport_pc (with the options
"io=0x378,0x278 irq=7,auto") whenever a parallel port device driver
(such as lp) is loaded.
Kerneld, in conjunction with parport, will automatically load
parport_pc whenever a parallel port device driver (such as lp) is
loaded.
Parport probe [optional]
-------------
Once the architecture-dependent part of the parport code is loaded
into the kernel, you insert the parport_probe module with:
into the kernel, you can insert the parport_probe module with:
# insmod parport_probe.o
......@@ -53,22 +59,25 @@ message similar to:
parport0: Printer, BJC-210 (Canon)
(If you are using kerneld and have configured parport_probe as a
module, this will just happen.)
(If you are using kmod and have configured parport_probe as a module,
this will just happen.)
Parport, but not as modules
===========================
Parport linked into the kernel statically
=========================================
If you compile the parport code into the kernel, then you can use
kernel boot parameters to get the same effect. Add something like the
following to your LILO command line:
parport=0x378,7 parport=0x278,5
parport=0x3bc parport=0x378,7 parport=0x278,auto
You can have many `parport=...' statements, one for each port you want
to add. Adding `parport=0' to the kernel command-line will disable
parport support entirely.
parport support entirely. Adding `parport=auto' to the kernel
command-line will make parport use any IRQ lines or DMA channels that
it auto-detects.
Files in /proc
==============
......@@ -90,10 +99,10 @@ File: Contents:
and DMA channel.
/proc/parport/0/irq The IRQ that parport is using for that
port (as above). This is in a
separate file to allow you to alter it
by writing a new value in (IRQ number
or "none").
port. This is in a separate file to
allow you to alter it by writing a new
value in (IRQ number or "none").
Device drivers
==============
......@@ -121,7 +130,7 @@ regardless of base address.
Also:
* If you selected the device autoprobe at compile time, you can say
* If you selected the IEEE-1284 autoprobe at compile time, you can say
`lp=auto' on the kernel command line, and lp will create devices
only for those ports that seem to have printers attached.
......@@ -129,10 +138,7 @@ Also:
the command line, or with `insmod plip timid=1' when using modules,
it will avoid any ports that seem to be in use by other devices.
* If your BIOS allows you to engage "ECP mode", you may find that
your port's IRQ can be autoprobed, without having to specify any
parameters.
* IRQ autoprobing works only for a few port types at the moment.
--
Philip.Blundell@pobox.com
......
insmod sound
insmod ad1848
insmod gus io=* irq=* dma=* ...
This loads the driver for the Gravis Ultrasound familily of soundcards.
The gus modules takes the following arguments
io I/O address of the ultrasound card (eg. io=0x220)
irq IRQ of the soundblaster card
dma DMA channel for the soundblaster
dma16 2nd DMA channel, only needed for full duplex operation
type 1 for PnP card
gus16 1 for using 16 bit sampling daughter board
no_wave_dma Set to disable dma usage for wavetable (see note)
db16 ???
no_wave_dma option
This option defaults to a value of 0, which allows the Ultrasound wavetable
DSP to use DMA for for playback and downloading samples. This is the same
as the old behaviour. If set to 1, no DMA is needed for downloading samples,
and allows owners of a GUS MAX to make use of simultanious digital audio
(/dev/dsp), MIDI, and wavetable playback.
If you have problems in recording with GUS MAX, you could try to use
just one 8 bit DMA channel. Recording will not work with one DMA
channel if it's a 16 bit one.
VERSION = 2
PATCHLEVEL = 1
SUBLEVEL = 95
SUBLEVEL = 96
ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/)
......
......@@ -410,7 +410,7 @@ static void layout_dev(struct pci_dev *dev)
pcibios_write_config_dword(bus->number, dev->devfn,
off, base);
handle = HANDLE(bus->number) | base;
dev->base_address[PCI_BASE_INDEX(off)] = handle;
dev->base_address[idx] = handle;
DBG_DEVS(("layout_dev: dev 0x%x MEM @ 0x%lx (0x%x)\n",
dev->device, handle, size));
}
......
......@@ -12,6 +12,9 @@
#
# Copyright (C) 1995, 1996 by Russell King
CFLAGS_PROC :=
ASFLAGS_PROC :=
ifeq ($(CONFIG_CPU_ARM2),y)
PROCESSOR = armo
ASFLAGS_PROC += -m2
......@@ -65,7 +68,6 @@ endif
# ZRELADDR - Compressed kernel relocating address (point at which uncompressed kernel is loaded).
#
HEAD := arch/arm/kernel/head-$(PROCESSOR).o arch/arm/kernel/init_task.o
COMPRESSED_HEAD = head.o
ifeq ($(PROCESSOR),armo)
......@@ -79,11 +81,13 @@ endif
ifeq ($(CONFIG_ARCH_A5K),y)
MACHINE = a5k
ARCHDIR = arc
COMPRESSED_EXTRA = $(TOPDIR)/arch/arm/lib/ll_char_wr.o
endif
ifeq ($(CONFIG_ARCH_ARC),y)
MACHINE = arc
ARCHDIR = arc
COMPRESSED_EXTRA = $(TOPDIR)/arch/arm/lib/ll_char_wr.o
endif
......@@ -96,6 +100,7 @@ endif
ifeq ($(CONFIG_ARCH_RPC),y)
MACHINE = rpc
ARCHDIR = rpc
COMPRESSED_EXTRA = $(TOPDIR)/arch/arm/lib/ll_char_wr.o
ZTEXTADDR = 0x10008000
ZRELADDR = 0x10008000
......@@ -103,6 +108,14 @@ endif
ifeq ($(CONFIG_ARCH_EBSA110),y)
MACHINE = ebsa110
ARCHDIR = ebsa110
ZTEXTADDR = 0x00008000
ZRELADDR = 0x00008000
endif
ifeq ($(CONFIG_ARCH_EBSA285),y)
MACHINE = ebsa285
ARCHDIR = ebsa285
ZTEXTADDR = 0x00008000
ZRELADDR = 0x00008000
endif
......@@ -129,35 +142,55 @@ ifeq ($(CONFIG_FRAME_POINTER),y)
CFLAGS := $(CFLAGS:-fomit-frame-pointer=)
endif
CFLAGS := $(CFLAGS_PROC) $(CFLAGS) -pipe
ASFLAGS := $(ASFLAGS_PROC) $(ASFLAGS) -D__ASSEMBLY__
ASFLAGS := $(ASFLAGS_PROC) $(ASFLAGS)
LINKFLAGS = -T $(TOPDIR)/arch/arm/vmlinux.lds -e stext -Ttext $(TEXTADDR)
ZLINKFLAGS = -Ttext $(ZTEXTADDR)
SUBDIRS := $(SUBDIRS:drivers=) arch/arm/lib arch/arm/kernel arch/arm/mm arch/arm/drivers
HEAD := arch/arm/kernel/head-$(PROCESSOR).o arch/arm/kernel/init_task.o
CORE_FILES := arch/arm/kernel/kernel.o arch/arm/mm/mm.o $(CORE_FILES)
LIBS := arch/arm/lib/lib.a $(LIBS) $(GCCLIB)
DRIVERS := arch/arm/drivers/block/block.a \
arch/arm/drivers/char/char.a \
drivers/misc/misc.a \
arch/arm/drivers/net/net.a
BLOCK_DRIVERS := arch/arm/drivers/block/block.a
CDROM_DRIVERS := drivers/cdrom/cdrom.a
CHAR_DRIVERS := arch/arm/drivers/char/char.a
MISC_DRIVERS := drivers/misc/misc.a
NET_DRIVERS := drivers/net/net.a
PARIDE_DRIVERS := drivers/block/paride/paride.a
PCI_DRIVERS := drivers/pci/pci.a
SCSI_DRIVERS := drivers/scsi/scsi.a
SOUND_DRIVERS := drivers/sound/sound.a
ifeq ($(CONFIG_SCSI),y)
DRIVERS := $(DRIVERS) arch/arm/drivers/scsi/scsi.a
ifeq ($(CONFIG_ARCH_ACORN),y)
BLOCK_DRIVERS += drivers/acorn/block/acorn-block.a
CHAR_DRIVERS += drivers/acorn/char/acorn-char.a
NET_DRIVERS += drivers/acorn/net/acorn-net.a drivers/net/net.a
SCSI_DRIVERS += drivers/acorn/scsi/acorn-scsi.a
endif
DRIVERS := $(BLOCK_DRIVERS) $(CHAR_DRIVERS) $(MISC_DRIVERS) $(NET_DRIVERS)
ifeq ($(CONFIG_SCSI),y)
DRIVERS := $(DRIVERS) $(SCSI_DRIVERS)
endif
ifneq ($(CONFIG_CD_NO_IDESCSI)$(CONFIG_BLK_DEV_IDECD)$(CONFIG_BLK_DEV_SR),)
DRIVERS := $(DRIVERS) drivers/cdrom/cdrom.a
DRIVERS := $(DRIVERS) $(CDROM_DRIVERS)
endif
ifdef CONFIG_PCI
DRIVERS := $(DRIVERS) $(PCI_DRIVERS)
endif
ifeq ($(CONFIG_SOUND),y)
DRIVERS := $(DRIVERS) arch/arm/drivers/sound/sound.a
DRIVERS := $(DRIVERS) $(SOUND_DRIVERS)
endif
ifeq ($(CONFIG_PARIDE),y)
DRIVERS := $(DRIVERS) $(PARIDE_DRIVERS)
endif
symlinks::
$(RM) include/asm-arm/arch include/asm-arm/proc
(cd include/asm-arm; ln -sf arch-$(MACHINE) arch; ln -sf proc-$(PROCESSOR) proc)
(cd include/asm-arm; ln -sf arch-$(ARCHDIR) arch; ln -sf proc-$(PROCESSOR) proc)
# Once we've finished integrating the sources, the @$(MAKE) will disappear
mrproper::
rm -f include/asm-arm/arch include/asm-arm/proc
@$(MAKE) -C arch/$(ARCH)/drivers mrproper
......@@ -183,7 +216,6 @@ install: vmlinux
@$(MAKEBOOT) install
# My testing targets (that short circuit a few dependencies)
#
zImg:; @$(MAKEBOOT) zImage
Img:; @$(MAKEBOOT) Image
i:; @$(MAKEBOOT) install
......@@ -191,8 +223,7 @@ zi:; @$(MAKEBOOT) zinstall
archclean:
@$(MAKEBOOT) clean
@$(MAKE) -C arch/arm/lib clean
$(RM) arch/arm/lib/constants.h
archdep:
@$(MAKEBOOT) dep
sed -e /^MACHINE..*=/s,= .*,= rpc,;/^PROCESSOR..*=/s,= .*,= armv, linux/arch/arm/Makefile.normal
......@@ -25,11 +25,8 @@ install: $(CONFIGURE) Image
zinstall: $(CONFIGURE) zImage
sh ./install.sh $(VERSION).$(PATCHLEVEL).$(SUBLEVEL) zImage $(TOPDIR)/System.map "$(INSTALL_PATH)"
tools/build: tools/build.c
$(HOSTCC) $(HOSTCFLAGS) -o $@ $< -I$(TOPDIR)/include
clean:
rm -f Image zImage tools/build
rm -f Image zImage
@$(MAKE) -C compressed clean
dep:
......@@ -26,7 +26,7 @@ piggy.o: $(SYSTEM)
$(OBJCOPY) $(SYSTEM) $$tmppiggy; \
gzip -f -9 < $$tmppiggy > $$tmppiggy.gz; \
echo "SECTIONS { .data : { input_len = .; LONG(input_data_end - input_data) input_data = .; *(.data) input_data_end = .; }}" > $$tmppiggy.lnk; \
$(LD) -m elf_arm -r -o piggy.o -b binary $$tmppiggy.gz -b elf32-arm -T $$tmppiggy.lnk; \
$(LD) -r -o piggy.o -b binary $$tmppiggy.gz -b elf32-arm -T $$tmppiggy.lnk; \
rm -f $$tmppiggy $$tmppiggy.gz $$tmppiggy.lnk;
clean:; rm -f vmlinux core
......
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <a.out.h>
typedef unsigned char byte;
typedef unsigned short word;
typedef unsigned long u32;
void die(const char * str, ...)
{
va_list args;
va_start(args, str);
vfprintf(stderr, str, args);
fputc('\n', stderr);
exit (1);
}
int main(int argc, char **argv)
{
void *data;
struct exec ex;
FILE *f;
int totlen;
if (argc < 2) {
fprintf(stderr, "Usage: build kernel-name\n");
exit(1);
}
f = fopen(argv[1], "rb");
if (!f)
die("Unable to open `%s': %m", argv[1]);
fread(&ex, 1, sizeof(ex), f);
if(N_MAGIC(ex) == ZMAGIC) {
fseek(f, 4096, SEEK_SET);
totlen = ex.a_text + ex.a_data;
} else
if(N_MAGIC(ex) == QMAGIC) {
unsigned long my_header;
fseek(f, 4, SEEK_SET);
my_header = 0xea000006;
fwrite(&my_header, 4, 1, stdout);
totlen = ex.a_text + ex.a_data - 4;
} else {
fprintf(stderr, "Unacceptable a.out header on kernel\n");
fclose(f);
exit(1);
}
fprintf(stderr, "Kernel is %dk (%dk text, %dk data, %dk bss)\n",
(ex.a_text + ex.a_data + ex.a_bss)/1024,
ex.a_text/1024, ex.a_data/1024, ex.a_bss/1024);
data = malloc(totlen);
fread(data, 1, totlen, f);
fwrite(data, 1, totlen, stdout);
free(data);
fclose(f);
fflush(stdout);
return 0;
}
......@@ -7,38 +7,25 @@ mainmenu_name "Linux Kernel Configuration"
define_bool CONFIG_ARM y
mainmenu_option next_comment
comment 'Code maturity level options'
bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL
endmenu
mainmenu_option next_comment
comment 'Loadable module support'
bool 'Enable loadable module support' CONFIG_MODULES
if [ "$CONFIG_MODULES" = "y" ]; then
bool 'Set version information on all symbols for modules' CONFIG_MODVERSIONS
bool 'Kernel module loader' CONFIG_KMOD
fi
endmenu
mainmenu_option next_comment
comment 'General setup'
comment 'System type and processor type'
choice 'ARM system type' \
"Archimedes CONFIG_ARCH_ARC \
A5000 CONFIG_ARCH_A5K \
RiscPC CONFIG_ARCH_RPC \
EBSA-110 CONFIG_ARCH_EBSA110 \
EBSA-285 CONFIG_ARCH_EBSA285 \
NexusPCI CONFIG_ARCH_NEXUSPCI" RiscPC
if [ "$CONFIG_ARCH_ARC" = "y" -o "$CONFIG_ARCH_A5K" = "y" -o "$CONFIG_ARCH_RPC" = "y" ]; then
define_bool CONFIG_ARCH_ACORN y
else
define_bool CONFIG_ARCH_ACORN n
fi
if [ "$CONFIG_ARCH_NEXUSPCI" = "y" ]; then
if [ "$CONFIG_ARCH_NEXUSPCI" = "y" -o "$CONFIG_ARCH_EBSA285" = "y" ]; then
define_bool CONFIG_PCI y
else
define_bool CONFIG_PCI n
fi
if [ "$CONFIG_ARCH_NEXUSPCI" = "y" -o "$CONFIG_ARCH_EBSA110" = "y" ]; then
if [ "$CONFIG_ARCH_NEXUSPCI" = "y" -o "$CONFIG_ARCH_EBSA110" = "y" -o "$CONFIG_ARCH_EBSA285" = "y" ]; then
define_bool CONFIG_CPU_SA110 y
else
if [ "$CONFIG_ARCH_A5K" = "y" ]; then
......@@ -51,11 +38,31 @@ else
StrongARM CONFIG_CPU_SA110" StrongARM
fi
fi
endmenu
mainmenu_option next_comment
comment 'Code maturity level options'
bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL
endmenu
mainmenu_option next_comment
comment 'Loadable module support'
bool 'Enable loadable module support' CONFIG_MODULES
if [ "$CONFIG_MODULES" = "y" ]; then
bool 'Set version information on all symbols for modules' CONFIG_MODVERSIONS
bool 'Kernel module loader' CONFIG_KMOD
fi
endmenu
mainmenu_option next_comment
comment 'General setup'
bool 'Compile kernel with frame pointer (for useful debugging)' CONFIG_FRAME_POINTER
bool 'Use new compilation options (for GCC 2.8)' CONFIG_BINUTILS_NEW
bool 'Debug kernel errors' CONFIG_DEBUG_ERRORS
bool 'Networking support' CONFIG_NET
bool 'System V IPC' CONFIG_SYSVIPC
# This needs kernel/acct.c to be updated
#bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT
bool 'Sysctl support' CONFIG_SYSCTL
tristate 'Kernel support for a.out binaries' CONFIG_BINFMT_AOUT
tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
......@@ -70,6 +77,7 @@ fi
endmenu
source arch/arm/drivers/block/Config.in
source drivers/acorn/block/Config.in
if [ "$CONFIG_NET" = "y" ]; then
source net/Config.in
......@@ -81,7 +89,7 @@ comment 'SCSI support'
tristate 'SCSI support?' CONFIG_SCSI
if [ "$CONFIG_SCSI" != "n" ]; then
source arch/arm/drivers/scsi/Config.in
source drivers/scsi/Config.in
fi
endmenu
......@@ -91,7 +99,7 @@ if [ "$CONFIG_NET" = "y" ]; then
bool 'Network device support?' CONFIG_NETDEVICES
if [ "$CONFIG_NETDEVICES" = "y" ]; then
source arch/arm/drivers/net/Config.in
source drivers/net/Config.in
fi
endmenu
fi
......@@ -128,7 +136,7 @@ if [ "$CONFIG_ARCH_ACORN" = "y" ]; then
tristate 'Sound support' CONFIG_SOUND
if [ "$CONFIG_SOUND" != "n" ]; then
source arch/arm/drivers/sound/Config.in
source drivers/sound/Config.in
fi
endmenu
fi
......
......@@ -31,6 +31,7 @@ CONFIG_ARCH_ACORN=y
CONFIG_CPU_SA110=y
CONFIG_FRAME_POINTER=y
# CONFIG_BINUTILS_NEW is not set
CONFIG_DEBUG_ERRORS=y
CONFIG_NET=y
CONFIG_SYSVIPC=y
CONFIG_SYSCTL=y
......@@ -76,7 +77,7 @@ CONFIG_BLK_DEV_PART=y
#
# Networking options
#
CONFIG_PACKET=m
# CONFIG_PACKET is not set
# CONFIG_NETLINK is not set
# CONFIG_FIREWALL is not set
# CONFIG_NET_ALIAS is not set
......@@ -112,8 +113,11 @@ CONFIG_IP_NOSR=y
# CONFIG_BRIDGE is not set
# CONFIG_LLC is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_FASTROUTE is not set
# CONFIG_NET_HW_FLOWCONTROL is not set
# CONFIG_CPU_IS_SLOW is not set
# CONFIG_NET_SCHED is not set
# CONFIG_NET_PROFILE is not set
#
# SCSI support
......@@ -149,7 +153,6 @@ CONFIG_SCSI_POWERTECSCSI=m
# The following drives are not fully supported
#
CONFIG_SCSI_CUMANA_1=m
CONFIG_SCSI_ECOSCSI=m
CONFIG_SCSI_OAK1=m
CONFIG_SCSI_PPA=m
CONFIG_SCSI_PPA_HAVE_PEDANTIC=2
......@@ -199,6 +202,7 @@ CONFIG_LOCKD=y
# CONFIG_AUTOFS_FS is not set
# CONFIG_UFS_FS is not set
CONFIG_ADFS_FS=y
CONFIG_ADFS_FS=y
# CONFIG_MAC_PARTITION is not set
CONFIG_NLS=y
......@@ -252,10 +256,10 @@ CONFIG_RPCMOUSE=y
#
# Sound
#
# CONFIG_SOUND is not set
# CONFIG_VIDC is not set
# CONFIG_AUDIO is not set
# DSP_BUFFSIZE is not set
CONFIG_SOUND=m
CONFIG_VIDC=y
CONFIG_AUDIO=y
DSP_BUFFSIZE=65536
#
# Kernel hacking
......
......@@ -19,15 +19,24 @@ else
O_OBJS += armksyms.o
endif
ifdef CONFIG_PCI
O_OBJS += bios32.o
endif
ifdef CONFIG_ARCH_ACORN
O_OBJS += setup.o ecard.o iic.o dma.o
ifdef CONFIG_ARCH_ARC
O_OBJS += oldlatches.o
endif
O_OBJS += dma-$(MACHINE).o
endif
ifeq ($(MACHINE),ebsa110)
O_OBJS += setup-ebsa110.o dma.o
O_OBJS += setup-ebsa110.o dma.o dma-dummy.o
endif
ifeq ($(MACHINE),ebsa285)
O_OBJS += dma.o dma-dummy.o leds-ebsa285.o setup-ebsa110.o
endif
ifeq ($(MACHINE),nexuspci)
......@@ -37,9 +46,12 @@ endif
$(HEAD_OBJ): $(HEAD_OBJ:.o=.S)
$(CC) -D__ASSEMBLY__ -traditional -c $(HEAD_OBJ:.o=.S) -o $@
$(ENTRY_OBJ): $(ENTRY_OBJ:.o=.S)
$(CC) $(CFLAGS) -D__ASSEMBLY__ -c $(ENTRY_OBJ:.o=.S) -o $@
include $(TOPDIR)/Rules.make
$(ENTRY_OBJ:.o=.S): ../lib/constants.h
$(ENTRY_OBJ): ../lib/constants.h
.PHONY: ../lib/constants.h
......
......@@ -12,7 +12,6 @@
#include <asm/dma.h>
#include <asm/pgtable.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
extern void dump_thread(struct pt_regs *, struct user *);
extern int dump_fpu(struct pt_regs *, struct user_fp_struct *);
......@@ -64,7 +63,6 @@ extern void fp_send_sig(int);
EXPORT_SYMBOL(dump_thread);
EXPORT_SYMBOL(dump_fpu);
EXPORT_SYMBOL(udelay);
EXPORT_SYMBOL(dma_str);
EXPORT_SYMBOL(xchg_str);
/* expansion card support */
......@@ -78,26 +76,39 @@ EXPORT_SYMBOL(ecard_address);
/* processor dependencies */
EXPORT_SYMBOL(processor);
/* irq */
EXPORT_SYMBOL(enable_irq);
EXPORT_SYMBOL(disable_irq);
/* io */
EXPORT_SYMBOL(outswb);
EXPORT_SYMBOL(outsw);
EXPORT_SYMBOL(inswb);
EXPORT_SYMBOL(insw);
#ifdef CONFIG_ARCH_RPC
EXPORT_SYMBOL(drambank);
/* address translation */
#ifndef __virt_to_phys__is_a_macro
EXPORT_SYMBOL(__virt_to_phys);
#endif
#ifndef __phys_to_virt__is_a_macro
EXPORT_SYMBOL(__phys_to_virt);
#endif
#ifndef __virt_to_bus__is_a_macro
EXPORT_SYMBOL(__virt_to_bus);
#endif
#ifndef __bus_to_virt__is_a_macro
EXPORT_SYMBOL(__bus_to_virt);
#endif
EXPORT_SYMBOL(quicklists);
EXPORT_SYMBOL(__bad_pmd);
EXPORT_SYMBOL(__bad_pmd_kernel);
/* dma */
EXPORT_SYMBOL(dma_str);
EXPORT_SYMBOL(enable_dma);
EXPORT_SYMBOL(set_dma_mode);
EXPORT_SYMBOL(disable_dma);
EXPORT_SYMBOL(set_dma_addr);
EXPORT_SYMBOL(set_dma_count);
EXPORT_SYMBOL(set_dma_mode);
EXPORT_SYMBOL(get_dma_residue);
EXPORT_SYMBOL(set_dma_sg);
/*
* floating point math emulator support.
......@@ -182,7 +193,3 @@ EXPORT_SYMBOL(change_bit);
EXPORT_SYMBOL(test_and_change_bit);
EXPORT_SYMBOL(find_first_zero_bit);
EXPORT_SYMBOL(find_next_zero_bit);
#if CONFIG_PCI
EXPORT_SYMBOL(pci_devices);
#endif
/*
* arch/arm/kernel/bios32.c: PCI functions for ARM
*
* Copyright (C) 1998 Russell King
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/init.h>
int pcibios_present(void)
{
return 1;
}
static unsigned long pcibios_base_address(unsigned char dev_fn)
{
int slot = PCI_SLOT(dev_fn);
if (slot < 4)
return 0xf8000000 + (1 << (19 - slot));
else
return 0;
}
int pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn,
unsigned char where, unsigned char *val)
{
unsigned long addr = pcibios_base_address(dev_fn);
unsigned char v;
if (addr) {
__asm__("ldr%?b %0, [%1, %2]"
: "=r" (v)
: "r" (addr), "r" (where));
*val = v;
} else
*val = 0xff;
return PCIBIOS_SUCCESSFUL;
}
int pcibios_read_config_word(unsigned char bus, unsigned char dev_fn,
unsigned char where, unsigned short *val)
{
unsigned long addr = pcibios_base_address(dev_fn);
unsigned short v;
if (addr) {
__asm__("ldrh%? %0, [%1, %2]"
: "=r" (v)
: "r" (addr), "r" (where));
*val = v;
} else
*val = 0xffff;
return PCIBIOS_SUCCESSFUL;
}
int pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn,
unsigned char where, unsigned int *val)
{
unsigned long addr = pcibios_base_address(dev_fn);
unsigned int v;
if (addr) {
__asm__("ldr%? %0, [%1, %2]"
: "=r" (v)
: "r" (addr), "r" (where));
*val = v;
} else
*val = 0xffffffff;
return PCIBIOS_SUCCESSFUL;
}
int pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn,
unsigned char where, unsigned char val)
{
unsigned long addr = pcibios_base_address(dev_fn);
if (addr)
__asm__("str%?b %0, [%1, %2]"
: : "r" (val), "r" (addr), "r" (where));
return PCIBIOS_SUCCESSFUL;
}
int pcibios_write_config_word(unsigned char bus, unsigned char dev_fn,
unsigned char where, unsigned short val)
{
unsigned long addr = pcibios_base_address(dev_fn);
if (addr)
__asm__("strh%? %0, [%1, %2]"
: : "r" (val), "r" (addr), "r" (where));
return PCIBIOS_SUCCESSFUL;
}
int pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn,
unsigned char where, unsigned int val)
{
unsigned long addr = pcibios_base_address(dev_fn);
if (addr)
__asm__("str%? %0, [%1, %2]"
: : "r" (val), "r" (addr), "r" (where));
return PCIBIOS_SUCCESSFUL;
}
static int irq[] = { 18, 8, 9, 11 };
__initfunc(void pcibios_fixup(void))
{
struct pci_dev *dev;
unsigned char pin;
for (dev = pci_devices; dev; dev = dev->next) {
pcibios_read_config_byte(dev->bus->number,
dev->devfn,
PCI_INTERRUPT_PIN,
&pin);
dev->irq = irq[(PCI_SLOT(dev->devfn) + pin) & 3];
pcibios_write_config_byte(dev->bus->number,
dev->devfn,
PCI_INTERRUPT_LINE,
dev->irq);
printk("PCI: %02x:%02x [%04x/%04x] pin %d irq %d\n",
dev->bus->number, dev->devfn,
dev->vendor, dev->device,
pin, dev->irq);
}
}
__initfunc(void pcibios_init(void))
{
int rev;
rev = *(unsigned char *)0xfe000008;
printk("DEC21285 PCI revision %02X\n", rev);
}
__initfunc(char *pcibios_setup(char *str))
{
return str;
}
/*
* arch/arm/kernel/dma-a5k.c
*
* Copyright (C) 1998 Russell King
*
* DMA functions specific to A5000 architecture
*/
#include <linux/sched.h>
#include <linux/init.h>
#include <asm/dma.h>
#include <asm/io.h>
#include <asm/hardware.h>
#include "dma.h"
int arch_request_dma(dmach_t channel, dma_t *dma)
{
if (channel == DMA_VIRTUAL_FLOPPY0)
return 0;
else
return -EINVAL;
}
void arch_free_dma(dmach_t channel, dma_t *dma)
{
if (channel != DMA_VIRTUAL_FLOPPY0)
printk ("arch_free_dma: invalid channel %d\n", channel);
}
int arch_get_dma_residue(dmach_t channel, dma_t *dma)
{
if (channel != DMA_VIRTUAL_FLOPPY0)
printk ("arch_dma_count: invalid channel %d\n", dmanr);
else {
extern int floppy_fiqresidual(void);
return floppy_fiqresidual();
}
return 0;
}
void arch_enable_dma(dmach_t channel, dma_t *dma)
{
if (channel != DMA_VIRTUAL_FLOPPY0)
printk ("arch_enable_dma: invalid channel %d\n", channel);
else {
void *fiqhandler_start;
unsigned int fiqhandler_length;
extern void floppy_fiqsetup (unsigned long len, unsigned long addr,
unsigned long port);
if (dma->dma_mode == DMA_MODE_READ) {
extern unsigned char floppy_fiqin_start, floppy_fiqin_end;
fiqhandler_start = &floppy_fiqin_start;
fiqhandler_length = &floppy_fiqin_end - &floppy_fiqin_start;
} else {
extern unsigned char floppy_fiqout_start, floppy_fiqout_end;
fiqhandler_start = &floppy_fiqout_start;
fiqhandler_length = &floppy_fiqout_end - &floppy_fiqout_start;
}
memcpy ((void *)0x1c, fiqhandler_start, fiqhandler_length);
flush_page_to_ram(0);
floppy_fiqsetup (dma->buf.length, __bus_to_virt(dma->buf.address), (int)PCIO_FLOPPYDMABASE);
enable_irq (dma->dma_irq);
}
}
void arch_disable_dma(dmach_t channel, dma_t *dma)
{
if (channel != DMA_VIRTUAL_FLOPPY0)
printk ("arch_disable_dma: invalid channel %d\n", channel);
else
disable_irq (dma->dma_irq);
}
__initfunc(void arch_dma_init(dma_t *dma))
{
dma[DMA_VIRTUAL_FLOPPY0].dma_irq = 64;
}
/*
* arch/arm/kernel/dma-arc.c
*
* Copyright (C) 1998 Dave Gilbert / Russell King
*
* DMA functions specific to Archimedes architecture
*/
#include <linux/sched.h>
#include <linux/init.h>
#include <asm/dma.h>
#include <asm/io.h>
#include <asm/hardware.h>
#include "dma.h"
int arch_request_dma(dmach_t channel, dma_t *dma)
{
if (channel == DMA_VIRTUAL_FLOPPY0 ||
channel == DMA_VIRTUAL_FLOPPY1)
return 0;
else
return -EINVAL;
}
void arch_free_dma(dmach_t channel, dma_t *dma)
{
if (channel != DMA_VIRTUAL_FLOPPY0 &&
channel != DMA_VIRTUAL_FLOPPY1)
return 0;
else
return -EINVAL;
}
void arch_enable_dma(dmach_t channel, dma_t *dma)
{
switch (channel) {
case DMA_VIRTUAL_FLOPPY0: { /* Data DMA */
switch (dma->dma_mode) {
case DMA_MODE_READ: /* read */
{
extern unsigned char fdc1772_dma_read, fdc1772_dma_read_end;
extern void fdc1772_setupdma(unsigned int count,unsigned int addr);
unsigned long flags;
#ifdef DEBUG
printk("enable_dma fdc1772 data read\n");
#endif
save_flags(flags);
cliIF();
memcpy ((void *)0x1c, (void *)&fdc1772_dma_read,
&fdc1772_dma_read_end - &fdc1772_dma_read);
fdc1772_setupdma(dma->buf.length, __bus_to_virt(dma->buf.address)); /* Sets data pointer up */
enable_irq (64);
restore_flags(flags);
}
break;
case DMA_MODE_WRITE: /* write */
{
extern unsigned char fdc1772_dma_write, fdc1772_dma_write_end;
extern void fdc1772_setupdma(unsigned int count,unsigned int addr);
unsigned long flags;
#ifdef DEBUG
printk("enable_dma fdc1772 data write\n");
#endif
save_flags(flags);
cliIF();
memcpy ((void *)0x1c, (void *)&fdc1772_dma_write,
&fdc1772_dma_write_end - &fdc1772_dma_write);
fdc1772_setupdma(dma->buf.length, __bus_to_virt(dma->buf.address)); /* Sets data pointer up */
enable_irq (64);
restore_flags(flags);
}
break;
default:
printk ("enable_dma: dma%d not initialised\n", channel);
return;
}
}
break;
case DMA_VIRTUAL_FLOPPY1: { /* Command end FIQ - actually just sets a flag */
/* Need to build a branch at the FIQ address */
extern void fdc1772_comendhandler(void);
unsigned long flags;
/*printk("enable_dma fdc1772 command end FIQ\n");*/
save_flags(flags);
cliIF();
*((unsigned int *)0x1c)=0xea000000 | (((unsigned int)fdc1772_comendhandler-(0x1c+8))/4); /* B fdc1772_comendhandler */
restore_flags(flags);
}
break;
}
}
void arch_disable_dma(dmach_t channel, dma_t *dma)
{
if (channel != DMA_VIRTUAL_FLOPPY0 &&
channel != DMA_VIRTUAL_FLOPPY1)
printk("arch_disable_dma: invalid channel %d\n", channel);
else
disable_irq(dma->dma_irq);
}
__initfunc(void arch_dma_init(dma_t *dma))
{
dma[DMA_VIRTUAL_FLOPPY0].dma_irq = 64;
dma[DMA_VIRTUAL_FLOPPY1].dma_irq = 65;
}
/*
* arch/arm/kernel/dma-dummy.c
*
* Copyright (C) 1998 Russell King
*
* Dummy DMA functions
*/
#include <linux/sched.h>
#include <linux/init.h>
#include <asm/dma.h>
#include <asm/io.h>
#include <asm/hardware.h>
#include "dma.h"
int arch_request_dma(dmach_t channel, dma_t *dma, const char *devname)
{
return -EINVAL;
}
void arch_free_dma(dmach_t channel, dma_t *dma)
{
printk ("arch_free_dma: invalid channel %d\n", channel);
}
void arch_enable_dma(dmach_t channel, dma_t *dma)
{
printk ("arch_enable_dma: invalid channel %d\n", channel);
}
void arch_disable_dma(dmach_t channel, dma_t *dma)
{
printk ("arch_disable_dma: invalid channel %d\n", channel);
}
int arch_get_dma_residue(dmach_t channel, dma_t *dma)
{
printk ("arch_get_dma_residue: invalid channel %d\n", channel);
return 0;
}
__initfunc(void arch_dma_init(dma_t *dma))
{
}
/*
* arch/arm/kernel/dma-rpc.c
*
* Copyright (C) 1998 Russell King
*
* DMA functions specific to RiscPC architecture
*/
#include <linux/sched.h>
#include <linux/malloc.h>
#include <linux/mman.h>
#include <linux/init.h>
#include <asm/page.h>
#include <asm/pgtable.h>
#include <asm/dma.h>
#include <asm/io.h>
#include <asm/hardware.h>
#include <asm/uaccess.h>
#include "dma.h"
#if 0
typedef enum {
dma_size_8 = 1,
dma_size_16 = 2,
dma_size_32 = 4,
dma_size_128 = 16
} dma_size_t;
typedef struct {
dma_size_t transfersize;
} dma_t;
#endif
#define TRANSFER_SIZE 2
#define CURA (0)
#define ENDA ((IOMD_IO0ENDA - IOMD_IO0CURA) << 2)
#define CURB ((IOMD_IO0CURB - IOMD_IO0CURA) << 2)
#define ENDB ((IOMD_IO0ENDB - IOMD_IO0CURA) << 2)
#define CR ((IOMD_IO0CR - IOMD_IO0CURA) << 2)
#define ST ((IOMD_IO0ST - IOMD_IO0CURA) << 2)
#define state_prog_a 0
#define state_wait_a 1
#define state_wait_b 2
static void arch_get_next_sg(dmasg_t *sg, dma_t *dma)
{
unsigned long end, offset, flags = 0;
if (dma->sg) {
sg->address = dma->sg->address;
offset = sg->address & ~PAGE_MASK;
end = offset + dma->sg->length;
if (end > PAGE_SIZE)
end = PAGE_SIZE;
if (offset + (int) TRANSFER_SIZE > end)
flags |= DMA_END_L;
sg->length = end - TRANSFER_SIZE;
dma->sg->length -= end - offset;
dma->sg->address += end - offset;
if (dma->sg->length == 0) {
if (dma->sgcount > 1) {
dma->sg++;
dma->sgcount--;
} else {
dma->sg = NULL;
flags |= DMA_END_S;
}
}
} else {
flags = DMA_END_S | DMA_END_L;
sg->address = 0;
sg->length = 0;
}
sg->length |= flags;
}
static inline void arch_setup_dma_a(dmasg_t *sg, dma_t *dma)
{
outl_t(sg->address, dma->dma_base + CURA);
outl_t(sg->length, dma->dma_base + ENDA);
}
static inline void arch_setup_dma_b(dmasg_t *sg, dma_t *dma)
{
outl_t(sg->address, dma->dma_base + CURB);
outl_t(sg->length, dma->dma_base + ENDB);
}
static void arch_dma_handle(int irq, void *dev_id, struct pt_regs *regs)
{
dma_t *dma = (dma_t *)dev_id;
unsigned int status = 0, no_buffer = dma->sg == NULL;
do {
switch (dma->state) {
case state_prog_a:
arch_get_next_sg(&dma->cur_sg, dma);
arch_setup_dma_a(&dma->cur_sg, dma);
dma->state = state_wait_a;
case state_wait_a:
status = inb_t(dma->dma_base + ST);
switch (status & (DMA_ST_OFL|DMA_ST_INT|DMA_ST_AB)) {
case DMA_ST_OFL|DMA_ST_INT:
arch_get_next_sg(&dma->cur_sg, dma);
arch_setup_dma_a(&dma->cur_sg, dma);
break;
case DMA_ST_INT:
arch_get_next_sg(&dma->cur_sg, dma);
arch_setup_dma_b(&dma->cur_sg, dma);
dma->state = state_wait_b;
break;
case DMA_ST_OFL|DMA_ST_INT|DMA_ST_AB:
arch_setup_dma_b(&dma->cur_sg, dma);
dma->state = state_wait_b;
break;
}
break;
case state_wait_b:
status = inb_t(dma->dma_base + ST);
switch (status & (DMA_ST_OFL|DMA_ST_INT|DMA_ST_AB)) {
case DMA_ST_OFL|DMA_ST_INT|DMA_ST_AB:
arch_get_next_sg(&dma->cur_sg, dma);
arch_setup_dma_b(&dma->cur_sg, dma);
break;
case DMA_ST_INT|DMA_ST_AB:
arch_get_next_sg(&dma->cur_sg, dma);
arch_setup_dma_a(&dma->cur_sg, dma);
dma->state = state_wait_a;
break;
case DMA_ST_OFL|DMA_ST_INT:
arch_setup_dma_a(&dma->cur_sg, dma);
dma->state = state_wait_a;
break;
}
break;
}
} while (dma->sg && (status & DMA_ST_INT));
if (!no_buffer)
enable_irq(irq);
}
int arch_request_dma(dmach_t channel, dma_t *dma, const char *dev_name)
{
unsigned long flags;
int ret;
switch (channel) {
case DMA_0:
case DMA_1:
case DMA_2:
case DMA_3:
case DMA_S0:
case DMA_S1:
save_flags_cli(flags);
ret = request_irq(dma->dma_irq, arch_dma_handle, SA_INTERRUPT, dev_name, dma);
if (!ret)
disable_irq(dma->dma_irq);
restore_flags(flags);
break;
case DMA_VIRTUAL_FLOPPY:
case DMA_VIRTUAL_SOUND:
ret = 0;
break;
default:
ret = -EINVAL;
break;
}
return ret;
}
void arch_free_dma(dmach_t channel, dma_t *dma)
{
switch (channel) {
case DMA_0:
case DMA_1:
case DMA_2:
case DMA_3:
case DMA_S0:
case DMA_S1:
free_irq(dma->dma_irq, dma);
break;
default:
break;
}
}
int arch_get_dma_residue(dmach_t channel, dma_t *dma)
{
int residue = 0;
switch (channel) {
case DMA_0: /* Physical DMA channels */
case DMA_1:
case DMA_2:
case DMA_3:
case DMA_S0:
case DMA_S1:
break;
case DMA_VIRTUAL_FLOPPY: {
extern int floppy_fiqresidual(void);
residue = floppy_fiqresidual();
}
break;
}
return residue;
}
void arch_enable_dma(dmach_t channel, dma_t *dma)
{
unsigned long dma_base = dma->dma_base;
unsigned int ctrl;
switch (channel) {
case DMA_0: /* Physical DMA channels */
case DMA_1:
case DMA_2:
case DMA_3:
case DMA_S0:
case DMA_S1:
ctrl = TRANSFER_SIZE | DMA_CR_E;
if (dma->invalid) {
dma->invalid = 0;
outb_t(DMA_CR_C, dma_base + CR);
dma->state = state_prog_a;
}
if (dma->dma_mode == DMA_MODE_READ)
ctrl |= DMA_CR_D;
outb_t(ctrl, dma_base + CR);
enable_irq(dma->dma_irq);
break;
case DMA_VIRTUAL_FLOPPY: {
void *fiqhandler_start;
unsigned int fiqhandler_length;
extern void floppy_fiqsetup(unsigned long len, unsigned long addr,
unsigned long port);
if (dma->dma_mode == DMA_MODE_READ) {
extern unsigned char floppy_fiqin_start, floppy_fiqin_end;
fiqhandler_start = &floppy_fiqin_start;
fiqhandler_length = &floppy_fiqin_end - &floppy_fiqin_start;
} else {
extern unsigned char floppy_fiqout_start, floppy_fiqout_end;
fiqhandler_start = &floppy_fiqout_start;
fiqhandler_length = &floppy_fiqout_end - &floppy_fiqout_start;
}
/* Allow access to page 0 via domains */
__asm__ __volatile__("mcr p15, 0, %0, c3, c0" :
: "r" (DOMAIN_USER_MANAGER |
DOMAIN_KERNEL_CLIENT |
DOMAIN_IO_CLIENT));
memcpy((void *)0x1c, fiqhandler_start, fiqhandler_length);
/* set domain register to normal */
set_fs(get_fs());
flush_page_to_ram(0);
floppy_fiqsetup(dma->buf.length, __bus_to_virt(dma->buf.address), (int)PCIO_FLOPPYDMABASE);
enable_irq(dma->dma_irq);
}
break;
default:
break;
}
}
void arch_disable_dma(dmach_t channel, dma_t *dma)
{
unsigned long dma_base = dma->dma_base;
unsigned int ctrl;
switch (channel) {
case DMA_0: /* Physical DMA channels */
case DMA_1:
case DMA_2:
case DMA_3:
case DMA_S0:
case DMA_S1:
disable_irq(dma->dma_irq);
ctrl = inb_t(dma_base + CR);
outb_t(ctrl & ~DMA_CR_E, dma_base + CR);
break;
case DMA_VIRTUAL_FLOPPY:
disable_irq(dma->dma_irq);
break;
}
}
__initfunc(void arch_dma_init(dma_t *dma))
{
outb(0, IOMD_IO0CR);
outb(0, IOMD_IO1CR);
outb(0, IOMD_IO2CR);
outb(0, IOMD_IO3CR);
// outb(0xf0, IOMD_DMATCR);
dma[0].dma_base = ioaddr(IOMD_IO0CURA);
dma[0].dma_irq = IRQ_DMA0;
dma[1].dma_base = ioaddr(IOMD_IO1CURA);
dma[1].dma_irq = IRQ_DMA1;
dma[2].dma_base = ioaddr(IOMD_IO2CURA);
dma[2].dma_irq = IRQ_DMA2;
dma[3].dma_base = ioaddr(IOMD_IO3CURA);
dma[3].dma_irq = IRQ_DMA3;
dma[4].dma_base = ioaddr(IOMD_SD0CURA);
dma[4].dma_irq = IRQ_DMAS0;
dma[5].dma_base = ioaddr(IOMD_SD1CURA);
dma[5].dma_irq = IRQ_DMAS1;
dma[6].dma_irq = 64;
/* Setup DMA channels 2,3 to be for podules
* and channels 0,1 for internal devices
*/
outb(DMA_EXT_IO3|DMA_EXT_IO2, IOMD_DMAEXT);
}
/*
* linux/arch/arm/kernel/dma.c
*
* Copyright (C) 1995, 1996 Russell King
* Copyright (C) 1995-1998 Russell King
*
* Front-end to the DMA handling. You must provide the following
* architecture-specific routines:
*
* int arch_request_dma(dmach_t channel, dma_t *dma, const char *dev_id);
* void arch_free_dma(dmach_t channel, dma_t *dma);
* void arch_enable_dma(dmach_t channel, dma_t *dma);
* void arch_disable_dma(dmach_t channel, dma_t *dma);
* int arch_get_dma_residue(dmach_t channel, dma_t *dma);
*
* Moved DMA resource allocation here...
*/
#include <linux/config.h>
#include <linux/sched.h>
#include <linux/malloc.h>
#include <linux/mman.h>
#include <linux/init.h>
#include <asm/page.h>
#include <asm/pgtable.h>
#include <asm/irq.h>
#include <asm/hardware.h>
#include <asm/io.h>
#define KERNEL_ARCH_DMA
#include <asm/dma.h>
static unsigned long dma_address[8];
static unsigned long dma_count[8];
static char dma_direction[8] = { -1, -1, -1, -1, -1, -1, -1};
#include "dma.h"
#if defined(CONFIG_ARCH_A5K) || defined(CONFIG_ARCH_RPC)
#define DMA_PCIO
#endif
#if defined(CONFIG_ARCH_ARC) && defined(CONFIG_BLK_DEV_FD)
#define DMA_OLD
#endif
static dma_t dma_chan[MAX_DMA_CHANNELS];
void enable_dma (unsigned int dmanr)
/* Get dma list
* for /proc/dma
*/
int get_dma_list(char *buf)
{
switch (dmanr) {
#ifdef DMA_PCIO
case 2: {
void *fiqhandler_start;
unsigned int fiqhandler_length;
extern void floppy_fiqsetup (unsigned long len, unsigned long addr,
unsigned long port);
switch (dma_direction[dmanr]) {
case 1: {
extern unsigned char floppy_fiqin_start, floppy_fiqin_end;
fiqhandler_start = &floppy_fiqin_start;
fiqhandler_length = &floppy_fiqin_end - &floppy_fiqin_start;
break;
}
case 0: {
extern unsigned char floppy_fiqout_start, floppy_fiqout_end;
fiqhandler_start = &floppy_fiqout_start;
fiqhandler_length = &floppy_fiqout_end - &floppy_fiqout_start;
break;
}
default:
printk ("enable_dma: dma%d not initialised\n", dmanr);
return;
}
memcpy ((void *)0x1c, fiqhandler_start, fiqhandler_length);
flush_page_to_ram(0);
floppy_fiqsetup (dma_count[dmanr], dma_address[dmanr], (int)PCIO_FLOPPYDMABASE);
enable_irq (64);
return;
}
#endif
#ifdef DMA_OLD
case 0: { /* Data DMA */
switch (dma_direction[dmanr]) {
case 1: /* read */
{
extern unsigned char fdc1772_dma_read, fdc1772_dma_read_end;
extern void fdc1772_setupdma(unsigned int count,unsigned int addr);
unsigned long flags;
#ifdef DEBUG
printk("enable_dma fdc1772 data read\n");
#endif
save_flags(flags);
cliIF();
memcpy ((void *)0x1c, (void *)&fdc1772_dma_read,
&fdc1772_dma_read_end - &fdc1772_dma_read);
fdc1772_setupdma(dma_count[dmanr],dma_address[dmanr]); /* Sets data pointer up */
enable_irq (64);
restore_flags(flags);
}
break;
case 0: /* write */
{
extern unsigned char fdc1772_dma_write, fdc1772_dma_write_end;
extern void fdc1772_setupdma(unsigned int count,unsigned int addr);
unsigned long flags;
#ifdef DEBUG
printk("enable_dma fdc1772 data write\n");
#endif
save_flags(flags);
cliIF();
memcpy ((void *)0x1c, (void *)&fdc1772_dma_write,
&fdc1772_dma_write_end - &fdc1772_dma_write);
fdc1772_setupdma(dma_count[dmanr],dma_address[dmanr]); /* Sets data pointer up */
enable_irq (64);
restore_flags(flags);
}
break;
default:
printk ("enable_dma: dma%d not initialised\n", dmanr);
return;
}
}
break;
int i, len = 0;
case 1: { /* Command end FIQ - actually just sets a flag */
/* Need to build a branch at the FIQ address */
extern void fdc1772_comendhandler(void);
unsigned long flags;
for (i = 0; i < MAX_DMA_CHANNELS; i++) {
if (dma_chan[i].lock)
len += sprintf(buf + len, "%2d: %s\n",
i, dma_chan[i].device_id);
}
return len;
}
/*printk("enable_dma fdc1772 command end FIQ\n");*/
save_flags(flags);
cliIF();
*((unsigned int *)0x1c)=0xea000000 | (((unsigned int)fdc1772_comendhandler-(0x1c+8))/4); /* B fdc1772_comendhandler */
/* Request DMA channel
*
* On certain platforms, we have to allocate an interrupt as well...
*/
int request_dma(dmach_t channel, const char *device_id)
{
if (channel < MAX_DMA_CHANNELS) {
int ret;
if (xchg(&dma_chan[channel].lock, 1) != 0)
return -EBUSY;
ret = arch_request_dma(channel, &dma_chan[channel], device_id);
if (!ret) {
dma_chan[channel].device_id = device_id;
dma_chan[channel].active = 0;
dma_chan[channel].invalid = 1;
} else
xchg(&dma_chan[channel].lock, 0);
return ret;
} else {
printk (KERN_ERR "Trying to allocate DMA%d\n", channel);
return -EINVAL;
}
}
/* Free DMA channel
*
* On certain platforms, we have to free interrupt as well...
*/
void free_dma(dmach_t channel)
{
if (channel >= MAX_DMA_CHANNELS) {
printk (KERN_ERR "Trying to free DMA%d\n", channel);
return;
}
restore_flags(flags);
if (xchg(&dma_chan[channel].lock, 0) == 0) {
if (dma_chan[channel].active) {
printk (KERN_ERR "Freeing active DMA%d\n", channel);
arch_disable_dma(channel, &dma_chan[channel]);
dma_chan[channel].active = 0;
}
break;
#endif
case DMA_0:
case DMA_1:
case DMA_2:
case DMA_3:
case DMA_S0:
case DMA_S1:
arch_enable_dma (dmanr - DMA_0);
break;
default:
printk ("enable_dma: dma %d not supported\n", dmanr);
printk (KERN_ERR "Trying to free free DMA%d\n", channel);
return;
}
arch_free_dma(channel, &dma_chan[channel]);
}
/* Set DMA Scatter-Gather list
*/
void set_dma_sg (dmach_t channel, dmasg_t *sg, int nr_sg)
{
dma_chan[channel].sg = sg;
dma_chan[channel].sgcount = nr_sg;
dma_chan[channel].invalid = 1;
}
void set_dma_mode (unsigned int dmanr, char mode)
/* Set DMA address
*
* Copy address to the structure, and set the invalid bit
*/
void set_dma_addr (dmach_t channel, unsigned long physaddr)
{
if (dmanr < 8) {
if (mode == DMA_MODE_READ)
dma_direction[dmanr] = 1;
else if (mode == DMA_MODE_WRITE)
dma_direction[dmanr] = 0;
else
printk ("set_dma_mode: dma%d: invalid mode %02X not supported\n",
dmanr, mode);
} else if (dmanr < MAX_DMA_CHANNELS)
arch_set_dma_mode (dmanr - DMA_0, mode);
else
printk ("set_dma_mode: dma %d not supported\n", dmanr);
if (dma_chan[channel].active)
printk(KERN_ERR "set_dma_addr: altering DMA%d"
" address while DMA active\n",
channel);
dma_chan[channel].sg = &dma_chan[channel].buf;
dma_chan[channel].sgcount = 1;
dma_chan[channel].buf.address = physaddr;
dma_chan[channel].invalid = 1;
}
void set_dma_addr (unsigned int dmanr, unsigned int addr)
/* Set DMA byte count
*
* Copy address to the structure, and set the invalid bit
*/
void set_dma_count (dmach_t channel, unsigned long count)
{
if (dmanr < 8)
dma_address[dmanr] = (unsigned long)addr;
else if (dmanr < MAX_DMA_CHANNELS)
arch_set_dma_addr (dmanr - DMA_0, addr);
else
printk ("set_dma_addr: dma %d not supported\n", dmanr);
if (dma_chan[channel].active)
printk(KERN_ERR "set_dma_count: altering DMA%d"
" count while DMA active\n",
channel);
dma_chan[channel].sg = &dma_chan[channel].buf;
dma_chan[channel].sgcount = 1;
dma_chan[channel].buf.length = count;
dma_chan[channel].invalid = 1;
}
void set_dma_count (unsigned int dmanr, unsigned int count)
/* Set DMA direction mode
*/
void set_dma_mode (dmach_t channel, dmamode_t mode)
{
if (dmanr < 8)
dma_count[dmanr] = (unsigned long)count;
else if (dmanr < MAX_DMA_CHANNELS)
arch_set_dma_count (dmanr - DMA_0, count);
else
printk ("set_dma_count: dma %d not supported\n", dmanr);
if (dma_chan[channel].active)
printk(KERN_ERR "set_dma_mode: altering DMA%d"
" mode while DMA active\n",
channel);
dma_chan[channel].dma_mode = mode;
dma_chan[channel].invalid = 1;
}
int get_dma_residue (unsigned int dmanr)
/* Enable DMA channel
*/
void enable_dma (dmach_t channel)
{
if (dmanr < 8) {
switch (dmanr) {
#if defined(CONFIG_ARCH_A5K) || defined(CONFIG_ARCH_RPC)
case 2: {
extern int floppy_fiqresidual (void);
return floppy_fiqresidual ();
}
#endif
#if defined(CONFIG_ARCH_ARC) && defined(CONFIG_BLK_DEV_FD)
case 0: {
extern unsigned int fdc1772_bytestogo;
return fdc1772_bytestogo;
if (dma_chan[channel].lock) {
if (dma_chan[channel].active == 0) {
dma_chan[channel].active = 1;
arch_enable_dma(channel, &dma_chan[channel]);
}
#endif
default:
return -1;
} else
printk (KERN_ERR "Trying to enable free DMA%d\n", channel);
}
/* Disable DMA channel
*/
void disable_dma (dmach_t channel)
{
if (dma_chan[channel].lock) {
if (dma_chan[channel].active == 1) {
dma_chan[channel].active = 0;
arch_disable_dma(channel, &dma_chan[channel]);
}
} else if (dmanr < MAX_DMA_CHANNELS)
return arch_dma_count (dmanr - DMA_0);
return -1;
} else
printk (KERN_ERR "Trying to disable free DMA%d\n", channel);
}
int get_dma_residue(dmach_t channel)
{
return arch_get_dma_residue(channel, &dma_chan[channel]);
}
__initfunc(void init_dma(void))
{
arch_dma_init(dma_chan);
}
/*
* arch/arm/kernel/dma.h
*
* Copyright (C) 1998 Russell King
*
* This header file describes the interface between the generic DMA handler
* (dma.c) and the architecture-specific DMA backends (dma-*.c)
*/
typedef struct {
dmasg_t buf; /* single DMA */
int sgcount; /* number of DMA SG */
dmasg_t *sg; /* DMA Scatter-Gather List */
unsigned int active:1; /* Transfer active */
unsigned int invalid:1; /* Address/Count changed */
dmamode_t dma_mode; /* DMA mode */
unsigned int lock; /* Device is allocated */
const char *device_id; /* Device name */
unsigned int dma_base; /* Controller base address */
int dma_irq; /* Controller IRQ */
int state; /* Controller state */
dmasg_t cur_sg; /* Current controller buffer */
} dma_t;
/* Prototype: int arch_request_dma(channel, dma, dev_id)
* Purpose : Perform architecture specific claiming of a DMA channel
* Params : channel - DMA channel number
* : dma - DMA structure (above) for channel
* : dev_id - device ID string passed with request
* Returns : 0 on success, E????? number on error
*/
int arch_request_dma(dmach_t channel, dma_t *dma, const char *dev_id);
/* Prototype: int arch_free_dma(channel, dma)
* Purpose : Perform architecture specific freeing of a DMA channel
* Params : channel - DMA channel number
* : dma - DMA structure for channel
*/
void arch_free_dma(dmach_t channel, dma_t *dma);
/* Prototype: void arch_enable_dma(channel, dma)
* Purpose : Enable a claimed DMA channel
* Params : channel - DMA channel number
* : dma - DMA structure for channel
*/
void arch_enable_dma(dmach_t channel, dma_t *dma);
/* Prototype: void arch_disable_dma(channel, dma)
* Purpose : Disable a claimed DMA channel
* Params : channel - DMA channel number
* : dma - DMA structure for channel
*/
void arch_disable_dma(dmach_t channel, dma_t *dma);
/* Prototype: int arch_get_dma_residue(channel, dma)
* Purpose : Return number of bytes left to DMA
* Params : channel - DMA channel number
* : dma - DMA structure for channel
* Returns : Number of bytes left to DMA
*/
int arch_get_dma_residue(dmach_t channel, dma_t *dma);
/* Prototype: void arch_dma_init(dma)
* Purpose : Initialise architecture specific DMA
* Params : dma - pointer to array of DMA structures
*/
void arch_dma_init(dma_t *dma);
......@@ -13,6 +13,7 @@
* now register their own routine to control interrupts (recommended).
* 29-Sep-1997 RMK Expansion card interrupt hardware not being re-enabled on reset from
* Linux. (Caused cards not to respond under RiscOS without hard reset).
* 15-Feb-1998 RMK Added DMA support
*/
#define ECARD_C
......@@ -24,13 +25,14 @@
#include <linux/interrupt.h>
#include <linux/mm.h>
#include <linux/malloc.h>
#include <linux/init.h>
#include <asm/irq-no.h>
#include <asm/ecard.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/hardware.h>
#include <asm/arch/irq.h>
#include <asm/ecard.h>
#include <asm/irq.h>
#include <asm/dma.h>
#ifdef CONFIG_ARCH_ARC
#include <asm/arch/oldlatches.h>
......@@ -59,9 +61,11 @@ static const struct expcard_blacklist {
BLACKLIST_LOADER(MANU_ATOMWIDE, PROD_ATOMWIDE_3PSERIAL, atomwide_serial_loader),
BLACKLIST_LOADER(MANU_OAK, PROD_OAK_SCSI, oak_scsi_loader),
/* Supported cards with broken loader */
{ MANU_ALSYSTEMS, PROD_ALSYS_SCSIATAPI, noloader, "AlSystems PowerTec SCSI (loader blacklisted)" },
/* Unsupported cards with no loader */
BLACKLIST_NOLOADER(MANU_ALSYSTEMS, PROD_ALSYS_SCSIATAPI),
BLACKLIST_NOLOADER(MANU_MCS, PROD_MCS_CONNECT32)
BLACKLIST_NOLOADER(MANU_MCS, PROD_MCS_CONNECT32)
};
extern int setup_arm_irq(int, struct irqaction *);
......@@ -75,7 +79,6 @@ static ecard_t expcard[MAX_ECARDS];
static signed char irqno_to_expcard[16];
static unsigned int ecard_numcards, ecard_numirqcards;
static unsigned int have_expmask;
static unsigned long kmem;
static void ecard_def_irq_enable (ecard_t *ec, int irqnr)
{
......@@ -178,20 +181,6 @@ void ecard_disablefiq (unsigned int fiqnr)
}
}
static void *ecard_malloc(int len)
{
int r;
len = (len + 3) & ~3;
if (kmem) {
r = kmem;
kmem += len;
return (void *)r;
} else
return kmalloc(len, GFP_KERNEL);
}
static void ecard_irq_noexpmask(int intr_no, void *dev_id, struct pt_regs *regs)
{
const int num_cards = ecard_numirqcards;
......@@ -301,13 +290,13 @@ static void ecard_readbytes (void *addr, ecard_t *ec, int off, int len, int usel
lowaddress = 0;
}
while (lowaddress <= laddr) {
byte = inb (ec->podaddr + haddr);
byte = inb(ec->podaddr + haddr);
lowaddress += 1;
}
while (len--) {
*a++ = byte;
if (len) {
byte = inb (ec->podaddr + haddr);
byte = inb(ec->podaddr + haddr);
lowaddress += 1;
}
}
......@@ -417,7 +406,7 @@ int ecard_readchunk (struct in_chunk_dir *cd, ecard_t *ec, int id, int num)
}
if (c_id(&excd) == 0x80) { /* loader */
if (!ec->loader) {
ec->loader = (loader_t)ecard_malloc(c_len(&excd));
ec->loader = (loader_t)kmalloc(c_len(&excd), GFP_KERNEL);
ecard_readbytes(ec->loader, ec, (int)c_start(&excd), c_len(&excd), useld);
}
continue;
......@@ -441,20 +430,39 @@ int ecard_readchunk (struct in_chunk_dir *cd, ecard_t *ec, int id, int num)
return 1;
}
unsigned int ecard_address (ecard_t *ec, card_type_t memc, card_speed_t speed)
unsigned int ecard_address (ecard_t *ec, card_type_t type, card_speed_t speed)
{
switch (ec->slot_no) {
case 0:
case 1:
case 2:
case 3:
return (memc ? MEMCECIO_BASE : IOCECIO_BASE + (speed << 17)) + (ec->slot_no << 12);
switch (type) {
case ECARD_MEMC:
return MEMCECIO_BASE + (ec->slot_no << 12);
case ECARD_IOC:
return IOCECIO_BASE + (speed << 17) + (ec->slot_no << 12);
default:
return 0;
}
#ifdef IOCEC4IO_BASE
case 4:
case 5:
case 6:
case 7:
return (memc ? 0 : IOCEC4IO_BASE + (speed << 17)) + ((ec->slot_no - 4) << 12);
switch (type) {
case ECARD_MEMC:
return 0;
case ECARD_IOC:
return IOCEC4IO_BASE + (speed << 17) + ((ec->slot_no - 4) << 12);
default:
return 0;
}
#endif
#ifdef MEMCEC8IO_BASE
case 8:
......@@ -470,7 +478,7 @@ unsigned int ecard_address (ecard_t *ec, card_type_t memc, card_speed_t speed)
* If bit 1 of the first byte of the card is set,
* then the card does not exist.
*/
static int ecard_probe (int card, int freeslot)
__initfunc(static int ecard_probe (int card, int freeslot))
{
ecard_t *ec = expcard + freeslot;
struct ex_ecld excld;
......@@ -480,7 +488,7 @@ static int ecard_probe (int card, int freeslot)
irqno_to_expcard[card] = -1;
ec->slot_no = card;
if ((ec->podaddr = ecard_address (ec, 0, ECARD_SYNC)) == 0)
if ((ec->podaddr = ecard_address (ec, ECARD_IOC, ECARD_SYNC)) == 0)
return 0;
excld.r_ecld = 2;
......@@ -490,8 +498,9 @@ static int ecard_probe (int card, int freeslot)
irqno_to_expcard[card] = freeslot;
ec->irq = -1;
ec->fiq = -1;
ec->irq = NO_IRQ;
ec->fiq = NO_IRQ;
ec->dma = NO_DMA;
ec->cld.ecld = e_ecld(&excld);
ec->cld.manufacturer = e_manu(&excld);
ec->cld.product = e_prod(&excld);
......@@ -514,15 +523,20 @@ static int ecard_probe (int card, int freeslot)
break;
}
if (card != 8) {
ec->irq = 32 + card;
ec->irq = 32 + card;
#if 0
ec->fiq = 96 + card;
/* We don't support FIQs on expansion cards at the moment */
ec->fiq = 96 + card;
#endif
} else {
#ifdef CONFIG_ARCH_RPC
if (card != 8) {
/* On RiscPC, only first two slots have DMA capability
*/
if (card < 2)
ec->dma = 2 + card;
} else
ec->irq = 11;
ec->fiq = -1;
}
#endif
if ((ec->cld.ecld & 0x78) == 0) {
struct in_chunk_dir incd;
......@@ -551,11 +565,10 @@ static struct irqaction irqexpansioncard = { ecard_irq_noexpmask, SA_INTERRUPT,
* Locate all hardware - interrupt management and
* actual cards.
*/
unsigned long ecard_init(unsigned long start_mem)
__initfunc(void ecard_init(void))
{
int i, nc = 0;
kmem = (start_mem | 3) & ~3;
memset (expcard, 0, sizeof (expcard));
#ifdef HAS_EXPMASK
......@@ -565,6 +578,7 @@ unsigned long ecard_init(unsigned long start_mem)
have_expmask = -1;
}
#endif
printk("Installed expansion cards:");
/*
......@@ -578,27 +592,25 @@ unsigned long ecard_init(unsigned long start_mem)
ecard_numirqcards = nc;
/*
* Now probe other cards with different interrupt lines
/* Now probe other cards with different interrupt lines
*/
#ifdef MEMCEC8IO_BASE
if (ecard_probe (8, nc))
nc += 1;
#endif
printk("\n");
ecard_numcards = nc;
if (nc && setup_arm_irq(IRQ_EXPANSIONCARD, &irqexpansioncard)) {
printk ("Could not allocate interrupt for expansion cards\n");
return kmem;
return;
}
#ifdef HAS_EXPMASK
if (nc && have_expmask)
EXPMASK_ENABLE = have_expmask;
#endif
oldlatch_init ();
start_mem = kmem;
kmem = 0;
return start_mem;
}
This diff is collapsed.
/*
*=============================================================================
* Low-level interface code
*-----------------------------------------------------------------------------
* Trap initialisation
*-----------------------------------------------------------------------------
*
* Note - FIQ code has changed. The default is a couple of words in 0x1c, 0x20
* that call _unexp_fiq. Nowever, we now copy the FIQ routine to 0x1c (removes
* some excess cycles).
*
* What we need to put into 0-0x1c are ldrs to branch to 0xC0000000
* (the kernel).
* 0x1c onwards is reserved for FIQ, so I think that I will allocate 0xe0 onwards for
* the actuall address to jump to.
*/
/*
* these go into 0x00
*/
.Lbranches: swi SYS_ERROR0
ldr pc, .Lbranches + 0xe4
ldr pc, .Lbranches + 0xe8
ldr pc, .Lbranches + 0xec
ldr pc, .Lbranches + 0xf0
ldr pc, .Lbranches + 0xf4
ldr pc, .Lbranches + 0xf8
ldr pc, .Lbranches + 0xfc
/*
* this is put into 0xe4 and above
*/
.Ljump_addresses:
.word vector_undefinstr @ 0xe4
.word vector_swi @ 0xe8
.word vector_prefetch @ 0xec
.word vector_data @ 0xf0
.word vector_addrexcptn @ 0xf4
.word vector_IRQ @ 0xf8
.word _unexp_fiq @ 0xfc
/*
* initialise the trap system
/*============================================================================
* All exits to user mode from the kernel go through this code.
*/
ENTRY(trap_init)
stmfd sp!, {r4 - r7, lr}
initialise_traps_extra
mov r0, #0xe4
adr r1, .Ljump_addresses
ldmia r1, {r1 - r6}
stmia r0, {r1 - r6}
mov r0, #0
adr r1, .Lbranches
ldmia r1, {r1 - r7}
stmia r0, {r1 - r7}
LOADREGS(fd, sp!, {r4 - r7, pc})
.globl ret_from_sys_call
.globl SYMBOL_NAME(fpreturn)
SYMBOL_NAME(fpreturn):
ret_from_exception:
adr r0, 1f
ldmia r0, {r0, r1}
ldr r0, [r0]
ldr r1, [r1]
tst r0, r1
blne SYMBOL_NAME(do_bottom_half)
ret_from_intr: ldr r0, [sp, #S_PSR]
tst r0, #3
beq ret_with_reschedule
b ret_from_all
ret_signal: mov r1, sp
adrsvc al, lr, ret_from_all
b SYMBOL_NAME(do_signal)
2: bl SYMBOL_NAME(schedule)
ret_from_sys_call:
adr r0, 1f
ldmia r0, {r0, r1}
ldr r0, [r0]
ldr r1, [r1]
tst r0, r1
adrsvc ne, lr, ret_from_intr
bne SYMBOL_NAME(do_bottom_half)
ret_with_reschedule:
ldr r0, 1f + 8
ldr r0, [r0]
teq r0, #0
bne 2b
get_current_task r1
ldr r1, [r1, #TSK_SIGPENDING]
teq r1, #0
bne ret_signal
ret_from_all: restore_user_regs
1: .word SYMBOL_NAME(bh_mask)
.word SYMBOL_NAME(bh_active)
.word SYMBOL_NAME(need_resched)
/*=============================================================================
* SWI handler
......@@ -77,7 +75,7 @@ vector_swi: save_user_regs
bcs 2f
get_current_task r5
ldr ip, [r5, #FLAGS] @ check for syscall tracing
ldr ip, [r5, #TSK_FLAGS] @ check for syscall tracing
tst ip, #PF_TRACESYS
bne 1f
......@@ -91,7 +89,7 @@ vector_swi: save_user_regs
1: ldr r7, [sp, #S_IP] @ save old IP
mov r0, #0
str r7, [sp, #S_IP] @ trace entry [IP = 0]
str r0, [sp, #S_IP] @ trace entry [IP = 0]
bl SYMBOL_NAME(syscall_trace)
str r7, [sp, #S_IP]
ldmia sp, {r0 - r3} @ have to reload r0 - r3
......@@ -193,57 +191,59 @@ sys_rt_sigreturn_wrapper:
add r0, sp, #4
b SYMBOL_NAME(sys_rt_sigreturn)
/*============================================================================
* All exits to user mode from the kernel go through this code.
/*
*=============================================================================
* Low-level interface code
*-----------------------------------------------------------------------------
* Trap initialisation
*-----------------------------------------------------------------------------
*
* Note - FIQ code has changed. The default is a couple of words in 0x1c, 0x20
* that call _unexp_fiq. Nowever, we now copy the FIQ routine to 0x1c (removes
* some excess cycles).
*
* What we need to put into 0-0x1c are ldrs to branch to 0xC0000000
* (the kernel).
* 0x1c onwards is reserved for FIQ, so I think that I will allocate 0xe0 onwards for
* the actuall address to jump to.
*/
.globl ret_from_sys_call
.globl SYMBOL_NAME(fpreturn)
SYMBOL_NAME(fpreturn):
ret_from_exception:
adr r0, 1f
ldmia r0, {r0, r1}
ldr r0, [r0]
ldr r1, [r1]
tst r0, r1
blne SYMBOL_NAME(do_bottom_half)
ret_from_intr: ldr r0, [sp, #S_PSR]
tst r0, #3
beq ret_with_reschedule
b ret_from_all
ret_signal: mov r1, sp
adrsvc al, lr, ret_from_all
b SYMBOL_NAME(do_signal)
2: bl SYMBOL_NAME(schedule)
ret_from_sys_call:
adr r0, 1f
ldmia r0, {r0, r1}
ldr r0, [r0]
ldr r1, [r1]
tst r0, r1
adrsvc ne, lr, ret_from_intr
bne SYMBOL_NAME(do_bottom_half)
ret_with_reschedule:
ldr r0, 1f + 8
ldr r0, [r0]
teq r0, #0
bne 2b
get_current_task r1
ldr r1, [r1, #SIGPENDING]
teq r1, #0
bne ret_signal
ret_from_all: restore_user_regs
1: .word SYMBOL_NAME(bh_mask)
.word SYMBOL_NAME(bh_active)
.word SYMBOL_NAME(need_resched)
/*
* these go into 0x00
*/
.Lbranches: swi SYS_ERROR0
ldr pc, .Lbranches + 0xe4
ldr pc, .Lbranches + 0xe8
ldr pc, .Lbranches + 0xec
ldr pc, .Lbranches + 0xf0
ldr pc, .Lbranches + 0xf4
ldr pc, .Lbranches + 0xf8
ldr pc, .Lbranches + 0xfc
/*
* this is put into 0xe4 and above
*/
.Ljump_addresses:
.word vector_undefinstr @ 0xe4
.word vector_swi @ 0xe8
.word vector_prefetch @ 0xec
.word vector_data @ 0xf0
.word vector_addrexcptn @ 0xf4
.word vector_IRQ @ 0xf8
.word _unexp_fiq @ 0xfc
/*
* initialise the trap system
*/
ENTRY(trap_init)
stmfd sp!, {r4 - r7, lr}
initialise_traps_extra
mov r0, #0xe4
adr r1, .Ljump_addresses
ldmia r1, {r1 - r6}
stmia r0, {r1 - r6}
mov r0, #0
adr r1, .Lbranches
ldmia r1, {r1 - r7}
stmia r0, {r1 - r7}
LOADREGS(fd, sp!, {r4 - r7, pc})
/*============================================================================
* FP support
......
......@@ -42,7 +42,7 @@ Lcontinue: str r5, [r6]
b SYMBOL_NAME(start_kernel)
LC1: .word SYMBOL_NAME(_stext)
LC0: .word SYMBOL_NAME(_edata)
LC0: .word SYMBOL_NAME(__bss_start)
.word SYMBOL_NAME(arm_id)
.word SYMBOL_NAME(_end)
.word SYMBOL_NAME(init_task_union)+8192
......
......@@ -16,19 +16,21 @@
.globl __stext
/*
* Entry point and restart point. Entry *must* be called with r0 == 0,
* MMU off.
* MMU off. Note! These should be unique!!! Please read Documentation/ARM-README
* for more information.
*
* r1 = 0 -> ebsa (Ram @ 0x00000000)
* r1 = 1 -> RPC (Ram @ 0x10000000)
* r1 = 2 -> ebsit (???)
* r1 = 0 -> ebsa110 (Ram @ 0x00000000)
* r1 = 1 -> RPC (Ram @ 0x10000000)
* r1 = 2 -> ebsit (???)
* r1 = 3 -> nexuspci
* r1 = 4 -> ebsa285 (Ram @ 0x00000000)
*/
ENTRY(stext)
ENTRY(_stext)
__entry:
teq r0, #0 @ check for illegal entry...
bne .Lerror @ loop indefinitely
cmp r1, #4 @ Unknown machine architecture
cmp r1, #5 @ Unknown machine architecture
bge .Lerror
@
@ First thing to do is to get the page tables set up so that we can call the kernel
......@@ -57,18 +59,23 @@ __entry:
adr r4, .LCMachTypes
add r4, r4, r1, lsl #4
ldmia r4, {r4, r5, r6} @ r4 = page dir in physical ram
ldmia r4, {r4, r5, r6}
/*
* r4 = page dir in physical ram
* r5 = physical address of start of RAM
* r6 = I/O address
*/
mov r0, r4
mov r1, #0
add r2, r0, #0x4000
1: str r1, [r0], #4 @ Clear page table
teq r0, r2
bne 1b
@
@ Add enough entries to allow the kernel to be called.
@ It will sort out the real mapping in paging_init
@
/*
* Add enough entries to allow the kernel to be called.
* It will sort out the real mapping in paging_init.
* We map in 2MB of memory into 0xC0000000 - 0xC0200000
*/
add r0, r4, #0x3000
mov r1, #0x0000000c @ SECT_CACHEABLE | SECT_BUFFERABLE
orr r1, r1, r8
......@@ -121,7 +128,7 @@ __entry:
.Lbranch: .long .Lalready_done_mmap @ Real address of routine
@ EBSA (pg dir phys, phys ram start, phys i/o)
@ EBSA110 (pg dir phys, phys ram start, phys i/o)
.LCMachTypes: .long SYMBOL_NAME(swapper_pg_dir) - 0xc0000000 @ Address of page tables (physical)
.long 0 @ Address of RAM
.long 0xe0000000 @ I/O address
......@@ -145,6 +152,14 @@ __entry:
.long 0x10000000
.long 0
@ EBSA285
.long SYMBOL_NAME(swapper_pg_dir) - 0xc0000000 @ Address of page tables (physical)
.long 0 @ Address of RAM
.long 0x24000000 @ I/O base address (0x42000000 -> 0xFE000000)
.long 0
.LCProcTypes: @ ARM6 / 610
.long 0x41560600
.long 0xffffff00
......@@ -168,7 +183,7 @@ __entry:
.long 0
.LC0: .long SYMBOL_NAME(_edata)
.LC0: .long SYMBOL_NAME(__bss_start)
.long SYMBOL_NAME(arm_id)
.long SYMBOL_NAME(_end)
.long SYMBOL_NAME(init_task_union)+8192
......@@ -231,19 +246,84 @@ __entry:
b SYMBOL_NAME(start_kernel)
#if 1
#if defined(CONFIG_ARCH_RPC)
.macro addruart,rx
mov \rx, #0xe0000000
orr \rx, \rx, #0x00010000
orr \rx, \rx, #0x00000fe0
.endm
.macro senduart,rd,rx
strb \rd, [\rx]
.endm
.macro busyuart,rd,rx
1002: ldrb \rd, [\rx, #0x14]
and \rd, \rd, #0x60
bne 1002b
.endm
.macro waituart,rd,rx
1001: ldrb \rd, [\rx, #0x18]
tst \rd, #0x10
beq 1001b
.endm
#elif defined(CONFIG_ARCH_EBSA110)
.macro addruart,rx
mov \rx, #0xf0000000
orr \rx, \rx, #0x00000be0
.endm
.macro senduart,rd,rx
strb \rd, [\rx]
.endm
.macro busyuart,rd,rx
1002: ldrb \rd, [\rx, #0x14]
and \rd, \rd, #0x60
bne 1002b
.endm
.macro waituart,rd,rx
1001: ldrb \rd, [\rx, #0x18]
tst \rd, #0x10
beq 1001b
.endm
#elif defined(CONFIG_ARCH_EBSA285)
.macro addruart,rx
mov \rx, #0xfe000000
.endm
.macro senduart,rd,rx
str \rd, [\rx, #0x160] @ UARTDR
.endm
.macro busyuart,rd,rx
1001: ldr \rd, [\rx, #0x178] @ UARTFLG
tst \rd, #1 << 3
bne 1001b
.endm
.macro waituart,rd,rx
.endm
#endif
/*
* Useful debugging routines
*/
.globl _printhex8
_printhex8: mov r1, #8
ENTRY(printhex8)
mov r1, #8
b printhex
.globl _printhex4
_printhex4: mov r1, #4
ENTRY(printhex4)
mov r1, #4
b printhex
.globl _printhex2
_printhex2: mov r1, #2
ENTRY(printhex2)
mov r1, #2
printhex: ldr r2, =hexbuf
add r3, r2, r1
mov r1, #0
......@@ -258,46 +338,23 @@ printhex: ldr r2, =hexbuf
bne 1b
mov r0, r2
.globl _printascii
_printascii:
#ifdef CONFIG_ARCH_RPC
mov r3, #0xe0000000
orr r3, r3, #0x00010000
orr r3, r3, #0x00000fe0
#else
mov r3, #0xf0000000
orr r3, r3, #0x0be0
#endif
b 3f
1: ldrb r2, [r3, #0x18]
tst r2, #0x10
beq 1b
strb r1, [r3]
2: ldrb r2, [r3, #0x14]
and r2, r2, #0x60
teq r2, #0x60
bne 2b
ENTRY(printascii)
addruart r3
b 2f
1: waituart r2, r3
senduart r1, r3
busyuart r2, r3
teq r1, #'\n'
moveq r1, #'\r'
beq 1b
3: teq r0, #0
2: teq r0, #0
ldrneb r1, [r0], #1
teqne r1, #0
bne 1b
mov pc, lr
.ltorg
.globl _printch
_printch:
#ifdef CONFIG_ARCH_RPC
mov r3, #0xe0000000
orr r3, r3, #0x00010000
orr r3, r3, #0x00000fe0
#else
mov r3, #0xf0000000
orr r3, r3, #0x0be0
#endif
ENTRY(printch)
addruart r3
mov r1, r0
mov r0, #0
b 1b
......
......@@ -33,16 +33,10 @@
#include <asm/io.h>
#include <asm/system.h>
#include <asm/hardware.h>
#include <asm/irq-no.h>
#include <asm/arch/irq.h>
unsigned int local_bh_count[NR_CPUS];
unsigned int local_irq_count[NR_CPUS];
#ifdef __SMP__
atomic_t __arm_bh_counter;
#else
int __arm_bh_counter;
#endif
spinlock_t irq_controller_lock;
#ifndef SMP
......@@ -80,13 +74,21 @@ void enable_irq(unsigned int irq_nr)
struct irqaction *irq_action[NR_IRQS];
/*
* Bitmask indicating valid interrupt numbers
#ifdef CONFIG_ARCH_ACORN
/* Bitmask indicating valid interrupt numbers
* (to be moved to include/asm-arm/arch-*)
*/
unsigned long validirqs[NR_IRQS / 32] = {
0x003fffff, 0x000001ff, 0x000000ff, 0x00000000
0x003ffe7f, 0x000001ff, 0x000000ff, 0x00000000
};
#define valid_irq(x) ((x) < NR_IRQS && validirqs[(x) >> 5] & (1 << ((x) & 31)))
#else
#define valid_irq(x) ((x) < NR_IRQS)
#endif
int get_irq_list(char *buf)
{
int i;
......@@ -98,7 +100,7 @@ int get_irq_list(char *buf)
if (!action)
continue;
p += sprintf(p, "%3d: %10u %s",
i, kstat.irqs[0][i], action->name);
i, kstat_irqs(i), action->name);
for (action = action->next; action; action = action->next) {
p += sprintf(p, ", %s", action->name);
}
......@@ -126,7 +128,7 @@ asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
cpu = smp_processor_id();
irq_enter(cpu, irq);
kstat.irqs[0][irq]++;
kstat.irqs[cpu][irq]++;
/* Return with this interrupt masked if no action */
status = 0;
......@@ -143,13 +145,26 @@ asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
if (status & SA_SAMPLE_RANDOM)
add_interrupt_randomness(irq);
__cli();
switch (irq) {
#if defined(HAS_IOMD) || defined(HAS_IOC)
if (irq != IRQ_KEYBOARDTX && irq != IRQ_EXPANSIONCARD)
case IRQ_KEYBOARDTX:
case IRQ_EXPANSIONCARD:
break;
#endif
#ifdef HAS_IOMD
case IRQ_DMA0:
case IRQ_DMA1:
case IRQ_DMA2:
case IRQ_DMA3:
break;
#endif
{
default:
spin_lock(&irq_controller_lock);
unmask_irq(irq);
spin_unlock(&irq_controller_lock);
break;
}
}
......@@ -235,7 +250,7 @@ int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *)
unsigned long retval;
struct irqaction *action;
if (irq >= NR_IRQS || !(validirqs[irq >> 5] & (1 << (irq & 31))))
if (!valid_irq(irq))
return -EINVAL;
if (!handler)
return -EINVAL;
......@@ -263,7 +278,7 @@ void free_irq(unsigned int irq, void *dev_id)
struct irqaction * action, **p;
unsigned long flags;
if (irq >= NR_IRQS || !(validirqs[irq >> 5] & (1 << (irq & 31)))) {
if (!valid_irq(irq)) {
printk(KERN_ERR "Trying to free IRQ%d\n",irq);
#ifdef CONFIG_DEBUG_ERRORS
__backtrace();
......@@ -294,7 +309,7 @@ unsigned long probe_irq_on (void)
/* first snaffle up any unassigned irqs */
for (i = 15; i > 0; i--) {
if (!irq_action[i]) {
if (!irq_action[i] && valid_irq(i)) {
enable_irq(i);
irqs |= 1 << i;
}
......@@ -323,5 +338,7 @@ int probe_irq_off (unsigned long irqs)
__initfunc(void init_IRQ(void))
{
extern void init_dma(void);
irq_init_irq();
init_dma();
}
/*
* arch/arm/kernel/leds-285.c
*
* Copyright (C) 1998 Russell King
*
* EBSA-285 LED control routines. We use the leds as follows:
*
* - Green - toggles state every 50 timer interrupts
* - Amber - On if system is not idle
* - Red - currently unused
*/
#include <asm/hardware.h>
#include <asm/leds.h>
#include <asm/system.h>
static char led_state = XBUS_LED_RED | XBUS_LED_GREEN;
void leds_event(led_event_t ledevt)
{
unsigned long flags;
save_flags_cli(flags);
switch(ledevt) {
case led_idle_start:
led_state |= XBUS_LED_AMBER;
break;
case led_idle_end:
led_state &= ~XBUS_LED_AMBER;
break;
case led_timer:
led_state ^= XBUS_LED_GREEN;
break;
default:
break;
}
restore_flags(flags);
*XBUS_LEDS = led_state;
}
......@@ -69,8 +69,10 @@ asmlinkage int sys_idle(void)
current->priority = -100;
for (;;)
{
#if 0 //def ARCH_IDLE_OK
if (!hlt_counter && !need_resched)
proc_idle ();
#endif
run_task_queue(&tq_scheduler);
schedule();
}
......@@ -142,7 +144,7 @@ void show_regs(struct pt_regs * regs)
" mrc p15, 0, %1, c2, c0\n"
" mrc p15, 0, %2, c3, c0\n"
: "=r" (ctrl), "=r" (transbase), "=r" (dac));
printk("Control: %04X Table: %08X DAC: %08X",
printk("Control: %04X Table: %08X DAC: %08X ",
ctrl, transbase, dac);
}
#endif
......
......@@ -27,18 +27,6 @@
*/
#define BREAKINST 0xef9f0001
/* change a pid into a task struct. */
static inline struct task_struct * get_task(int pid)
{
int i;
for (i = 1; i < NR_TASKS; i++) {
if (task[i] != NULL && (task[i]->pid == pid))
return task[i];
}
return NULL;
}
/*
* this routine will get a word off of the processes privileged stack.
* the offset is how far from the base addr as stored in the TSS.
......@@ -581,7 +569,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
if (pid == 1) /* you may not mess with init */
goto out;
ret = -ESRCH;
if (!(child = get_task(pid)))
if (!(child = find_task_by_pid(pid)))
goto out;
ret = -EPERM;
if (request == PTRACE_ATTACH) {
......
......@@ -26,62 +26,95 @@
#include <linux/delay.h>
#include <linux/major.h>
#include <linux/utsname.h>
#include <linux/init.h>
#include <asm/segment.h>
#include <asm/system.h>
#include <asm/hardware.h>
#include <asm/pgtable.h>
#include <asm/segment.h>
#include <asm/setup.h>
#include <asm/system.h>
#ifndef CONFIG_CMDLINE
#define CONFIG_CMDLINE "root=nfs rw console=ttyS1,38400n8"
#endif
#define COMMAND_LINE_SIZE 256
#define MEM_SIZE (16*1024*1024)
#define COMMAND_LINE_SIZE 256
static char command_line[COMMAND_LINE_SIZE] = { 0, };
char saved_command_line[COMMAND_LINE_SIZE];
struct processor processor;
struct screen_info screen_info;
unsigned char aux_device_present;
unsigned long arm_id;
extern int root_mountflags;
extern int _etext, _edata, _end;
extern const struct processor sa110_processor_functions;
#ifdef CONFIG_BLK_DEV_RAM
extern int rd_doload; /* 1 = load ramdisk, 0 = don't load */
extern int rd_prompt; /* 1 = prompt for ramdisk, 0 = don't prompt */
extern int rd_image_start; /* starting block # of image */
static inline void setup_ramdisk (void)
static inline void setup_ramdisk(int start, int prompt, int load)
{
rd_image_start = 0;
rd_prompt = 1;
rd_doload = 1;
rd_image_start = start;
rd_prompt = prompt;
rd_doload = load;
}
#else
#define setup_ramdisk()
#define setup_ramdisk(start,prompt,load)
#endif
#ifdef PARAMS_BASE
static struct param_struct *params = (struct param_struct *)PARAMS_BASE;
static inline char *setup_params(unsigned long *mem_end_p)
{
ROOT_DEV = to_kdev_t(params->u1.s.rootdev);
ORIG_X = params->u1.s.video_x;
ORIG_Y = params->u1.s.video_y;
ORIG_VIDEO_COLS = params->u1.s.video_num_cols;
ORIG_VIDEO_LINES = params->u1.s.video_num_rows;
setup_ramdisk(params->u1.s.rd_start,
(params->u1.s.flags & FLAG_RDPROMPT) == 0,
(params->u1.s.flags & FLAG_RDLOAD) == 0);
*mem_end_p = 0xc0000000 + MEM_SIZE;
return params->commandline;
}
#else
static char default_command_line[] = CONFIG_CMDLINE;
static char command_line[COMMAND_LINE_SIZE] = { 0, };
char saved_command_line[COMMAND_LINE_SIZE];
struct processor processor;
extern const struct processor sa110_processor_functions;
static inline char *setup_params(unsigned long *mem_end_p)
{
ROOT_DEV = 0x00ff;
setup_ramdisk(0, 1, 1);
*mem_end_p = 0xc0000000 + MEM_SIZE;
return default_command_line;
}
#endif
void setup_arch(char **cmdline_p,
unsigned long * memory_start_p, unsigned long * memory_end_p)
__initfunc(void setup_arch(char **cmdline_p,
unsigned long * memory_start_p, unsigned long * memory_end_p))
{
unsigned long memory_start, memory_end;
char c = ' ', *to = command_line, *from;
int len = 0;
memory_start = (unsigned long)&_end;
memory_end = 0xc0000000 + MEM_SIZE;
from = default_command_line;
processor = sa110_processor_functions;
processor._proc_init ();
processor._proc_init();
ROOT_DEV = 0x00ff;
setup_ramdisk();
from = setup_params(&memory_end);
init_task.mm->start_code = TASK_SIZE;
init_task.mm->end_code = TASK_SIZE + (unsigned long) &_etext;
......
......@@ -26,15 +26,16 @@
#include <linux/major.h>
#include <linux/utsname.h>
#include <linux/blk.h>
#include <linux/init.h>
#include <asm/segment.h>
#include <asm/system.h>
#include <asm/hardware.h>
#include <asm/io.h>
#include <asm/pgtable.h>
#include <asm/arch/mmu.h>
#include <asm/procinfo.h>
#include <asm/io.h>
#include <asm/segment.h>
#include <asm/setup.h>
#include <asm/system.h>
#include <asm/arch/mmu.h>
struct drive_info_struct { char dummy[32]; } drive_info;
struct screen_info screen_info;
......@@ -153,13 +154,17 @@ static void setup_initrd (struct param_struct *params, unsigned long memory_end)
#define setup_initrd(p,m)
#endif
#ifdef IOEB_BASE
static inline void check_ioeb_present(void)
{
if (((*IOEB_BASE) & 15) == 5)
armidlist[armidindex].features |= F_IOEB;
}
#else
#define check_ioeb_present()
#endif
static void get_processor_type (void)
static inline void get_processor_type (void)
{
for (armidindex = 0; ; armidindex ++)
if (!((armidlist[armidindex].id ^ arm_id) &
......@@ -179,11 +184,14 @@ static void get_processor_type (void)
#define COMMAND_LINE_SIZE 256
/* Can this be initdata? --pb
* command_line can be, saved_command_line can't though
*/
static char command_line[COMMAND_LINE_SIZE] = { 0, };
char saved_command_line[COMMAND_LINE_SIZE];
void setup_arch(char **cmdline_p,
unsigned long * memory_start_p, unsigned long * memory_end_p)
__initfunc(void setup_arch(char **cmdline_p,
unsigned long * memory_start_p, unsigned long * memory_end_p))
{
static unsigned char smptrap;
unsigned long memory_start, memory_end;
......
......@@ -23,6 +23,7 @@
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/smp.h>
#include <linux/init.h>
#include <asm/uaccess.h>
#include <asm/io.h>
......@@ -30,7 +31,6 @@
#include <asm/delay.h>
#include <linux/timex.h>
#include <asm/irq-no.h>
#include <asm/hardware.h>
extern int setup_arm_irq(int, struct irqaction *);
......@@ -143,12 +143,12 @@ static void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
update_rtc ();
}
static struct irqaction irqtimer0 = { timer_interrupt, 0, 0, "timer", NULL, NULL};
static struct irqaction irqtimer = { timer_interrupt, 0, 0, "timer", NULL, NULL};
void time_init(void)
__initfunc(void time_init(void))
{
xtime.tv_sec = setup_timer();
xtime.tv_usec = 0;
setup_arm_irq(IRQ_TIMER0, &irqtimer0);
setup_arm_irq(IRQ_TIMER, &irqtimer);
}
......@@ -59,17 +59,27 @@ static int verify_stack_pointer (unsigned long stackptr, int size)
return 0;
}
static void dump_stack (unsigned long *start, unsigned long *end, int offset, int max)
/*
* Dump out the contents of some memory nicely...
*/
void dump_mem(unsigned long bottom, unsigned long top)
{
unsigned long *p;
unsigned long p = bottom & ~31;
int i;
for (p = start + offset, i = 0; i < max && p < end; i++, p++) {
if (i && (i & 7) == 0)
printk ("\n ");
printk ("%08lx ", *p);
for (p = bottom & ~31; p < top;) {
printk("%08lx: ", p);
for (i = 0; i < 8; i++, p += 4) {
if (p < bottom || p >= top)
printk(" ");
else
printk("%08lx ", *(unsigned long *)p);
if (i == 3)
printk(" ");
}
printk ("\n");
}
printk ("\n");
}
/*
......@@ -139,28 +149,26 @@ void die_if_kernel(char *str, struct pt_regs *regs, int err, int ret)
break;
}
console_verbose ();
printk ("Internal error: %s: %x\n", str, err);
printk ("CPU: %d", smp_processor_id());
show_regs (regs);
printk ("Process %s (pid: %d, stackpage=%08lx)\nStack: ",
console_verbose();
printk("Internal error: %s: %x\n", str, err);
printk("CPU: %d", smp_processor_id());
show_regs(regs);
printk("Process %s (pid: %d, stackpage=%08lx)\n",
current->comm, current->pid, 4096+(unsigned long)current);
cstack = (unsigned long)(regs + 1);
sstack = 4096+(unsigned long)current;
if (*(unsigned long *)sstack != STACK_MAGIC)
printk ("*** corrupted stack page\n ");
if (verify_stack_pointer (cstack, 4))
printk ("%08lx invalid kernel stack pointer\n", cstack);
printk("Stack: ");
if (verify_stack_pointer(cstack, 4))
printk("invalid kernel stack pointer %08lx", cstack);
else if(cstack > sstack + 4096)
printk("(sp overflow)\n");
printk("(sp overflow)");
else if(cstack < sstack)
printk("(sp underflow)\n");
else
dump_stack ((unsigned long *)sstack, (unsigned long *)sstack + 1024,
cstack - sstack, kstack_depth_to_print);
printk("(sp underflow)");
printk("\n");
dump_mem(cstack, sstack + 4096);
frameptr = regs->ARM_fp;
if (frameptr) {
......@@ -172,7 +180,7 @@ void die_if_kernel(char *str, struct pt_regs *regs, int err, int ret)
}
}
dump_instr (instruction_pointer(regs));
dump_instr(instruction_pointer(regs));
died = 0;
if (ret != -1)
do_exit (ret);
......
......@@ -5,17 +5,13 @@
#
L_TARGET := lib.a
L_OBJS := backtrace.o bitops.o delay.o fp_support.o \
L_OBJS := backtrace.o bitops.o checksum.o delay.o fp_support.o \
loaders.o memcpy.o memfastset.o system.o string.o uaccess.o
ifeq ($(PROCESSOR),armo)
L_OBJS += uaccess-armo.o
endif
ifdef CONFIG_INET
L_OBJS += checksum.o
endif
ifdef CONFIG_ARCH_ACORN
L_OBJS += ll_char_wr.o io-acorn.o
ifdef CONFIG_ARCH_A5K
......@@ -26,30 +22,27 @@ ifdef CONFIG_ARCH_ACORN
endif
endif
ifdef CONFIG_ARCH_EBSA110
ifeq ($(MACHINE),ebsa110)
L_OBJS += io-ebsa110.o
endif
include $(TOPDIR)/Rules.make
ifeq ($(MACHINE),ebsa285)
L_OBJS += io-ebsa285.o
endif
constants.h: getconstants
./getconstants > constants.h
include $(TOPDIR)/Rules.make
getconstants: getconstants.c getconstants.h
$(HOSTCC) -D__KERNEL__ -o getconstants getconstants.c
constants.h: getconsdata.o extractconstants.pl
$(PERL) extractconstants.pl $(OBJDUMP) > $@
getconstants.h: getconsdata.c
getconsdata.o: getconsdata.c
$(CC) $(CFLAGS) -c getconsdata.c
$(PERL) extractinfo.perl $(OBJDUMP) > $@
%.o: %.S
ifndef $(CONFIG_BINUTILS_NEW)
ifneq ($(CONFIG_BINUTILS_NEW),y)
$(CC) $(CFLAGS) -D__ASSEMBLY__ -E $< | tr ';$$' '\n#' > ..tmp.$<.s
$(CC) $(CFLAGS:-pipe=) -c -o $@ ..tmp.$<.s
$(RM) ..tmp.$<.s
else
$(CC) $(CFLAGS) -D__ASSEMBLY__ -c -o $@ $<
endif
clean:
$(RM) getconstants constants.h getconstants.h
......@@ -27,8 +27,10 @@ while (<DATA>) {
next if ($elf && ! (/^00...... g/ && /.data/));
next if (!$aout && !$elf);
($addr, $flags, $sect, $a1, $a2, $a3, $name) = split (' ') if $aout;
$nam[hex($addr)] = substr($name, 1) if $aout;
if ($aout) {
($addr, $flags, $sect, $a1, $a2, $a3, $name) = split (' ');
$nam[hex($addr)] = substr($name, 1);
}
if ($elf) {
chomp;
$addr = substr ($_, 0, 8);
......@@ -38,8 +40,7 @@ while (<DATA>) {
}
close (DATA);
print "/*\n * *** THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT! ***\n */\n";
for ($i = 0; $i < hex($addr)+12; $i ++) {
print "unsigned long $nam[$i] = $dat[$i];\n" if $dat[$i];
print "#define __HAS_$nam[$i]\n" if $dat[$i];
print "/*\n * *** This file is automatically generated from getconsdata.c. Do not edit! ***\n */\n";
for ($i = 0; $i < hex($addr)+4; $i += 4) {
print "#define $nam[$i] $dat[$i]\n";
}
/*
* linux/arch/arm/lib/getconsdata.c
*
* Copyright (C) 1995, 1996 Russell King
* Copyright (C) 1995-1998 Russell King
*/
#include <linux/config.h>
#include <linux/sched.h>
#include <linux/mm.h>
......@@ -15,17 +14,55 @@
#define OFF_MM(n) (unsigned long)&(((struct mm_struct *)0)->n)
#ifdef KERNEL_DOMAIN
unsigned long kernel_domain = KERNEL_DOMAIN;
unsigned long DOM_KERNELDOMAIN = KERNEL_DOMAIN;
#endif
#ifdef USER_DOMAIN
unsigned long user_domain = USER_DOMAIN;
#endif
unsigned long addr_limit = OFF_TSK(addr_limit);
unsigned long tss_memmap = OFF_TSK(tss.memmap);
unsigned long mm = OFF_TSK(mm);
unsigned long pgd = OFF_MM(pgd);
unsigned long tss_save = OFF_TSK(tss.save);
unsigned long tss_fpesave = OFF_TSK(tss.fpstate.soft.save);
unsigned long DOM_USERDOMAIN = USER_DOMAIN;
#endif
unsigned long TSK_STATE = OFF_TSK(state);
unsigned long TSK_FLAGS = OFF_TSK(flags);
unsigned long TSK_SIGPENDING = OFF_TSK(sigpending);
unsigned long TSK_ADDR_LIMIT = OFF_TSK(addr_limit);
unsigned long MM = OFF_TSK(mm);
unsigned long PGD = OFF_MM(pgd);
unsigned long TSS_MEMMAP = OFF_TSK(tss.memmap);
unsigned long TSS_SAVE = OFF_TSK(tss.save);
unsigned long TSS_FPESAVE = OFF_TSK(tss.fpstate.soft.save);
#if defined(CONFIG_CPU_ARM2) || defined(CONFIG_CPU_ARM3)
unsigned long tss_memcmap = OFF_TSK(tss.memcmap);
unsigned long TSS_MEMCMAP = OFF_TSK(tss.memcmap);
#endif
#ifdef _PAGE_PRESENT
unsigned long PAGE_PRESENT = _PAGE_PRESENT;
#endif
#ifdef _PAGE_RW
unsigned long PAGE_RW = _PAGE_RW;
#endif
#ifdef _PAGE_USER
unsigned long PAGE_USER = _PAGE_USER;
#endif
#ifdef _PAGE_ACCESSED
unsigned long PAGE_ACCESSED = _PAGE_ACCESSED;
#endif
#ifdef _PAGE_DIRTY
unsigned long PAGE_DIRTY = _PAGE_DIRTY;
#endif
#ifdef _PAGE_READONLY
unsigned long PAGE_READONLY = _PAGE_READONLY;
#endif
#ifdef _PAGE_NOT_USER
unsigned long PAGE_NOT_USER = _PAGE_NOT_USER;
#endif
#ifdef _PAGE_OLD
unsigned long PAGE_OLD = _PAGE_OLD;
#endif
#ifdef _PAGE_CLEAN
unsigned long PAGE_CLEAN = _PAGE_CLEAN;
#endif
unsigned long KSWI_BASE = 0x900000;
unsigned long KSWI_SYS_BASE = 0x9f0000;
unsigned long SYS_ERROR0 = 0x9f0000;
/*
* linux/arch/arm/lib/getconstants.c
*
* Copyright (C) 1995, 1996 Russell King
*/
#include <linux/mm.h>
#include <asm/pgtable.h>
#include <stdio.h>
#include <linux/unistd.h>
void printdef(char *def, int no)
{
printf("#define %s\t%d\n", def, no);
}
#include "getconstants.h"
int main()
{
printf("/*\n * contants.h generated by getconstants\n * DO NOT EDIT!\n */\n");
printf("#define _current\t_%s\n", "current_set");
#ifdef _PAGE_PRESENT
printdef("PAGE_PRESENT", _PAGE_PRESENT);
#endif
#ifdef _PAGE_RW
printdef("PAGE_RW", _PAGE_RW);
#endif
#ifdef _PAGE_USER
printdef("PAGE_USER", _PAGE_USER);
#endif
#ifdef _PAGE_ACCESSED
printdef("PAGE_ACCESSED", _PAGE_ACCESSED);
#endif
#ifdef _PAGE_DIRTY
printdef("PAGE_DIRTY", _PAGE_DIRTY);
#endif
#ifdef _PAGE_READONLY
printdef("PAGE_READONLY", _PAGE_READONLY);
#endif
#ifdef _PAGE_NOT_USER
printdef("PAGE_NOT_USER", _PAGE_NOT_USER);
#endif
#ifdef _PAGE_OLD
printdef("PAGE_OLD", _PAGE_OLD);
#endif
#ifdef _PAGE_CLEAN
printdef("PAGE_CLEAN", _PAGE_CLEAN);
#endif
printdef("TSS_MEMMAP", (int)tss_memmap);
printdef("TSS_SAVE", (int)tss_save);
#ifdef __HAS_tss_memcmap
printdef("TSS_MEMCMAP", (int)tss_memcmap);
#endif
#ifdef __HAS_addr_limit
printdef("ADDR_LIMIT", (int)addr_limit);
#endif
#ifdef __HAS_kernel_domain
printdef("KERNEL_DOMAIN", kernel_domain);
#endif
#ifdef __HAS_user_domain
printdef("USER_DOMAIN", user_domain);
#endif
printdef("TSS_FPESAVE", (int)tss_fpesave);
printdef("MM", (int)mm);
printdef("PGD", (int)pgd);
printf("#define KSWI_BASE 0x900000\n");
printf("#define KSWI_SYS_BASE 0x9F0000\n");
printf("#define SYS_ERROR0 0x9F0000\n");
return 0;
}
/*
* *** THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT! ***
*/
unsigned long addr_limit = 56;
#define __HAS_addr_limit
unsigned long tss_memmap = 640;
#define __HAS_tss_memmap
unsigned long mm = 1676;
#define __HAS_mm
unsigned long pgd = 8;
#define __HAS_pgd
unsigned long tss_save = 636;
#define __HAS_tss_save
unsigned long tss_fpesave = 492;
#define __HAS_tss_fpesave
unsigned long tss_memcmap = 644;
#define __HAS_tss_memcmap
......@@ -57,7 +57,7 @@ ENTRY(insw)
mov r2, r2, lsl#1
ENTRY(inswb)
mov ip, sp
stmfd sp!, {r4 - r10 ,fp ,ip ,lr ,pc}
stmfd sp!, {r4 - r10, fp, ip, lr, pc}
sub fp, ip, #4
addr r3, r0
add r0, r3, r0, lsl #2
......@@ -70,7 +70,7 @@ ENTRY(inswb)
strgeb r4, [r1], #1
movgt r4, r4, LSR#8
strgtb r4, [r1], #1
ldmleea fp, {r4 - r10, fp, sp, pc}^
LOADREGS(leea, fp, {r4 - r10, fp, sp, pc})
sub r2, r2, #2
Linswok: mov ip, #0xFF
orr ip, ip, ip, lsl #8
......
#define __ASSEMBLER__
#include <linux/linkage.h>
ENTRY(insl)
add r0, r0, #0xff000000
add r0, r0, #0x00e00000
ands ip, r1, #3
bne 2f
1: ldr r3, [r0]
str r3, [r1], #4
subs r2, r2, #1
bne 1b
mov pc, lr
2: cmp ip, #2
ldr ip, [r0]
blt 3f
bgt 4f
strh ip, [r1], #2
mov ip, ip, lsr #16
1: subs r2, r2, #1
ldrne r3, [r0]
orrne ip, ip, r3, lsl #16
strne ip, [r1], #4
movne ip, r3, lsr #16
bne 1b
strh ip, [r1], #2
mov pc, lr
3: strb ip, [r1], #1
mov ip, ip, lsr #8
strh ip, [r1], #2
mov ip, ip, lsr #16
1: subs r2, r2, #1
ldrne r3, [r0]
orrne ip, ip, r3, lsl #8
strne ip, [r1], #4
movne ip, r3, lsr #24
bne 1b
strb ip, [r1], #1
mov pc, lr
4: strb ip, [r1], #1
mov ip, ip, lsr #8
1: subs r2, r2, #1
ldrne r3, [r0]
orrne ip, ip, r3, lsl #24
strne ip, [r1], #4
movne ip, r3, lsr #8
bne 1b
strb ip, [r1], #1
mov ip, ip, lsr #8
strh ip, [r1], #2
mov pc, lr
ENTRY(outsl)
add r0, r0, #0xff000000
add r0, r0, #0x00e00000
ands ip, r1, #3
bne 2f
1: ldr r3, [r1], #4
str r3, [r0]
subs r2, r2, #1
bne 1b
mov pc, lr
2: bic r1, r1, #3
cmp ip, #2
ldr ip, [r1], #4
mov ip, ip, lsr #16
blt 3f
bgt 4f
1: ldr r3, [r1], #4
orr ip, ip, r3, lsl #16
str ip, [r0]
mov ip, r3, lsr #16
subs r2, r2, #1
bne 1b
mov pc, lr
3: ldr r3, [r1], #4
orr ip, ip, r3, lsl #8
str ip, [r0]
mov ip, r3, lsr #24
subs r2, r2, #1
bne 3b
mov pc, lr
4: ldr r3, [r1], #4
orr ip, ip, r3, lsl #24
str ip, [r0]
mov ip, r3, lsr #8
subs r2, r2, #1
bne 4b
mov pc, lr
ENTRY(outsw)
ENTRY(outswb)
mov pc, lr
ENTRY(insw)
ENTRY(inswb)
mov pc, lr
......@@ -3,9 +3,10 @@
*
* Copyright (C) 1995, 1996 Russell King.
*
* Speedups & 1bpp code (C) 1996 Philip Blundel & Russell King.
* Speedups & 1bpp code (C) 1996 Philip Blundell & Russell King.
*
* 10-04-96 RMK Various cleanups & reduced register usage.
* 08-04-98 RMK Shifts re-ordered
*/
@ Regs: [] = corruptable
......@@ -32,22 +33,22 @@ ENTRY(ll_write_char)
@
@ Smashable regs: {r0 - r3}, [r4 - r7], (r8 - fp), [ip], (sp), [lr], (pc)
@
eor ip, r1, #UNDERLINE << 24
eor ip, r1, #UNDERLINE << 9
/*
* calculate colours
*/
tst r1, #INVERSE << 24
moveq r2, r1, lsr #8
moveq r3, r1, lsr #16
movne r2, r1, lsr #16
movne r3, r1, lsr #8
tst r1, #INVERSE << 9
moveq r2, r1, lsr #16
moveq r3, r1, lsr #24
movne r2, r1, lsr #24
movne r3, r1, lsr #16
and r3, r3, #255
and r2, r2, #255
/*
* calculate offset into character table
*/
and r1, r1, #255
mov r1, r1, lsl #3
mov r1, r1, lsl #23
mov r1, r1, lsr #20
/*
* calculate offset required for each row [maybe I should make this an argument to this fn.
* Have to see what the register usage is like in the calling routines.
......@@ -67,7 +68,7 @@ ENTRY(ll_write_char)
add r0, r0, r5, lsl #3 @ Move to bottom of character
add r1, r1, #7
ldrb r7, [r6, r1]
tst ip, #UNDERLINE << 24
tst ip, #UNDERLINE << 9
eoreq r7, r7, #255
teq r4, #8
beq Lrow8bpplp
......@@ -131,7 +132,7 @@ Lrow8bpplp: mov ip, r7, lsr #4
@
Lrow1bpp: add r6, r6, r1
ldmia r6, {r4, r7}
tst ip, #INVERSE << 24
tst ip, #INVERSE << 9
mvnne r4, r4
mvnne r7, r7
strb r4, [r0], r5
......@@ -147,7 +148,7 @@ Lrow1bpp: add r6, r6, r1
mov r7, r7, lsr #8
strb r7, [r0], r5
mov r7, r7, lsr #8
tst ip, #UNDERLINE << 24
tst ip, #UNDERLINE << 9
mvneq r7, r7
strb r7, [r0], r5
LOADREGS(fd, sp!, {r4 - r7, pc})
......
......@@ -8,6 +8,12 @@
#include <asm/assembler.h>
#include <linux/linkage.h>
#ifndef ENTRY
#define ENTRY(x...) \
.globl _##x; \
_##x:
#endif
.text
#define ENTER \
mov ip,sp ;\
......@@ -84,6 +90,7 @@ ENTRY(memmove)
blt 6b
ands ip, r1, #3
beq 1b
8: bic r1, r1, #3
ldr r7, [r1], #4
cmp ip, #2
......@@ -105,14 +112,14 @@ ENTRY(memmove)
subs r2, r2, #16
bge 9b
adds r2, r2, #12
blt 1b
blt 100f
10: mov r3, r7, lsr #8
ldr r7, [r1], #4
orr r3, r3, r7, lsl #24
str r3, [r0], #4
subs r2, r2, #4
bge 10b
sub r1, r1, #3
100: sub r1, r1, #3
b 6b
11: cmp r2, #12
......
......@@ -13,13 +13,21 @@
#include <asm/errno.h>
.text
#ifdef ENTRY
#define USER(x...) \
9999: x; \
.section __ex_table,"a"; \
.align 3; \
.long 9999b,9001f; \
.previous
#else
#define USER(x...) \
x
#define ENTRY(x...) \
.globl _##x; \
_##x:
#define TESTING
#endif
#define PAGE_SHIFT 12
......@@ -278,12 +286,12 @@ USER( strgebt r3, [r0], #1) // May fault
USER( strgtbt r3, [r0], #1) // May fault
b .c2u_finished
#ifndef TESTING
.section .fixup,"ax"
.align 0
9001: LOADREGS(fd,sp!, {r0, r4 - r7, pc})
.previous
#endif
/* Prototype: unsigned long __arch_copy_from_user(void *to,const void *from,unsigned long n);
* Purpose : copy a block from user memory to kernel memory
......@@ -538,10 +546,12 @@ USER( ldrget r3, [r1], #0) // May fault
strgtb r3, [r0], #1
b .cfu_finished
#ifndef TESTING
.section .fixup,"ax"
.align 0
9001: LOADREGS(fd,sp!, {r0, r4 - r7, pc})
.previous
#endif
/* Prototype: int __arch_clear_user(void *addr, size_t sz)
* Purpose : clear some user memory
......@@ -556,7 +566,7 @@ ENTRY(__arch_clear_user)
blt 2f
ands ip, r0, #3
beq 1f
cmp ip, #1
cmp ip, #2
USER( strbt r2, [r0], #1)
USER( strlebt r2, [r0], #1)
USER( strltbt r2, [r0], #1)
......@@ -566,9 +576,9 @@ USER( strltbt r2, [r0], #1)
USER( strplt r2, [r0], #4)
USER( strplt r2, [r0], #4)
bpl 1b
2: adds r1, r1, #4 @ 3 2 1 0 -1 -2 -3
adds r1, r1, #4 @ 3 2 1 0 -1 -2 -3
USER( strplt r2, [r0], #4)
tst r1, #2 @ 1x 1x 0x 0x 1x 1x 0x
2: tst r1, #2 @ 1x 1x 0x 0x 1x 1x 0x
USER( strnebt r2, [r0], #1)
USER( strnebt r2, [r0], #1)
tst r1, #1 @ x1 x0 x1 x0 x1 x0 x1
......@@ -576,6 +586,7 @@ USER( strnebt r2, [r0], #1)
mov r0, #0
LOADREGS(fd,sp!, {r1, pc})
#ifndef TESTING
.section .fixup,"ax"
.align 0
9001: LOADREGS(fd,sp!, {r0, pc})
......@@ -611,21 +622,25 @@ USER( ldrbt r1, [r0], #1)
*/
ENTRY(__arch_strncpy_from_user)
stmfd sp!, {lr}
mov ip, r2
add ip, r1, #1
1: subs r2, r2, #1
bmi 2f
USER( ldrbt r3, [r1], #1)
strb r3, [r0], #1
teq r3, #0
bne 1b
2: subs r0, ip, r2
LOADREGS(fd,sp!, {pc})
sub r0, r1, ip
LOADREGS(fd, sp!, {pc})
2: sub ip, ip, #1
sub r0, r1, ip
LOADREGS(fd, sp!, {pc})
.section .fixup,"ax"
.align 0
9001: mov r0, #-EFAULT
LOADREGS(fd,sp!, {pc})
LOADREGS(fd, sp!, {pc})
.previous
.align
#endif
......@@ -7,8 +7,14 @@
#
# Note 2! The CFLAGS definition is now in the main makefile...
ifeq ($(MACHINE),a5k)
MMARCH=arc
else
MMARCH=$(MACHINE)
endif
O_TARGET := mm.o
O_OBJS := init.o extable.o fault-$(PROCESSOR).o mm-$(MACHINE).o
O_OBJS := init.o extable.o fault-$(PROCESSOR).o mm-$(MMARCH).o
ifeq ($(PROCESSOR),armo)
O_OBJS += proc-arm2,3.o
......@@ -28,9 +34,9 @@ proc-sa110.o: ../lib/constants.h
../lib/constants.h:
@$(MAKE) -C ../lib constants.h
ifneq ($(CONFIG_BINUTILS_NEW),y)
%.o: %.S
ifndef $(CONFIG_BINUTILS_NEW)
$(CC) $(CFLAGS) -D__ASSEMBLY__ -E $< | tr ';$$' '\n#' > ..tmp.s
$(CC) $(CFLAGS:-pipe=) -c -o $@ ..tmp.s
$(RM) ..tmp.s
$(CC) $(CFLAGS) -D__ASSEMBLY__ -E $< | tr ';$$' '\n#' > ..$@.tmp.s
$(CC) $(CFLAGS:-pipe=) -c -o $@ ..$@.tmp.s
$(RM) ..$@.tmp.s
endif
......@@ -27,13 +27,13 @@
struct pgtable_cache_struct quicklists;
void __bad_pte(pmd_t *pmd)
void __bad_pmd(pmd_t *pmd)
{
printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd));
set_pmd(pmd, mk_user_pmd(BAD_PAGETABLE));
}
void __bad_pte_kernel(pmd_t *pmd)
void __bad_pmd_kernel(pmd_t *pmd)
{
printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd));
set_pmd(pmd, mk_kernel_pmd(BAD_PAGETABLE));
......@@ -72,7 +72,7 @@ pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset)
}
free_small_page ((unsigned long) pte);
if (pmd_bad(*pmd)) {
__bad_pte(pmd);
__bad_pmd(pmd);
return NULL;
}
return (pte_t *) pmd_page(*pmd) + offset;
......@@ -94,7 +94,7 @@ pte_t *get_pte_kernel_slow(pmd_t *pmd, unsigned long offset)
}
free_small_page ((unsigned long) pte);
if (pmd_bad(*pmd)) {
__bad_pte_kernel(pmd);
__bad_pmd_kernel(pmd);
return NULL;
}
return (pte_t *) pmd_page(*pmd) + offset;
......@@ -102,6 +102,19 @@ pte_t *get_pte_kernel_slow(pmd_t *pmd, unsigned long offset)
extern void die_if_kernel(char *msg, struct pt_regs *regs, unsigned int err, unsigned int ret);
#ifdef DEBUG
static int sp_valid (unsigned long *sp)
{
unsigned long addr = (unsigned long) sp;
if (addr >= 0xb0000000 && addr < 0xd0000000)
return 1;
if (addr >= 0x03ff0000 && addr < 0x04000000)
return 1;
return 0;
}
#endif
static void kernel_page_fault (unsigned long addr, int mode, struct pt_regs *regs,
struct task_struct *tsk, struct mm_struct *mm)
{
......@@ -178,6 +191,16 @@ static void page_fault (unsigned long addr, int mode, struct pt_regs *regs)
printk ("%s: memory violation at pc=0x%08lx, lr=0x%08lx (bad address=0x%08lx, code %d)\n",
tsk->comm, regs->ARM_pc, regs->ARM_lr, addr, mode);
#ifdef DEBUG
{
unsigned int i, j;
unsigned long *sp = (unsigned long *) (regs->ARM_sp - 128);
for (j = 0; j < 20 && sp_valid (sp); j++) {
printk ("%p: ", sp);
for (i = 0; i < 8 && sp_valid (sp); i += 1, sp++)
printk ("%08lx ", *sp);
printk ("\n");
}
}
show_regs (regs);
c_backtrace (regs->ARM_fp, regs->ARM_cpsr);
#endif
......@@ -208,7 +231,6 @@ do_DataAbort (unsigned long addr, int fsr, int error_code, struct pt_regs *regs)
{
if (user_mode(regs))
error_code |= FAULT_CODE_USER;
#define DIE(signr,nam)\
force_sig(signr, current);\
die_if_kernel(nam, regs, fsr, signr);\
......@@ -229,18 +251,22 @@ do_DataAbort (unsigned long addr, int fsr, int error_code, struct pt_regs *regs)
case 11:
DIE(SIGSEGV, "Domain fault")
case 13:/* permission fault on section */
#ifndef DEBUG
#ifdef DEBUG
{
unsigned int i, j, a;
static int count=2;
if (count-- == 0) while (1);
a = regs->ARM_sp;
for (j = 0; j < 10; j++) {
printk ("%08x: ", a);
for (i = 0; i < 8; i += 1, a += 4)
printk ("%08lx ", *(unsigned long *)a);
unsigned int i, j;
unsigned long *sp;
printk ("%s: section permission fault (bad address=0x%08lx, code %d)\n",
current->comm, addr, error_code);
sp = (unsigned long *) (regs->ARM_sp - 128);
for (j = 0; j < 20 && sp_valid (sp); j++) {
printk ("%p: ", sp);
for (i = 0; i < 8 && sp_valid (sp); i += 1, sp++)
printk ("%08lx ", *sp);
printk ("\n");
}
show_regs (regs);
c_backtrace(regs->ARM_fp, regs->ARM_cpsr);
}
#endif
DIE(SIGSEGV, "Permission fault")
......
......@@ -17,6 +17,7 @@
#include <linux/mm.h>
#include <linux/swap.h>
#include <linux/smp.h>
#include <linux/init.h>
#ifdef CONFIG_BLK_DEV_INITRD
#include <linux/blk.h>
#endif
......@@ -102,7 +103,7 @@ void show_mem(void)
/*
* paging_init() sets up the page tables...
*/
unsigned long paging_init(unsigned long start_mem, unsigned long end_mem)
__initfunc(unsigned long paging_init(unsigned long start_mem, unsigned long end_mem))
{
extern unsigned long free_area_init(unsigned long, unsigned long);
......@@ -129,7 +130,7 @@ unsigned long paging_init(unsigned long start_mem, unsigned long end_mem)
* memory is free. This is done after various parts of the system have
* claimed their memory after the kernel image.
*/
void mem_init(unsigned long start_mem, unsigned long end_mem)
__initfunc(void mem_init(unsigned long start_mem, unsigned long end_mem))
{
extern void sound_init(void);
int codepages = 0;
......
/*
* arch/arm/mm/mm-a5k.c
*
* Extra MM routines for the Archimedes architecture
*
* Copyright (C) 1998 Russell King
*/
......@@ -5,3 +5,4 @@
*
* Copyright (C) 1998 Russell King
*/
#include <asm/arch/mm-init.h>
......@@ -5,3 +5,22 @@
*
* Copyright (C) 1998 Russell King
*/
#include <asm/io.h>
/* map in IO */
void setup_io_pagetables(void)
{
unsigned long address = IO_START;
int spi = IO_BASE >> PGDIR_SHIFT;
pgd_val(swapper_pg_dir[spi-1]) = 0xc0000000 | PMD_TYPE_SECT |
PMD_DOMAIN(DOMAIN_KERNEL) | PMD_SECT_AP_WRITE;
while (address < IO_START + IO_SIZE && address) {
pgd_val(swapper_pg_dir[spi++]) = address | PMD_TYPE_SECT |
PMD_DOMAIN(DOMAIN_IO) |
PMD_SECT_AP_WRITE;
address += PGDIR_SIZE;
}
}
/*
* arch/arm/mm/mm-ebsa285.c
*
* Extra MM routines for the EBSA285 architecture
*
* Copyright (C) 1998 Russell King
*/
#include <linux/sched.h>
#include <linux/mm.h>
#include <asm/pgtable.h>
#include <asm/page.h>
#include <asm/io.h>
#include <asm/proc/mm-init.h>
/* Logical Physical
* 0xfff00000 0x40000000 X-Bus
* 0xffe00000 0x7c000000 PCI I/O space
* 0xfe000000 0x42000000 CSR
* 0xfd000000 0x78000000 Outbound write flush
* 0xfc000000 0x79000000 PCI IACK/special space
* 0xf9000000 0x7a000000 PCI Config type 1
* 0xf8000000 0x7b000000 PCI Config type 0
*/
static struct mapping {
unsigned long virtual;
unsigned long physical;
unsigned long length;
} io_mapping[] = {
/*
* This is to allow us to fiddle with the EEPROM
* This entry will go away in time
*/
{ 0xd8000000, 0x41000000, 0x00400000 },
/*
* These ones are so that we can fiddle
* with the various cards (eg VGA)
* until we're happy with them...
*/
{ 0xdc000000, 0x7c000000, 0x00100000 },
{ 0xe0000000, 0x80000000, 0x10000000 },
{ 0xf8000000, 0x7b000000, 0x01000000 }, /* Type 0 Config */
{ 0xf9000000, 0x7a000000, 0x01000000 }, /* Type 1 Config */
{ 0xfc000000, 0x79000000, 0x01000000 }, /* PCI IACK */
{ 0xfd000000, 0x78000000, 0x01000000 }, /* Outbound wflsh*/
{ 0xfe000000, 0x42000000, 0x01000000 }, /* CSR */
{ 0xffe00000, 0x7c000000, 0x00100000 }, /* PCI I/O */
{ 0xfff00000, 0x40000000, 0x00100000 }, /* X-Bus */
};
#define SIZEOFIO (sizeof(io_mapping) / sizeof(io_mapping[0]))
/* map in IO */
unsigned long setup_io_pagetables(unsigned long start_mem)
{
struct mapping *mp;
int i;
for (i = 0, mp = io_mapping; i < SIZEOFIO; i++, mp++) {
while ((mp->virtual & 1048575 || mp->physical & 1048575) && mp->length >= PAGE_SIZE) {
alloc_init_page(&start_mem, mp->virtual, mp->physical, DOMAIN_IO,
PTE_AP_WRITE);
mp->length -= PAGE_SIZE;
mp->virtual += PAGE_SIZE;
mp->physical += PAGE_SIZE;
}
while (mp->length >= 1048576) {
if (mp->virtual > 0xf0000000)
alloc_init_section(&start_mem, mp->virtual, mp->physical, DOMAIN_IO,
PMD_SECT_AP_WRITE);
else
alloc_init_section(&start_mem, mp->virtual, mp->physical, DOMAIN_USER, PMD_SECT_AP_WRITE | PMD_SECT_AP_READ);
mp->length -= 1048576;
mp->virtual += 1048576;
mp->physical += 1048576;
}
while (mp->length >= PAGE_SIZE) {
alloc_init_page(&start_mem, mp->virtual, mp->physical, DOMAIN_IO,
PTE_AP_WRITE);
mp->length -= PAGE_SIZE;
mp->virtual += PAGE_SIZE;
mp->physical += PAGE_SIZE;
}
}
return start_mem;
}
/*
* arch/arm/mm/mm-nexuspci.c
* from arch/arm/mm/mm-ebsa110.c
*
* Extra MM routines for the Archimedes architecture
* Extra MM routines for the NexusPCI architecture
*
* Copyright (C) 1998 Russell King
*/
#include <asm/io.h>
/* map in IO */
void setup_io_pagetables(void)
{
unsigned long address = IO_START;
int spi = IO_BASE >> PGDIR_SHIFT;
pgd_val(swapper_pg_dir[spi-1]) = 0xc0000000 | PMD_TYPE_SECT |
PMD_DOMAIN(DOMAIN_KERNEL) | PMD_SECT_AP_WRITE;
while (address < IO_START + IO_SIZE && address) {
pgd_val(swapper_pg_dir[spi++]) = address | PMD_TYPE_SECT |
PMD_DOMAIN(DOMAIN_IO) |
PMD_SECT_AP_WRITE;
address += PGDIR_SIZE;
}
}
......@@ -6,7 +6,14 @@
* Copyright (C) 1998 Russell King
*/
#include <linux/sched.h>
#include <linux/slab.h>
#include <asm/pgtable.h>
#include <asm/setup.h>
#include <asm/io.h>
#include <asm/proc/mm-init.h>
#include <asm/arch/mm-init.h>
#define NR_DRAM_BANKS 4
#define NR_VRAM_BANKS 1
......@@ -21,8 +28,8 @@
#define FIRST_DRAM_ADDR 0x10000000
#define PHYS_TO_BANK(x) (((x) >> BANK_SHIFT) & (NR_DRAM_BANKS - 1))
#define BANK_TO_PHYS(x) ((FIRST_DRAM_ADDR) +
(((x) - FIRST_DRAM_BANK) << BANK_SHIFT)
#define BANK_TO_PHYS(x) ((FIRST_DRAM_ADDR) + \
(((x) - FIRST_DRAM_BANK) << BANK_SHIFT))
struct ram_bank {
unsigned int virt_addr; /* virtual address of the *end* of this bank + 1 */
......@@ -75,6 +82,56 @@ void init_dram_banks(struct param_struct *params)
rambank[bank].virt_addr = PAGE_OFFSET + bytes;
}
drambank[4].phys_offset = 0xd6000000;
drambank[4].virt_addr = 0xd8000000;
rambank[FIRST_VRAM_BANK].phys_offset = 0xd6000000;
rambank[FIRST_VRAM_BANK].virt_addr = 0xd8000000;
current->tss.memmap = __virt_to_phys((unsigned long)swapper_pg_dir);
}
static struct mapping {
unsigned long virtual;
unsigned long physical;
unsigned long length;
} io_mapping[] = {
{ SCREEN2_BASE, SCREEN_START, 2*1048576 }, /* VRAM */
{ IO_BASE, IO_START, IO_SIZE } /* IO space */
};
#define SIZEOFIO (sizeof(io_mapping) / sizeof(io_mapping[0]))
/* map in IO */
unsigned long setup_io_pagetables(unsigned long start_mem)
{
struct mapping *mp;
int i;
for (i = 0, mp = io_mapping; i < SIZEOFIO; i++, mp++) {
while ((mp->virtual & 1048575 || mp->physical & 1048575) && mp->length >= PAGE_SIZE) {
alloc_init_page(&start_mem, mp->virtual, mp->physical, DOMAIN_IO,
PTE_AP_WRITE);
mp->length -= PAGE_SIZE;
mp->virtual += PAGE_SIZE;
mp->physical += PAGE_SIZE;
}
while (mp->length >= 1048576) {
alloc_init_section(&start_mem, mp->virtual, mp->physical, DOMAIN_IO,
PMD_SECT_AP_WRITE);
mp->length -= 1048576;
mp->virtual += 1048576;
mp->physical += 1048576;
}
while (mp->length >= PAGE_SIZE) {
alloc_init_page(&start_mem, mp->virtual, mp->physical, DOMAIN_IO,
PTE_AP_WRITE);
mp->length -= PAGE_SIZE;
mp->virtual += PAGE_SIZE;
mp->physical += PAGE_SIZE;
}
}
return start_mem;
}
......@@ -72,10 +72,10 @@ _arm6_7_switch_to:
stmfd sp!, {ip} @ Save cpsr_SVC
str sp, [r0, #TSS_SAVE] @ Save sp_SVC
ldr sp, [r1, #TSS_SAVE] @ Get saved sp_SVC
ldr r0, [r1, #ADDR_LIMIT]
ldr r0, [r1, #TSK_ADDR_LIMIT]
teq r0, #0
moveq r0, #KERNEL_DOMAIN
movne r0, #USER_DOMAIN
moveq r0, #DOM_KERNELDOMAIN
movne r0, #DOM_USERDOMAIN
mcr p15, 0, r0, c3, c0 @ Set domain reg
ldr r0, [r1, #TSS_MEMMAP] @ Page table pointer
mov r1, #0
......
......@@ -161,8 +161,6 @@ _sa110_flush_icache_area:
blt 1b
mcr p15, 0, r0, c7, c5, 0 @ flush I cache
mov pc, lr
@LC0: .word _current
/*
* Function: sa110_switch_to (struct task_struct *prev, struct task_struct *next)
*
......@@ -183,10 +181,10 @@ _sa110_switch_to:
stmfd sp!, {ip} @ Save cpsr_SVC
str sp, [r0, #TSS_SAVE] @ Save sp_SVC
ldr sp, [r1, #TSS_SAVE] @ Get saved sp_SVC
ldr r0, [r1, #ADDR_LIMIT]
ldr r0, [r1, #TSK_ADDR_LIMIT]
teq r0, #0
moveq r0, #KERNEL_DOMAIN
movne r0, #USER_DOMAIN
moveq r0, #DOM_KERNELDOMAIN
movne r0, #DOM_USERDOMAIN
mcr p15, 0, r0, c3, c0 @ Set segment
ldr r0, [r1, #TSS_MEMMAP] @ Page table pointer
ldr r3, =Lclean_switch
......@@ -227,8 +225,6 @@ _sa110_data_abort:
mov r2, r2, lsr #19 @ b1 = L
and r3, r2, #0x69 << 2
and r2, r2, #2
// teq r3, #0x21 << 2
// orreq r2, r2, #1 @ b0 = {LD,ST}RT
mrc p15, 0, r1, c5, c0, 0 @ get FSR
and r1, r1, #255
mov pc, lr
......
/* ld script to make i386 Linux kernel
/* ld script to make ARM Linux kernel
* taken from the i386 version
* Written by Martin Mares <mj@atrey.karlin.mff.cuni.cz>
*/
OUTPUT_FORMAT("elf32-arm", "elf32-arm", "elf32-arm")
......@@ -34,11 +35,15 @@ SECTIONS
_edata = .; /* End of data section */
. = ALIGN(4096); /* Init code and data */
/* This has to be aligned to a page boundary to do us any good. This
alignment is overkill for ARM6 up but needed for ARM3. Since all this
data will be thrown away I don't think the extra padding will hurt.
-- pb */
. = ALIGN(32768); /* Init code and data */
__init_begin = .;
.text.init : { *(.text.init) }
.data.init : { *(.data.init) }
. = ALIGN(4096);
. = ALIGN(32768);
__init_end = .;
__bss_start = .; /* BSS */
......
......@@ -112,7 +112,6 @@ static void read_intr (ide_drive_t *drive)
int i;
unsigned int msect, nsect;
struct request *rq;
unsigned long flags;
if (!OK_STAT(stat=GET_STAT(),DATA_READY,BAD_R_STAT)) {
ide_error(drive, "read_intr", stat);
......@@ -162,7 +161,6 @@ static void write_intr (ide_drive_t *drive)
int i;
ide_hwgroup_t *hwgroup = HWGROUP(drive);
struct request *rq = hwgroup->rq;
unsigned long flags;
int error = 0;
if (OK_STAT(stat=GET_STAT(),DRIVE_READY,drive->bad_wstat)) {
......@@ -239,7 +237,6 @@ static void multwrite_intr (ide_drive_t *drive)
int i;
ide_hwgroup_t *hwgroup = HWGROUP(drive);
struct request *rq = &hwgroup->wrq;
unsigned long flags;
int error = 0;
if (OK_STAT(stat=GET_STAT(),DRIVE_READY,drive->bad_wstat)) {
......
......@@ -1267,7 +1267,6 @@ static void unexpected_intr (int irq, ide_hwgroup_t *hwgroup)
static void do_ide_intr (int irq, void *dev_id, struct pt_regs *regs)
{
unsigned long flags;
ide_hwgroup_t *hwgroup = dev_id;
ide_hwif_t *hwif = hwgroup->hwif;
ide_handler_t *handler;
......
......@@ -84,9 +84,9 @@ __initfunc(void ide_probe_for_rz100x (void)) /* called from ide.c */
{
struct pci_dev *dev = NULL;
while (dev = pci_find_device(PCI_VENDOR_ID_PCTECH, PCI_DEVICE_PD_PCTECH_RZ1000, dev))
while (dev = pci_find_device(PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_RZ1000, dev))
init_rz1000 (dev, "RZ1000");
while (dev = pci_find_device(PCI_VENDOR_ID_PCTECH, PCI_DEVICE_PD_PCTECH_RZ1001, dev))
while (dev = pci_find_device(PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_RZ1001, dev))
init_rz1000 (dev, "RZ1001");
}
......
This diff is collapsed.
......@@ -239,23 +239,32 @@ static void lp_error(int minor)
}
static int lp_check_status(int minor) {
static unsigned char last = 0;
unsigned char status = r_str(minor);
if ((status & LP_POUTPA)) {
printk(KERN_INFO "lp%d out of paper\n", minor);
if (LP_F(minor) & LP_ABORT)
return 1;
lp_error(minor);
if (last != LP_POUTPA) {
last = LP_POUTPA;
printk(KERN_INFO "lp%d out of paper\n", minor);
}
} else if (!(status & LP_PSELECD)) {
printk(KERN_INFO "lp%d off-line\n", minor);
if (LP_F(minor) & LP_ABORT)
return 1;
lp_error(minor);
if (last != LP_PSELECD) {
last = LP_PSELECD;
printk(KERN_INFO "lp%d off-line\n", minor);
}
} else if (!(status & LP_PERRORP)) {
printk(KERN_ERR "lp%d printer error\n", minor);
if (last != LP_PERRORP) {
last = LP_PERRORP;
printk(KERN_ERR "lp%d on fire!\n", minor);
}
}
else last = 0;
if (last != 0) {
if (LP_F(minor) & LP_ABORT)
return 1;
lp_error(minor);
}
return 0;
}
......
......@@ -145,12 +145,12 @@ __initfunc(static char *initialize_kbd2(void))
*/
do {
kbd_write(KBD_DATA_REG, KBD_CMD_RESET);
kbd_write(KBD_DATA_REG, KBD_CMD_RESET);
status = kbd_wait_for_input();
if (status == KBD_REPLY_ACK)
break;
else if (status != KBD_REPLY_RESEND)
return "Keyboard reset failed, no ACK";
return "Keyboard reset failed, no ACK";
} while (1);
if (kbd_wait_for_input() != KBD_REPLY_POR)
......@@ -164,12 +164,12 @@ __initfunc(static char *initialize_kbd2(void))
*/
do {
kbd_write(KBD_DATA_REG, KBD_CMD_DISABLE);
kbd_write(KBD_DATA_REG, KBD_CMD_DISABLE);
status = kbd_wait_for_input();
if (status == KBD_REPLY_ACK)
break;
else if (status != KBD_REPLY_RESEND)
return "Disable keyboard: no ACK";
return "Disable keyboard: no ACK";
} while (1);
kbd_write(KBD_CNTL_REG, KBD_CCMD_WRITE_MODE);
......
......@@ -20,7 +20,7 @@
#ifndef MODULE
static int io[PARPORT_MAX+1] __initdata = { [0 ... PARPORT_MAX] = 0 };
static int irq[PARPORT_MAX] __initdata = { [0 ... PARPORT_MAX-1] = PARPORT_IRQ_NONE };
static int irq[PARPORT_MAX] __initdata = { [0 ... PARPORT_MAX-1] = PARPORT_IRQ_PROBEONLY };
static int dma[PARPORT_MAX] __initdata = { [0 ... PARPORT_MAX-1] = PARPORT_DMA_NONE };
extern int parport_pc_init(int *io, int *irq, int *dma);
......@@ -30,26 +30,68 @@ static int parport_setup_ptr __initdata = 0;
__initfunc(void parport_setup(char *str, int *ints))
{
if (ints[0] == 0 || ints[1] == 0) {
/* Disable parport if "parport=" or "parport=0" in cmdline */
if (ints[0] == 0) {
if (str && !strncmp(str, "auto", 4)) {
irq[0] = PARPORT_IRQ_AUTO;
dma[0] = PARPORT_DMA_AUTO;
}
else if (str)
printk (KERN_ERR "parport: `%s': huh?\n", str);
else
printk (KERN_ERR "parport: parport=.. what?\n");
return;
}
else if (ints[1] == 0) {
/* Disable parport if "parport=0" in cmdline */
io[0] = PARPORT_DISABLE;
return;
}
if (parport_setup_ptr < PARPORT_MAX) {
char *sep;
io[parport_setup_ptr] = ints[1];
if (ints[0]>1) {
irq[parport_setup_ptr] = PARPORT_IRQ_NONE;
dma[parport_setup_ptr] = PARPORT_DMA_NONE;
if (ints[0] > 1) {
irq[parport_setup_ptr] = ints[2];
if (ints[0]>2) dma[parport_setup_ptr] = ints[3];
if (ints[0] > 2) {
dma[parport_setup_ptr] = ints[3];
goto done;
}
if (str == NULL)
goto done;
goto dma_from_str;
}
parport_setup_ptr++;
} else {
printk(KERN_ERR "parport=0x%x", ints[1]);
if (ints[0]>1) {
printk(",%d", ints[2]);
if (ints[0]>2) printk(",%d", ints[3]);
else if (str == NULL)
goto done;
else if (!strncmp(str, "auto", 4))
irq[parport_setup_ptr] = PARPORT_IRQ_AUTO;
else if (strncmp(str, "none", 4) != 0) {
printk(KERN_ERR "parport: bad irq `%s'\n", str);
return;
}
printk(" ignored, too many ports.\n");
}
if ((sep = strchr(str, ',')) == NULL) goto done;
str = sep+1;
dma_from_str:
if (!strncmp(str, "auto", 4))
dma[parport_setup_ptr] = PARPORT_DMA_AUTO;
else if (strncmp(str, "none", 4) != 0) {
char *ep;
dma[parport_setup_ptr] = simple_strtoul(str, &ep, 0);
if (ep == str) {
printk(KERN_ERR "parport: bad dma `%s'\n",
str);
return;
}
}
done:
parport_setup_ptr++;
} else
printk(KERN_ERR "parport=%s ignored, too many ports\n", str);
}
#endif
......@@ -100,6 +142,7 @@ EXPORT_SYMBOL(parport_wait_peripheral);
EXPORT_SYMBOL(parport_proc_register);
EXPORT_SYMBOL(parport_proc_unregister);
EXPORT_SYMBOL(parport_probe_hook);
EXPORT_SYMBOL(parport_parse_irqs);
void inc_parport_count(void)
{
......
......@@ -36,7 +36,6 @@
#include <asm/ptrace.h>
#include <asm/io.h>
#include <asm/dma.h>
#include <linux/module.h>
#include <linux/delay.h>
......@@ -276,159 +275,6 @@ struct parport_operations parport_pc_ops =
parport_pc_dec_use_count
};
/* --- DMA detection -------------------------------------- */
/*
* Prepare DMA channels from 0-8 to transmit towards buffer
*/
static int parport_prepare_dma(char *buff, int size)
{
int tmp = 0;
int i,retv;
for (i = 0; i < 8; i++) {
retv = request_dma(i, "probe");
if (retv)
continue;
tmp |= 1 << i;
cli();
disable_dma(i);
clear_dma_ff(i);
set_dma_addr(i, virt_to_bus(buff));
set_dma_count(i, size);
set_dma_mode(i, DMA_MODE_READ);
sti();
}
return tmp;
}
/*
* Activate all DMA channels passed in dma
*/
static int parport_enable_dma(int dma)
{
int i;
for (i = 0; i < 8; i++)
if (dma & (1 << i)) {
cli();
enable_dma(i);
sti();
}
return dma;
}
static int parport_detect_dma_transfer(int dma, int size)
{
int i,n,retv;
int count=0;
retv = PARPORT_DMA_NONE;
for (i = 0; i < 8; i++)
if (dma & (1 << i)) {
disable_dma(i);
clear_dma_ff(i);
n = get_dma_residue(i);
if (n != size) {
retv = i;
if (count > 0) {
retv = PARPORT_DMA_NONE; /* Multiple DMA's */
printk(KERN_ERR "parport: multiple DMA detected. Huh?\n");
}
count++;
}
free_dma(i);
}
return retv;
}
/* Only if supports ECP mode */
static int programmable_dma_support(struct parport *pb)
{
unsigned char dma, oldstate = parport_pc_read_econtrol(pb);
parport_pc_write_econtrol(pb, 0xe0); /* Configuration MODE */
dma = parport_pc_read_configb(pb) & 0x07;
parport_pc_write_econtrol(pb, oldstate);
if (dma == 0 || dma == 4) /* Jumper selection */
return PARPORT_DMA_NONE;
else
return dma;
}
/* Only called if port supports ECP mode.
*
* The only restriction on DMA channels is that it has to be
* between 0 to 7 (inclusive). Used only in an ECP mode, DMAs are
* considered a shared resource and hence they should be registered
* when needed and then immediately unregistered.
*
* DMA autoprobes for ECP mode are known not to work for some
* main board BIOS configs. I had to remove everything from the
* port, set the mode to SPP, reboot to DOS, set the mode to ECP,
* and reboot again, then I got IRQ probes and DMA probes to work.
* [Is the BIOS doing a device detection?]
*
* A value of PARPORT_DMA_NONE is allowed indicating no DMA support.
*
* if( 0 < DMA < 4 )
* 1Byte DMA transfer
* else // 4 < DMA < 8
* 2Byte DMA transfer
*
*/
static int parport_dma_probe(struct parport *pb)
{
int dma,retv;
unsigned char dsr,dsr_read;
char *buff;
retv = programmable_dma_support(pb);
if (retv != PARPORT_DMA_NONE)
return retv;
if (!(buff = kmalloc(2048, GFP_KERNEL | GFP_DMA))) {
printk(KERN_ERR "parport: memory squeeze\n");
return PARPORT_DMA_NONE;
}
dsr = pb->ops->read_control(pb);
dsr_read = (dsr & ~(0x20)) | 0x04; /* Direction == read */
pb->ops->write_econtrol(pb, 0xc0); /* ECP MODE */
pb->ops->write_control(pb, dsr_read );
dma = parport_prepare_dma(buff, 1000);
pb->ops->write_econtrol(pb, 0xd8); /* ECP FIFO + enable DMA */
parport_enable_dma(dma);
udelay(500); /* Give some for DMA tranfer */
retv = parport_detect_dma_transfer(dma, 1000);
/*
* National Semiconductors only supports DMA tranfers
* in ECP MODE
*/
if (retv == PARPORT_DMA_NONE) {
pb->ops->write_econtrol(pb, 0x60); /* ECP MODE */
pb->ops->write_control(pb, dsr_read );
dma=parport_prepare_dma(buff,1000);
pb->ops->write_econtrol(pb, 0x68); /* ECP FIFO + enable DMA */
parport_enable_dma(dma);
udelay(500); /* Give some for DMA tranfer */
retv = parport_detect_dma_transfer(dma, 1000);
}
kfree(buff);
return retv;
}
/* --- Mode detection ------------------------------------- */
/*
......@@ -807,6 +653,7 @@ static int parport_irq_probe(struct parport *pb)
static int probe_one_port(unsigned long int base, int irq, int dma)
{
struct parport tmpport, *p;
int probedirq = PARPORT_IRQ_NONE;
if (check_region(base, 3)) return 0;
tmpport.base = base;
tmpport.ops = &parport_pc_ops;
......@@ -830,12 +677,16 @@ static int probe_one_port(unsigned long int base, int irq, int dma)
if (p->irq == PARPORT_IRQ_AUTO) {
p->irq = PARPORT_IRQ_NONE;
parport_irq_probe(p);
} else if (p->irq == PARPORT_IRQ_PROBEONLY) {
p->irq = PARPORT_IRQ_NONE;
parport_irq_probe(p);
probedirq = p->irq;
p->irq = PARPORT_IRQ_NONE;
}
if (p->irq != PARPORT_IRQ_NONE)
printk(", irq %d", p->irq);
if (p->dma == PARPORT_DMA_AUTO)
p->dma = (p->modes & PARPORT_MODE_PCECP)?
parport_dma_probe(p):PARPORT_DMA_NONE;
p->dma = PARPORT_DMA_NONE;
if (p->dma != PARPORT_DMA_NONE)
printk(", dma %d", p->dma);
printk(" [");
......@@ -851,6 +702,8 @@ static int probe_one_port(unsigned long int base, int irq, int dma)
}
#undef printmode
printk("]\n");
if (probedirq != PARPORT_IRQ_NONE)
printk("%s: detected irq %d; use procfs to enable interrupt-driven operation.\n", p->name, probedirq);
parport_proc_register(p);
p->flags |= PARPORT_FLAG_COMA;
......@@ -875,9 +728,9 @@ int parport_pc_init(int *io, int *irq, int *dma)
} while (*io && (++i < PARPORT_PC_MAX_PORTS));
} else {
/* Probe all the likely ports. */
count += probe_one_port(0x3bc, PARPORT_IRQ_AUTO, PARPORT_DMA_AUTO);
count += probe_one_port(0x378, PARPORT_IRQ_AUTO, PARPORT_DMA_AUTO);
count += probe_one_port(0x278, PARPORT_IRQ_AUTO, PARPORT_DMA_AUTO);
count += probe_one_port(0x3bc, irq[0], dma[0]);
count += probe_one_port(0x378, irq[0], dma[0]);
count += probe_one_port(0x278, irq[0], dma[0]);
}
/* Give any attached devices a chance to gather their thoughts */
......@@ -890,15 +743,22 @@ int parport_pc_init(int *io, int *irq, int *dma)
#ifdef MODULE
static int io[PARPORT_PC_MAX_PORTS+1] = { [0 ... PARPORT_PC_MAX_PORTS] = 0 };
static int dma[PARPORT_PC_MAX_PORTS] = { [0 ... PARPORT_PC_MAX_PORTS-1] = PARPORT_DMA_AUTO };
static int irq[PARPORT_PC_MAX_PORTS] = { [0 ... PARPORT_PC_MAX_PORTS-1] = PARPORT_IRQ_AUTO };
static int dma[PARPORT_PC_MAX_PORTS] = { [0 ... PARPORT_PC_MAX_PORTS-1] = PARPORT_DMA_NONE };
static int irqval[PARPORT_PC_MAX_PORTS] = { [0 ... PARPORT_PC_MAX_PORTS-1] = PARPORT_IRQ_PROBEONLY };
static char *irq = NULL;
MODULE_PARM(io, "1-" __MODULE_STRING(PARPORT_PC_MAX_PORTS) "i");
MODULE_PARM(irq, "1-" __MODULE_STRING(PARPORT_PC_MAX_PORTS) "i");
MODULE_PARM(irq, "1-" __MODULE_STRING(PARPORT_PC_MAX_PORTS) "s");
MODULE_PARM(dma, "1-" __MODULE_STRING(PARPORT_PC_MAX_PORTS) "i");
int init_module(void)
{
return (parport_pc_init(io, irq, dma)?0:1);
/* Work out how many ports we have, then get parport_share to parse
the irq values. */
unsigned int i;
for (i = 0; i < PARPORT_PC_MAX_PORTS && io[i]; i++);
parport_parse_irqs(i, irq, irqval);
return (parport_pc_init(io, irqval, dma)?0:1);
}
void cleanup_module(void)
......
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.
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.
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.
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