Commit 88af9fa8 authored by Alan Cox's avatar Alan Cox Committed by Linus Torvalds

[PATCH] arch specific files for MMUless NEC v850 port

This is the V850 support maintained by Miles Bader at NEC

Again this is just arch and include/asm- files. It matches 2.5.45-uc1 + v850
fixes which is close to what was in my old tree (some clean up done since then)
plus Kconfig
parent 9ce59cdc
#############################################################################
#
# For a description of the syntax of this configuration file,
# see Documentation/kbuild/config-language.txt.
#
#############################################################################
mainmenu "uClinux/v850 (w/o MMU) Kernel Configuration"
config MMU
bool
default n
config SWAP
bool
default n
config UID16
bool
default n
config RWSEM_GENERIC_SPINLOCK
bool
default y
config RWSEM_XCHGADD_ALGORITHM
bool
default n
# Turn off some random 386 crap that can affect device config
config ISA
bool
default n
config ISAPNP
bool
default n
config EISA
bool
default n
config MCA
bool
default n
#############################################################################
#### v850-specific config
# Define the architecture
config V850
bool
default y
menu "Processor type and features"
choice
prompt "Platform"
default GDB
config RTE_CB_MA1
bool "RTE-V850E/MA1-CB"
config RTE_CB_NB85E
bool "RTE-V850E/NB85E-CB"
config V850E_SIM
bool "GDB"
config V850E2_SIM85E2C
bool "sim85e2c"
config V850E2_FPGA85E2C
bool "NA85E2C-FPGA"
config V850E2_ANNA
bool "Anna"
endchoice
#### V850E processor-specific config
# All CPUs currently supported use the v850e architecture
config V850E
bool
default y
# The RTE-V850E/MA1-CB is the only type of V850E/MA1 platform we
# currently support
config V850E_MA1
bool
depends RTE_CB_MA1
default y
# Similarly for the RTE-V850E/MA1-CB - V850E/TEG
config V850E_TEG
bool
depends RTE_CB_NB85E
default y
# NB85E processor core
config V850E_NB85E
bool
depends V850E_MA1 || V850E_TEG
default y
config V850E_MA1_HIGHRES_TIMER
bool "High resolution timer support"
depends V850E_MA1
#### V850E2 processor-specific config
# V850E2 processors
config V850E2
bool
depends V850E2_SIM85E2C || V850E2_FPGA85E2C || V850E2_ANNA
default y
# Processors based on the NA85E2A core
config V850E2_NA85E2A
bool
depends V850E2_ANNA
default y
# Processors based on the NA85E2C core
config V850E2_NA85E2C
bool
depends V850E2_SIM85E2C || V850E2_FPGA85E2C
default y
#### RTE-CB platform-specific config
# Boards in the RTE-x-CB series
config RTE_CB
bool
depends RTE_CB_MA1 || RTE_CB_NB85E
default y
# Currently, we only support RTE-CB boards using the Multi debugger
config RTE_CB_MULTI
bool
depends RTE_CB
default y
config RTE_CB_MA1_KSRAM
bool "Kernel in SRAM (limits size of kernel)"
depends RTE_CB_MA1 && RTE_CB_MULTI
default n
config RTE_MB_A_PCI
bool "Mother-A PCI support"
depends RTE_CB
default y
# The GBUS is used to talk to the RTE-MOTHER-A board
config RTE_GBUS_INT
bool
depends RTE_MB_A_PCI
default y
# The only PCI bus we support is on the RTE-MOTHER-A board
config PCI
bool
default y if RTE_MB_A_PCI
#### Misc config
config ROM_KERNEL
bool "Kernel in ROM"
depends V850E2_ANNA || (RTE_CB && !RTE_CB_MULTI)
# Some platforms pre-zero memory, in which case the kernel doesn't need to
config ZERO_BSS
bool
depends !V850E2_SIM85E2C
default y
# The crappy-ass zone allocator requires that the start of allocatable
# memory be aligned to the largest possible allocation.
config FORCE_MAX_ZONEORDER
int
default 8 if V850E2_SIM85E2C || V850E2_FPGA85E2C
config TIME_BOOTUP
bool "Time bootup"
depends V850E_MA1_HIGHRES_TIMER
config RESET_GUARD
bool "Reset Guard"
config LARGE_ALLOCS
bool "Allow allocating large blocks (> 1MB) of memory"
help
Allow the slab memory allocator to keep chains for very large
memory sizes - upto 32MB. You may need this if your system has
a lot of RAM, and you need to able to allocate very large
contiguous chunks. If unsure, say N.
endmenu
#############################################################################
source init/Kconfig
#############################################################################
menu "Bus options (PCI, PCMCIA, EISA, MCA, ISA)"
# config PCI
# bool "PCI support"
# help
# Support for PCI bus.
source "drivers/pci/Kconfig"
config HOTPLUG
bool "Support for hot-pluggable device"
---help---
Say Y here if you want to plug devices into your computer while
the system is running, and be able to use them quickly. In many
cases, the devices can likewise be unplugged at any time too.
One well known example of this is PCMCIA- or PC-cards, credit-card
size devices such as network cards, modems or hard drives which are
plugged into slots found on all modern laptop computers. Another
example, used on modern desktops as well as laptops, is USB.
Enable HOTPLUG and KMOD, and build a modular kernel. Get agent
software (at <http://linux-hotplug.sourceforge.net/>) and install it.
Then your kernel will automatically call out to a user mode "policy
agent" (/sbin/hotplug) to load modules and set up software needed
to use devices as you hotplug them.
source "drivers/pcmcia/Kconfig"
source "drivers/hotplug/Kconfig"
endmenu
menu "Executable file formats"
config KCORE_AOUT
bool
default y
config KCORE_ELF
default y
config BINFMT_FLAT
tristate "Kernel support for flat binaries"
help
Support uClinux FLAT format binaries.
config BINFMT_ZFLAT
bool " Enable ZFLAT support"
depends on BINFMT_FLAT
help
Support FLAT format compressed binaries
endmenu
#############################################################################
source drivers/mtd/Kconfig
source drivers/parport/Kconfig
#source drivers/pnp/Kconfig
source drivers/block/Kconfig
#############################################################################
menu "Disk device support"
config IDE
tristate "ATA/ATAPI/MFM/RLL device support"
---help---
If you say Y here, your kernel will be able to manage low cost mass
storage units such as ATA/(E)IDE and ATAPI units. The most common
cases are IDE hard drives and ATAPI CD-ROM drives.
It only makes sense to choose this option if your board actually
has an IDE interface. If unsure, say N.
source "drivers/ide/Kconfig"
config SCSI
tristate "SCSI device support"
help
If you want to use a SCSI hard disk, SCSI tape drive, SCSI CD-ROM or
any other SCSI device under Linux, say Y and make sure that you know
the name of your SCSI host adapter (the card inside your computer
that "speaks" the SCSI protocol, also called SCSI controller),
because you will be asked for it.
source "drivers/scsi/Kconfig"
endmenu
#############################################################################
source "drivers/md/Kconfig"
source "drivers/message/fusion/Kconfig"
source "drivers/ieee1394/Kconfig"
source "drivers/message/i2o/Kconfig"
source "net/Kconfig"
menu "Network device support"
depends on NET
config NETDEVICES
bool "Network device support"
---help---
You can say N here if you don't intend to connect your Linux box to
any other computer at all or if all your connections will be over a
telephone line with a modem either via UUCP (UUCP is a protocol to
forward mail and news between unix hosts over telephone lines; read
the UUCP-HOWTO, available from
<http://www.linuxdoc.org/docs.html#howto>) or dialing up a shell
account or a BBS, even using term (term is a program which gives you
almost full Internet connectivity if you have a regular dial up
shell account on some Internet connected Unix computer. Read
<http://www.bart.nl/~patrickr/term-howto/Term-HOWTO.html>).
You'll have to say Y if your computer contains a network card that
you want to use under Linux (make sure you know its name because you
will be asked for it and read the Ethernet-HOWTO (especially if you
plan to use more than one network card under Linux)) or if you want
to use SLIP (Serial Line Internet Protocol is the protocol used to
send Internet traffic over telephone lines or null modem cables) or
CSLIP (compressed SLIP) or PPP (Point to Point Protocol, a better
and newer replacement for SLIP) or PLIP (Parallel Line Internet
Protocol is mainly used to create a mini network by connecting the
parallel ports of two local machines) or AX.25/KISS (protocol for
sending Internet traffic over amateur radio links).
Make sure to read the NET-3-HOWTO. Eventually, you will have to read
Olaf Kirch's excellent and free book "Network Administrator's
Guide", to be found in <http://www.linuxdoc.org/docs.html#guide>. If
unsure, say Y.
source "drivers/net/Kconfig"
source "drivers/atm/Kconfig"
endmenu
source "net/ax25/Kconfig"
source "net/irda/Kconfig"
source "drivers/isdn/Kconfig"
#source "drivers/telephony/Kconfig"
#
# input before char - char/joystick depends on it. As does USB.
#
source "drivers/input/Kconfig"
source "drivers/char/Kconfig"
#source drivers/misc/Config.in
source "drivers/media/Kconfig"
source "fs/Kconfig"
menu "Console drivers"
depends on VT
config VGA_CONSOLE
bool "VGA text console"
help
Saying Y here will allow you to use Linux in text mode through a
display that complies with the generic VGA standard. Virtually
everyone wants that.
The program SVGATextMode can be used to utilize SVGA video cards to
their full potential in text mode. Download it from
<ftp://ibiblio.org/pub/Linux/utils/console/>.
If unsure, say N.
config VIDEO_SELECT
bool "Video mode selection support"
---help---
This enables support for text mode selection on kernel startup. If
you want to take advantage of some high-resolution text mode your
card's BIOS offers, but the traditional Linux utilities like
SVGATextMode don't, you can say Y here and set the mode using the
"vga=" option from your boot loader (lilo or loadlin) or set
"vga=ask" which brings up a video mode menu on kernel startup. (Try
"man bootparam" or see the documentation of your boot loader about
how to pass options to the kernel.)
Read the file <file:Documentation/svga.txt> for more information
about the Video mode selection support. If unsure, say N.
source "drivers/video/Kconfig"
endmenu
menu "Sound"
config SOUND
tristate "Sound card support"
---help---
If you have a sound card in your computer, i.e. if it can say more
than an occasional beep, say Y. Be sure to have all the information
about your sound card and its configuration down (I/O port,
interrupt and DMA channel), because you will be asked for it.
You want to read the Sound-HOWTO, available from
<http://www.linuxdoc.org/docs.html#howto>. General information about
the modular sound system is contained in the files
<file:Documentation/sound/Introduction>. The file
<file:Documentation/sound/README.OSS> contains some slightly
outdated but still useful information as well.
If you have a PnP sound card and you want to configure it at boot
time using the ISA PnP tools (read
<http://www.roestock.demon.co.uk/isapnptools/>), then you need to
compile the sound card support as a module ( = code which can be
inserted in and removed from the running kernel whenever you want)
and load that module after the PnP configuration is finished. To do
this, say M here and read <file:Documentation/modules.txt> as well
as <file:Documentation/sound/README.modules>; the module will be
called soundcore.o.
I'm told that even without a sound card, you can make your computer
say more than an occasional beep, by programming the PC speaker.
Kernel patches and supporting utilities to do that are in the pcsp
package, available at <ftp://ftp.infradead.org/pub/pcsp/>.
source "sound/Kconfig"
endmenu
source "drivers/usb/Kconfig"
source "net/bluetooth/Kconfig"
menu "Kernel hacking"
config FULLDEBUG
bool "Full Symbolic/Source Debugging support"
help
Enable debuging symbols on kernel build.
config MAGIC_SYSRQ
bool "Magic SysRq key"
help
Enables console device to interprent special characters as
commands to dump state information.
config HIGHPROFILE
bool "Use fast second timer for profiling"
help
Use a fast secondary clock to produce profiling information.
config DUMPTOFLASH
bool "Panic/Dump to FLASH"
depends on COLDFIRE
help
Dump any panic of trap output into a flash memory segment
for later analysis.
config NO_KERNEL_MSG
bool "Suppress Kernel BUG Messages"
help
Do not output any debug BUG messages within the kernel.
config BDM_DISABLE
bool "Disable BDM signals"
depends on (EXPERIMENTAL && COLDFIRE)
help
Disable the CPU's BDM signals.
endmenu
source "security/Kconfig"
source "crypto/Kconfig"
source "lib/Kconfig"
#############################################################################
#
# arch/v850/Makefile
#
# Copyright (C) 2001,02 NEC Corporation
# Copyright (C) 2001,02 Miles Bader <miles@gnu.org>
#
# This file is included by the global makefile so that you can add your own
# architecture-specific flags and dependencies. Remember to do have actions
# for "archclean" and "archdep" for cleaning up and making dependencies for
# this architecture
#
# This file is subject to the terms and conditions of the GNU General Public
# License. See the file "COPYING" in the main directory of this archive
# for more details.
#
arch_dir = arch/v850
CFLAGS += -mv850e
# r16 is a fixed pointer to the current task
CFLAGS += -ffixed-r16 -mno-prolog-function
CFLAGS += -fno-builtin
CFLAGS += -D__linux__ -DUTS_SYSNAME=\"uClinux\"
HEAD := $(arch_dir)/kernel/head.o $(arch_dir)/kernel/init_task.o
core-y += $(arch_dir)/kernel/
libs-y += $(arch_dir)/lib/
include $(TOPDIR)/Rules.make
# Deal with the initial contents of the root device
ifdef ROOT_FS_IMAGE
core-y += root_fs_image.o
# Because the kernel build-system erases all explicit .o build rules, we
# have to use an intermediate target to fool it into building for us.
# This results in it being built anew each time, but that's alright.
root_fs_image.o: root_fs_image_force
# Note that we use the build-system's objcopy, as the v850 tools are fairly
# old, and don't have the --rename-section option.
root_fs_image_force: $(ROOT_FS_IMAGE)
objcopy -I binary -O elf32-little -B i386 --rename-section .data=.root,alloc,load,readonly,data,contents $< root_fs_image.o
endif
prepare: include/asm-$(ARCH)/asm-consts.h
# Generate constants from C code for use by asm files
arch/$(ARCH)/kernel/asm-consts.s: include/asm include/linux/version.h \
include/config/MARKER
include/asm-$(ARCH)/asm-consts.h.tmp: arch/$(ARCH)/kernel/asm-consts.s
@$(generate-asm-offsets.h) < $< > $@
include/asm-$(ARCH)/asm-consts.h: include/asm-$(ARCH)/asm-consts.h.tmp
@echo -n ' Generating $@'
@$(update-if-changed)
CLEAN_FILES += include/asm-$(ARCH)/asm-consts.h.tmp \
include/asm-$(ARCH)/asm-consts.h \
arch/$(ARCH)/kernel/asm-consts.s \
root_fs_image.o
This port to the NEC V850E processor supports the following platforms:
+ The gdb v850e simulator (CONFIG_V850E_SIM); see the subdirectory `sim'
for some more support files for this.
+ The Midas labs RTE-V850E/MA1-CB evaluation board (CONFIG_RTE_CB_MA1),
with untested support for the RTE-V850E/NB85E-CB board
(CONFIG_RTE_CB_NB85E). This support has only been tested when running
with the Multi-debugger monitor ROM (for the Green Hills Multi debugger).
The optional NEC Solution Gear RTE-MOTHER-A motherboard is also
supported, which allows PCI boards to be used (CONFIG_RTE_MB_A_PCI).
+ The sim85e2c simulator, which is a verilog simulation of the V850E2
NA85E2C cpu core (CONFIG_V850E2_SIM85E2C).
+ A FPGA implementation of the V850E2 NA85E2C cpu core
(CONFIG_V850E2_FPGA85E2C).
+ The `Anna' (board/chip) implementation of the V850E2 processor.
Porting to anything with a V850E/MA1 or MA2 processor should be simple.
See the file <asm-v850/machdep.h> and the files it includes for an example of
how to add platform/chip-specific support.
/* Linker script for the Midas labs Anna V850E2 evaluation board
(CONFIG_V850E2_ANNA), with kernel in ROM (CONFIG_ROM_KERNEL). */
/* Note, all symbols are prefixed with an extra `_' for compatibility with
the existing linux sources. */
_jiffies = _jiffies_64 ;
MEMORY {
/* 8MB of flash ROM. */
ROM : ORIGIN = 0, LENGTH = 0x00800000
/* 1MB of static RAM. This memory is mirrored 64 times. */
SRAM : ORIGIN = 0x04000000, LENGTH = 0x00100000
/* 64MB of DRAM. */
SDRAM : ORIGIN = 0x08000000, LENGTH = 0x04000000
}
SECTIONS {
.intv : {
__intv_start = . ;
*(.intv.reset) /* Reset vector */
*(.intv.common) /* Vectors common to all v850e proc. */
*(.intv.mach) /* Machine-specific int. vectors. */
__intv_end = . ;
} > ROM
.text ALIGN (0x10) : {
__stext = . ;
*(.text)
*(.exit.text) /* 2.5 convention */
*(.text.exit) /* 2.4 convention */
*(.text.lock)
*(.exitcall.exit)
__real_etext = . ; /* There may be data after here. */
*(.rodata)
. = ALIGN (0x4) ;
*(.kstrtab)
. = ALIGN (4) ;
*(.call_table_data)
*(.call_table_text)
. = ALIGN (16) ; /* Exception table. */
___start___ex_table = . ;
*(__ex_table)
___stop___ex_table = . ;
___start___ksymtab = . ;/* Kernel symbol table. */
*(__ksymtab)
___stop___ksymtab = . ;
. = ALIGN (4) ;
__etext = . ;
} > ROM
.init_text ALIGN (4096) : {
*(.init.text) /* 2.5 convention */
*(.text.init) /* 2.4 convention */
. = ALIGN (16) ;
___setup_start = . ;
*(.init.setup) /* 2.5 convention */
*(.setup.init) /* 2.4 convention */
___setup_end = . ;
___initcall_start = . ;
*(.initcall.init)
*(.initcall1.init)
*(.initcall2.init)
*(.initcall3.init)
*(.initcall4.init)
*(.initcall5.init)
*(.initcall6.init)
*(.initcall7.init)
. = ALIGN (4) ;
___initcall_end = . ;
} > ROM
/* Device contents for the root filesystem. */
.root ALIGN (4096) : {
__root_fs_image_start = . ;
*(.root)
__root_fs_image_end = . ;
} > ROM
__rom_copy_src_start = . ;
.data : {
__kram_start = . ;
__rom_copy_dst_start = . ;
__sdata = . ;
___data_start = . ;
*(.data)
*(.exit.data) /* 2.5 convention */
*(.data.exit) /* 2.4 convention */
. = ALIGN (16) ;
*(.data.cacheline_aligned)
. = ALIGN (0x2000) ;
*(.data.init_task)
. = ALIGN (0x2000) ;
__edata = . ;
} > SRAM AT> ROM
.init_data ALIGN (4096) : {
__init_start = . ;
*(.init.data) /* 2.5 convention */
*(.data.init) /* 2.4 convention */
__init_end = . ;
__rom_copy_dst_end = . ;
} > SRAM AT> ROM
.bss ALIGN (4096) : {
__sbss = . ;
*(.bss)
*(COMMON)
. = ALIGN (4) ;
__init_stack_end = . ;
__ebss = . ;
__kram_end = . ;
} > SRAM
.bootmap ALIGN (4096) : {
__bootmap = . ;
. = . + 4096 ; /* enough for 128MB. */
} > SRAM
}
/* Linker script for the Midas labs Anna V850E2 evaluation board
(CONFIG_V850E2_ANNA). */
/* Note, all symbols are prefixed with an extra `_' for compatibility with
the existing linux sources. */
_jiffies = _jiffies_64 ;
MEMORY {
/* 256KB of internal memory (followed by one mirror). */
iMEM0 : ORIGIN = 0, LENGTH = 0x00040000
/* 256KB of internal memory (followed by one mirror). */
iMEM1 : ORIGIN = 0x00040000, LENGTH = 0x00040000
/* 1MB of static RAM. This memory is mirrored 64 times. */
SRAM : ORIGIN = 0x04000000, LENGTH = 0x00100000
/* 64MB of DRAM. */
SDRAM : ORIGIN = 0x08000000, LENGTH = 0x04000000
}
SECTIONS {
.intv : {
__intv_start = . ;
*(.intv.reset) /* Reset vector */
*(.intv.common) /* Vectors common to all v850e proc. */
*(.intv.mach) /* Machine-specific int. vectors. */
__intv_end = . ;
} > iMEM0
.text : {
__kram_start = . ;
__stext = . ;
*(.text)
*(.exit.text) /* 2.5 convention */
*(.text.exit) /* 2.4 convention */
*(.text.lock)
*(.exitcall.exit)
__real_etext = . ; /* There may be data after here. */
*(.rodata)
. = ALIGN (0x4) ;
*(.kstrtab)
. = ALIGN (4) ;
*(.call_table_data)
*(.call_table_text)
. = ALIGN (16) ; /* Exception table. */
___start___ex_table = . ;
*(__ex_table)
___stop___ex_table = . ;
___start___ksymtab = . ;/* Kernel symbol table. */
*(__ksymtab)
___stop___ksymtab = . ;
. = ALIGN (4) ;
__etext = . ;
} > SRAM
.data ALIGN (0x4) : {
__sdata = . ;
___data_start = . ;
*(.data)
*(.exit.data) /* 2.5 convention */
*(.data.exit) /* 2.4 convention */
. = ALIGN (16) ;
*(.data.cacheline_aligned)
. = ALIGN (0x2000) ;
*(.data.init_task)
. = ALIGN (0x2000) ;
__edata = . ;
} > SRAM
.bss ALIGN (0x4) : {
__sbss = . ;
*(.bss)
*(COMMON)
. = ALIGN (4) ;
__init_stack_end = . ;
__ebss = . ;
} > SRAM
.init ALIGN (4096) : {
__init_start = . ;
*(.init.text) /* 2.5 convention */
*(.init.data)
*(.text.init) /* 2.4 convention */
*(.data.init)
. = ALIGN (16) ;
___setup_start = . ;
*(.init.setup) /* 2.5 convention */
*(.setup.init) /* 2.4 convention */
___setup_end = . ;
___initcall_start = . ;
*(.initcall.init)
*(.initcall1.init)
*(.initcall2.init)
*(.initcall3.init)
*(.initcall4.init)
*(.initcall5.init)
*(.initcall6.init)
*(.initcall7.init)
. = ALIGN (4) ;
___initcall_end = . ;
__init_end = . ;
__kram_end = . ;
} > SRAM
.bootmap ALIGN (4096) : {
__bootmap = . ;
. = . + 4096 ; /* enough for 128MB. */
} > SRAM
/* Device contents for the root filesystem. */
.root : {
__root_fs_image_start = . ;
*(.root)
__root_fs_image_end = . ;
} > SDRAM
}
/* Linker script for the FPGA implementation of the V850E2 NA85E2C cpu core
(CONFIG_V850E2_FPGA85E2C). */
/* Note, all symbols are prefixed with an extra `_' for compatibility with
the existing linux sources. */
_jiffies = _jiffies_64 ;
MEMORY {
/* Reset vector. */
RESET : ORIGIN = 0, LENGTH = 0x10
/* Interrupt vectors. */
INTV : ORIGIN = 0x10, LENGTH = 0x470
/* The `window' in RAM were we're allowed to load stuff. */
RAM_LOW : ORIGIN = 0x480, LENGTH = 0x0005FB80
/* Some more ram above the window were we can put bss &c. */
RAM_HIGH : ORIGIN = 0x00060000, LENGTH = 0x000A0000
/* This is the area visible from the outside world (we can use
this only for uninitialized data). */
VISIBLE : ORIGIN = 0x00200000, LENGTH = 0x00060000
}
SECTIONS {
.reset : {
__kram_start = . ;
__intv_start = . ;
*(.intv.reset) /* Reset vector */
} > RESET
.r0_ram : {
__r0_ram = . ;
. = . + 32 ;
} > RAM_LOW
.text : {
__stext = . ;
*(.text)
*(.exit.text) /* 2.5 convention */
*(.text.exit) /* 2.4 convention */
*(.text.lock)
*(.exitcall.exit)
__real_etext = . ; /* There may be data after here. */
*(.rodata)
. = ALIGN (0x4) ;
*(.kstrtab)
. = ALIGN (4) ;
*(.call_table_data)
*(.call_table_text)
. = ALIGN (16) ; /* Exception table. */
___start___ex_table = . ;
*(__ex_table)
___stop___ex_table = . ;
___start___ksymtab = . ;/* Kernel symbol table. */
*(__ksymtab)
___stop___ksymtab = . ;
. = ALIGN (4) ;
__etext = . ;
} > RAM_LOW
.data : {
__sdata = . ;
*(.data)
*(.exit.data) /* 2.5 convention */
*(.data.exit) /* 2.4 convention */
. = ALIGN (16) ;
*(.data.cacheline_aligned)
. = ALIGN (0x2000) ;
*(.data.init_task)
. = ALIGN (0x2000) ;
__edata = . ;
} > RAM_LOW
/* Device contents for the root filesystem. */
.root : {
. = ALIGN (4096) ;
__root_fs_image_start = . ;
*(.root)
__root_fs_image_end = . ;
} > RAM_LOW
.init ALIGN (4096) : {
__init_start = . ;
*(.init.text) /* 2.5 convention */
*(.init.data)
*(.text.init) /* 2.4 convention */
*(.data.init)
. = ALIGN (16) ;
___setup_start = . ;
*(.init.setup) /* 2.5 convention */
*(.setup.init) /* 2.4 convention */
___setup_end = . ;
___initcall_start = . ;
*(.initcall.init)
*(.initcall1.init)
*(.initcall2.init)
*(.initcall3.init)
*(.initcall4.init)
*(.initcall5.init)
*(.initcall6.init)
*(.initcall7.init)
. = ALIGN (4) ;
___initcall_end = . ;
} > RAM_LOW
/* Where the interrupt vectors are initially loaded. */
__intv_load_start = . ;
.intv : {
*(.intv.common) /* Vectors common to all v850e proc. */
*(.intv.mach) /* Machine-specific int. vectors. */
__intv_end = . ;
} > INTV AT> RAM_LOW
.bss : {
/* This is here so that when we free init memory the
load-time copy of the interrupt vectors and any empty
space at the end of the `RAM_LOW' area is freed too. */
. = ALIGN (4096);
__init_end = . ;
__sbss = . ;
*(.bss)
*(COMMON)
. = ALIGN (4) ;
__init_stack_end = . ;
__ebss = . ;
__kram_end = . ;
} > RAM_HIGH
.bootmap ALIGN (4096) : {
__bootmap = . ;
. = . + 4096 ; /* enough for 128MB. */
} > RAM_HIGH
.visible : {
_memcons_output = . ;
. = . + 0x8000 ;
_memcons_output_end = . ;
} > VISIBLE
}
#
# arch/v850/kernel/Makefile
#
# Copyright (C) 2001,02 NEC Corporation
# Copyright (C) 2001,02 Miles Bader <miles@gnu.org>
#
# This file is subject to the terms and conditions of the GNU General Public
# License. See the file "COPYING" in the main directory of this archive
# for more details.
#
EXTRA_TARGETS := head.o init_task.o
obj-y += intv.o entry.o process.o syscalls.o time.o semaphore.o setup.o \
signal.o irq.o mach.o ptrace.o bug.o
export-objs += v850_ksyms.o rte_mb_a_pci.o
obj-$(CONFIG_MODULES) += v850_ksyms.o
# chip-specific code
obj-$(CONFIG_V850E_MA1) += ma.o nb85e_utils.o nb85e_timer_d.o
obj-$(CONFIG_V850E_NB85E) += nb85e_intc.o
obj-$(CONFIG_V850E2_ANNA) += anna.o nb85e_intc.o nb85e_utils.o nb85e_timer_d.o
# platform-specific code
obj-$(CONFIG_V850E_SIM) += sim.o simcons.o
obj-$(CONFIG_V850E2_SIM85E2C) += sim85e2c.o nb85e_intc.o memcons.o
obj-$(CONFIG_V850E2_FPGA85E2C) += fpga85e2c.o nb85e_intc.o memcons.o
obj-$(CONFIG_RTE_CB) += rte_cb.o rte_cb_leds.o
obj-$(CONFIG_RTE_CB_MA1) += rte_ma1_cb.o
obj-$(CONFIG_RTE_CB_NB85E) += rte_nb85e_cb.o
obj-$(CONFIG_RTE_CB_MULTI) += rte_cb_multi.o
obj-$(CONFIG_RTE_MB_A_PCI) += rte_mb_a_pci.o
obj-$(CONFIG_RTE_GBUS_INT) += gbus_int.o
# feature-specific code
obj-$(CONFIG_V850E_MA1_HIGHRES_TIMER) += highres_timer.o
obj-$(CONFIG_PROC_FS) += procfs.o
include $(TOPDIR)/Rules.make
/*
* arch/v850/kernel/anna.c -- Anna V850E2 evaluation chip/board
*
* Copyright (C) 2002 NEC Corporation
* Copyright (C) 2002 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/bootmem.h>
#include <linux/major.h>
#include <linux/irq.h>
#include <asm/machdep.h>
#include <asm/atomic.h>
#include <asm/page.h>
#include <asm/nb85e_timer_d.h>
#include <asm/nb85e_uart.h>
#include "mach.h"
/* SRAM and SDRAM are vaguely contiguous (with a hole in between; see
mach_reserve_bootmem for details), so just use both as one big area. */
#define RAM_START SRAM_ADDR
#define RAM_END (SDRAM_ADDR + SDRAM_SIZE)
static void anna_led_tick (void);
void __init mach_early_init (void)
{
ANNA_ILBEN = 0;
ANNA_CSC(0) = 0x402F;
ANNA_CSC(1) = 0x4000;
ANNA_BPC = 0;
ANNA_BSC = 0xAAAA;
ANNA_BEC = 0;
ANNA_BHC = 0x00FF; /* icache all memory, dcache none */
ANNA_BCT(0) = 0xB088;
ANNA_BCT(1) = 0x0008;
ANNA_DWC(0) = 0x0027;
ANNA_DWC(1) = 0;
ANNA_BCC = 0x0006;
ANNA_ASC = 0;
ANNA_LBS = 0x0089;
ANNA_SCR3 = 0x21A9;
ANNA_RFS3 = 0x8121;
nb85e_intc_disable_irqs ();
}
void __init mach_setup (char **cmdline)
{
printk (KERN_INFO
"CPU: %s\n"
"Platform: %s\n",
CPU_MODEL_LONG,
PLATFORM_LONG);
#ifdef CONFIG_V850E_NB85E_UART_CONSOLE
nb85e_uart_cons_init (1);
#endif
ANNA_PORT_PM (0) = 0; /* Make all LED pins output pins. */
mach_tick = anna_led_tick;
}
void __init mach_get_physical_ram (unsigned long *ram_start,
unsigned long *ram_len)
{
*ram_start = RAM_START;
*ram_len = RAM_END - RAM_START;
}
void __init mach_reserve_bootmem ()
{
/* The space between SRAM and SDRAM is filled with duplicate
images of SRAM. Prevent the kernel from using them. */
reserve_bootmem (SRAM_ADDR + SRAM_SIZE,
SDRAM_ADDR - (SRAM_ADDR + SRAM_SIZE));
}
void mach_gettimeofday (struct timespec *tv)
{
tv->tv_sec = 0;
tv->tv_nsec = 0;
}
void __init mach_sched_init (struct irqaction *timer_action)
{
/* Start hardware timer. */
nb85e_timer_d_configure (0, HZ);
/* Install timer interrupt handler. */
setup_irq (IRQ_INTCMD(0), timer_action);
}
static struct nb85e_intc_irq_init irq_inits[] = {
{ "IRQ", 0, NUM_MACH_IRQS, 1, 7 },
{ "PIN", IRQ_INTP(0), IRQ_INTP_NUM, 1, 4 },
{ "CCC", IRQ_INTCCC(0), IRQ_INTCCC_NUM, 1, 5 },
{ "CMD", IRQ_INTCMD(0), IRQ_INTCMD_NUM, 1, 5 },
{ "DMA", IRQ_INTDMA(0), IRQ_INTDMA_NUM, 1, 2 },
{ "DMXER", IRQ_INTDMXER,1, 1, 2 },
{ "SRE", IRQ_INTSRE(0), IRQ_INTSRE_NUM, 3, 3 },
{ "SR", IRQ_INTSR(0), IRQ_INTSR_NUM, 3, 4 },
{ "ST", IRQ_INTST(0), IRQ_INTST_NUM, 3, 5 },
{ 0 }
};
#define NUM_IRQ_INITS ((sizeof irq_inits / sizeof irq_inits[0]) - 1)
static struct hw_interrupt_type hw_itypes[NUM_IRQ_INITS];
void __init mach_init_irqs (void)
{
nb85e_intc_init_irq_types (irq_inits, hw_itypes);
}
void machine_restart (char *__unused)
{
#ifdef CONFIG_RESET_GUARD
disable_reset_guard ();
#endif
asm ("jmp r0"); /* Jump to the reset vector. */
}
void machine_halt (void)
{
#ifdef CONFIG_RESET_GUARD
disable_reset_guard ();
#endif
local_irq_disable (); /* Ignore all interrupts. */
ANNA_PORT_IO(0) = 0xAA; /* Note that we halted. */
for (;;)
asm ("halt; nop; nop; nop; nop; nop");
}
void machine_power_off (void)
{
machine_halt ();
}
/* Called before configuring an on-chip UART. */
void anna_uart_pre_configure (unsigned chan, unsigned cflags, unsigned baud)
{
/* The Anna connects some general-purpose I/O pins on the CPU to
the RTS/CTS lines of UART 1's serial connection. I/O pins P07
and P37 are RTS and CTS respectively. */
if (chan == 1) {
ANNA_PORT_PM(0) &= ~0x80; /* P07 in output mode */
ANNA_PORT_PM(3) |= 0x80; /* P37 in input mode */
}
}
/* Minimum and maximum bounds for the moving upper LED boundary in the
clock tick display. We can't use the last bit because it's used for
UART0's CTS output. */
#define MIN_MAX_POS 0
#define MAX_MAX_POS 6
/* There are MAX_MAX_POS^2 - MIN_MAX_POS^2 cycles in the animation, so if
we pick 6 and 0 as above, we get 49 cycles, which is when divided into
the standard 100 value for HZ, gives us an almost 1s total time. */
#define TICKS_PER_FRAME \
(HZ / (MAX_MAX_POS * MAX_MAX_POS - MIN_MAX_POS * MIN_MAX_POS))
static void anna_led_tick ()
{
static unsigned counter = 0;
if (++counter == TICKS_PER_FRAME) {
static int pos = 0, max_pos = MAX_MAX_POS, dir = 1;
if (dir > 0 && pos == max_pos) {
dir = -1;
if (max_pos == MIN_MAX_POS)
max_pos = MAX_MAX_POS;
else
max_pos--;
} else {
if (dir < 0 && pos == 0)
dir = 1;
if (pos + dir <= max_pos) {
/* Each bit of port 0 has a LED. */
clear_bit (pos, &ANNA_PORT_IO(0));
pos += dir;
set_bit (pos, &ANNA_PORT_IO(0));
}
}
counter = 0;
}
}
/*
* This program is used to generate definitions needed by
* assembly language modules.
*
* We use the technique used in the OSF Mach kernel code:
* generate asm statements containing #defines,
* compile this file to assembler, and then extract the
* #defines from the assembly-language output.
*/
#include <linux/stddef.h>
#include <linux/sched.h>
#include <linux/kernel_stat.h>
#include <asm/irq.h>
#include <asm/hardirq.h>
#include <asm/errno.h>
#define DEFINE(sym, val) \
asm volatile("\n->" #sym " %0 " #val : : "i" (val))
#define BLANK() asm volatile("\n->" : : )
int main (void)
{
/* offsets into the task struct */
DEFINE (TASK_STATE, offsetof (struct task_struct, state));
DEFINE (TASK_FLAGS, offsetof (struct task_struct, flags));
DEFINE (TASK_PTRACE, offsetof (struct task_struct, ptrace));
DEFINE (TASK_BLOCKED, offsetof (struct task_struct, blocked));
DEFINE (TASK_THREAD, offsetof (struct task_struct, thread));
DEFINE (TASK_THREAD_INFO, offsetof (struct task_struct, thread_info));
DEFINE (TASK_MM, offsetof (struct task_struct, mm));
DEFINE (TASK_ACTIVE_MM, offsetof (struct task_struct, active_mm));
DEFINE (TASK_PID, offsetof (struct task_struct, pid));
/* offsets into the kernel_stat struct */
DEFINE (STAT_IRQ, offsetof (struct kernel_stat, irqs));
/* signal defines */
DEFINE (SIGSEGV, SIGSEGV);
DEFINE (SEGV_MAPERR, SEGV_MAPERR);
DEFINE (SIGTRAP, SIGTRAP);
DEFINE (SIGCHLD, SIGCHLD);
DEFINE (SIGILL, SIGILL);
DEFINE (TRAP_TRACE, TRAP_TRACE);
/* ptrace flag bits */
DEFINE (PT_PTRACED, PT_PTRACED);
DEFINE (PT_DTRACE, PT_DTRACE);
/* error values */
DEFINE (ENOSYS, ENOSYS);
/* clone flag bits */
DEFINE (CLONE_VFORK, CLONE_VFORK);
DEFINE (CLONE_VM, CLONE_VM);
return 0;
}
/*
* arch/v850/kernel/bug.c -- Bug reporting functions
*
* Copyright (C) 2001,02 NEC Corporation
* Copyright (C) 2001,02 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#include <linux/kernel.h>
#include <linux/reboot.h>
#include <linux/sched.h>
#include <asm/errno.h>
#include <asm/ptrace.h>
#include <asm/current.h>
/* We should use __builtin_return_address, but it doesn't work in gcc-2.90
(which is currently our standard compiler on the v850). */
#define ret_addr() ({ register u32 lp asm ("lp"); lp; })
#define stack_addr() ({ register u32 sp asm ("sp"); sp; })
void __bug ()
{
printk (KERN_CRIT "kernel BUG at PC 0x%x (SP ~0x%x)!\n",
ret_addr() - 4, /* - 4 for `jarl' */
stack_addr());
machine_halt ();
}
int bad_trap (int trap_num, struct pt_regs *regs)
{
printk (KERN_CRIT
"unimplemented trap %d called at 0x%08lx, pid %d!\n",
trap_num, regs->pc, current->pid);
return -ENOSYS;
}
int debug_trap (struct pt_regs *regs)
{
printk (KERN_CRIT "debug trap at 0x%08lx!\n", regs->pc);
return -ENOSYS;
}
#ifdef CONFIG_RESET_GUARD
void unexpected_reset (unsigned long ret_addr, unsigned long kmode,
struct task_struct *task, unsigned long sp)
{
printk (KERN_CRIT
"unexpected reset in %s mode, pid %d"
" (ret_addr = 0x%lx, sp = 0x%lx)\n",
kmode ? "kernel" : "user",
task ? task->pid : -1,
ret_addr, sp);
machine_halt ();
}
#endif /* CONFIG_RESET_GUARD */
/*
* arch/v850/kernel/entry.S -- Low-level system-call handling, trap handlers,
* and context-switching
*
* Copyright (C) 2001,02 NEC Corporation
* Copyright (C) 2001,02 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#include <linux/sys.h>
#include <asm/entry.h>
#include <asm/current.h>
#include <asm/thread_info.h>
#include <asm/clinkage.h>
#include <asm/processor.h>
#include <asm/irq.h>
#include <asm/errno.h>
#include <asm/asm-consts.h>
/* Make a slightly more convenient alias for C_SYMBOL_NAME. */
#define CSYM C_SYMBOL_NAME
/* The offset of the struct pt_regs in a `state save frame' on the stack. */
#define PTO STATE_SAVE_PT_OFFSET
/* Save argument registers to the struct pt_regs pointed to by EP. */
#define SAVE_ARG_REGS \
sst.w r6, PTO+PT_GPR(6)[ep]; \
sst.w r7, PTO+PT_GPR(7)[ep]; \
sst.w r8, PTO+PT_GPR(8)[ep]; \
sst.w r9, PTO+PT_GPR(9)[ep];
/* Restore argument registers from the struct pt_regs pointed to by EP. */
#define RESTORE_ARG_REGS \
sld.w PTO+PT_GPR(6)[ep], r6; \
sld.w PTO+PT_GPR(7)[ep], r7; \
sld.w PTO+PT_GPR(8)[ep], r8; \
sld.w PTO+PT_GPR(9)[ep], r9;
/* Save value return registers to the struct pt_regs pointed to by EP. */
#define SAVE_RVAL_REGS \
sst.w r10, PTO+PT_GPR(10)[ep]; \
sst.w r11, PTO+PT_GPR(11)[ep];
/* Restore value return registers from the struct pt_regs pointed to by EP. */
#define RESTORE_RVAL_REGS \
sld.w PTO+PT_GPR(10)[ep], r10; \
sld.w PTO+PT_GPR(11)[ep], r11;
#define SAVE_CALL_CLOBBERED_REGS_BEFORE_ARGS \
sst.w r1, PTO+PT_GPR(1)[ep]; \
sst.w r5, PTO+PT_GPR(5)[ep];
#define SAVE_CALL_CLOBBERED_REGS_AFTER_RVAL \
sst.w r12, PTO+PT_GPR(12)[ep]; \
sst.w r13, PTO+PT_GPR(13)[ep]; \
sst.w r14, PTO+PT_GPR(14)[ep]; \
sst.w r15, PTO+PT_GPR(15)[ep]; \
sst.w r16, PTO+PT_GPR(16)[ep]; \
sst.w r17, PTO+PT_GPR(17)[ep]; \
sst.w r18, PTO+PT_GPR(18)[ep]; \
sst.w r19, PTO+PT_GPR(19)[ep];
#define RESTORE_CALL_CLOBBERED_REGS_BEFORE_ARGS \
sld.w PTO+PT_GPR(1)[ep], r1; \
sld.w PTO+PT_GPR(5)[ep], r5;
#define RESTORE_CALL_CLOBBERED_REGS_AFTER_RVAL \
sld.w PTO+PT_GPR(12)[ep], r12; \
sld.w PTO+PT_GPR(13)[ep], r13; \
sld.w PTO+PT_GPR(14)[ep], r14; \
sld.w PTO+PT_GPR(15)[ep], r15; \
sld.w PTO+PT_GPR(16)[ep], r16; \
sld.w PTO+PT_GPR(17)[ep], r17; \
sld.w PTO+PT_GPR(18)[ep], r18; \
sld.w PTO+PT_GPR(19)[ep], r19;
/* Save `call clobbered' registers to the struct pt_regs pointed to by EP. */
#define SAVE_CALL_CLOBBERED_REGS \
SAVE_CALL_CLOBBERED_REGS_BEFORE_ARGS; \
SAVE_ARG_REGS; \
SAVE_RVAL_REGS; \
SAVE_CALL_CLOBBERED_REGS_AFTER_RVAL;
/* Restore `call clobbered' registers from the struct pt_regs pointed to
by EP. */
#define RESTORE_CALL_CLOBBERED_REGS \
RESTORE_CALL_CLOBBERED_REGS_BEFORE_ARGS; \
RESTORE_ARG_REGS; \
RESTORE_RVAL_REGS; \
RESTORE_CALL_CLOBBERED_REGS_AFTER_RVAL;
/* Save `call clobbered' registers except for the return-value registers
to the struct pt_regs pointed to by EP. */
#define SAVE_CALL_CLOBBERED_REGS_NO_RVAL \
SAVE_CALL_CLOBBERED_REGS_BEFORE_ARGS; \
SAVE_ARG_REGS; \
SAVE_CALL_CLOBBERED_REGS_AFTER_RVAL;
/* Restore `call clobbered' registers except for the return-value registers
from the struct pt_regs pointed to by EP. */
#define RESTORE_CALL_CLOBBERED_REGS_NO_RVAL \
RESTORE_CALL_CLOBBERED_REGS_BEFORE_ARGS; \
RESTORE_ARG_REGS; \
RESTORE_CALL_CLOBBERED_REGS_AFTER_RVAL;
/* Zero `call clobbered' registers except for the return-value registers. */
#define ZERO_CALL_CLOBBERED_REGS_NO_RVAL \
mov r0, r1; mov r0, r5; \
mov r0, r12; mov r0, r13; mov r0, r14; mov r0, r15; \
mov r0, r16; mov r0, r17; mov r0, r18; mov r0, r19;
/* Save `call saved' registers to the struct pt_regs pointed to by EP. */
#define SAVE_CALL_SAVED_REGS \
sst.w r2, PTO+PT_GPR(2)[ep]; \
sst.w r20, PTO+PT_GPR(20)[ep]; \
sst.w r21, PTO+PT_GPR(21)[ep]; \
sst.w r22, PTO+PT_GPR(22)[ep]; \
sst.w r23, PTO+PT_GPR(23)[ep]; \
sst.w r24, PTO+PT_GPR(24)[ep]; \
sst.w r25, PTO+PT_GPR(25)[ep]; \
sst.w r26, PTO+PT_GPR(26)[ep]; \
sst.w r27, PTO+PT_GPR(27)[ep]; \
sst.w r28, PTO+PT_GPR(28)[ep]; \
sst.w r29, PTO+PT_GPR(29)[ep];
/* Restore `call saved' registers from the struct pt_regs pointed to by EP. */
#define RESTORE_CALL_SAVED_REGS \
sld.w PTO+PT_GPR(2)[ep], r2; \
sld.w PTO+PT_GPR(20)[ep], r20; \
sld.w PTO+PT_GPR(21)[ep], r21; \
sld.w PTO+PT_GPR(22)[ep], r22; \
sld.w PTO+PT_GPR(23)[ep], r23; \
sld.w PTO+PT_GPR(24)[ep], r24; \
sld.w PTO+PT_GPR(25)[ep], r25; \
sld.w PTO+PT_GPR(26)[ep], r26; \
sld.w PTO+PT_GPR(27)[ep], r27; \
sld.w PTO+PT_GPR(28)[ep], r28; \
sld.w PTO+PT_GPR(29)[ep], r29;
/* Save system registers to the struct pt_regs pointed to by REG.
r19 is clobbered. */
#define SAVE_SYS_REGS \
stsr SR_EIPC, r19; /* user's PC, before interrupt */ \
sst.w r19, PTO+PT_PC[ep]; \
stsr SR_EIPSW, r19; /* & PSW (XXX save this?) */ \
sst.w r19, PTO+PT_PSW[ep]; \
stsr SR_CTPC, r19; /* (XXX maybe not used in kernel?) */ \
sst.w r19, PTO+PT_CTPC[ep]; \
stsr SR_CTPSW, r19; /* " */ \
sst.w r19, PTO+PT_CTPSW[ep]; \
stsr SR_CTBP, r19; /* " */ \
sst.w r19, PTO+PT_CTBP[ep];
/* Restore system registers from the struct pt_regs pointed to by EP.
LP is clobbered (it is used as a scratch register because the POP_STATE
macro restores it, and this macro is usually used inside POP_STATE). */
#define RESTORE_SYS_REGS \
sld.w PTO+PT_PC[ep], lp; \
ldsr lp, SR_EIPC; /* user's PC, before interrupt */ \
sld.w PTO+PT_PSW[ep], lp; \
ldsr lp, SR_EIPSW; /* & PSW (XXX save this?) */ \
sld.w PTO+PT_CTPC[ep], lp; \
ldsr lp, SR_CTPC; /* (XXX maybe not used in kernel?) */ \
sld.w PTO+PT_CTPSW[ep], lp; \
ldsr lp, SR_CTPSW; /* " */ \
sld.w PTO+PT_CTBP[ep], lp; \
ldsr lp, SR_CTBP; /* " */
/* Save system registers to the struct pt_regs pointed to by REG. This is a
NMI-specific version, because NMIs save the PC/PSW in a different place
than other interrupt requests. r19 is clobbered. */
#define SAVE_SYS_REGS_FOR_NMI \
stsr SR_FEPC, r19; /* user's PC, before NMI */ \
sst.w r19, PTO+PT_PC[ep]; \
stsr SR_FEPSW, r19; /* & PSW (XXX save this?) */ \
sst.w r19, PTO+PT_PSW[ep]; \
stsr SR_CTPC, r19; /* (XXX maybe not used in kernel?) */ \
sst.w r19, PTO+PT_CTPC[ep]; \
stsr SR_CTPSW, r19; /* " */ \
sst.w r19, PTO+PT_CTPSW[ep]; \
stsr SR_CTBP, r19; /* " */ \
sst.w r19, PTO+PT_CTBP[ep];
/* Restore system registers from the struct pt_regs pointed to by EP. This is
a NMI-specific version, because NMIs save the PC/PSW in a different place
than other interrupt requests. LP is clobbered (it is used as a scratch
register because the POP_STATE macro restores it, and this macro is usually
used inside POP_STATE). */
#define RESTORE_SYS_REGS_FOR_NMI \
ldsr lp, SR_FEPC; /* user's PC, before NMI */ \
sld.w PTO+PT_PC[ep], lp; \
ldsr lp, SR_FEPSW; /* & PSW (XXX save this?) */ \
sld.w PTO+PT_PSW[ep], lp; \
ldsr lp, SR_CTPC; /* (XXX maybe not used in kernel?) */ \
sld.w PTO+PT_CTPC[ep], lp; \
ldsr lp, SR_CTPSW; /* " */ \
sld.w PTO+PT_CTPSW[ep], lp; \
ldsr lp, SR_CTBP; /* " */ \
sld.w PTO+PT_CTBP[ep], lp;
/* Push register state, except for the stack pointer, on the stack in the form
of a struct pt_regs, in preparation for a system call. This macro makes
sure that `special' registers, system registers; TYPE identifies the set of
extra registers to be saved as well. EP is clobbered. */
#define PUSH_STATE(type) \
addi -STATE_SAVE_SIZE, sp, sp; /* Make room on the stack. */ \
st.w ep, PTO+PT_GPR(GPR_EP)[sp]; \
mov sp, ep; \
sst.w gp, PTO+PT_GPR(GPR_GP)[ep]; \
sst.w lp, PTO+PT_GPR(GPR_LP)[ep]; \
type ## _STATE_SAVER;
/* Pop a register state, except for the stack pointer, from the struct pt_regs
on the stack. */
#define POP_STATE(type) \
mov sp, ep; \
type ## _STATE_RESTORER; \
sld.w PTO+PT_GPR(GPR_GP)[ep], gp; \
sld.w PTO+PT_GPR(GPR_LP)[ep], lp; \
sld.w PTO+PT_GPR(GPR_EP)[ep], ep; \
addi STATE_SAVE_SIZE, sp, sp; /* Clean up our stack space. */
/* Switch to the kernel stack if necessary, and push register state on
the stack in the form of a struct pt_regs. Also load the current
task pointer if switching from user mode. The stack-pointer (r3)
should have already been saved to the memory location SP_SAVE_LOC
(the reason for this is that the interrupt vectors may be beyond a
22-bit signed offset jump from the actual interrupt handler, and this
allows them to save the stack-pointer and use that register to do an
indirect jump). This macro makes sure that `special' registers,
system registers, and the stack pointer are saved; TYPE identifies
the set of extra registers to be saved as well. SYSCALL_NUM is the
register in which the system-call number this state is for is stored
(r0 if this isn't a system call). Interrupts should already be
disabled when calling this. */
#define SAVE_STATE(type, syscall_num, sp_save_loc) \
tst1 0, KM; /* See if already in kernel mode. */ \
bz 1f; \
/* Kernel-mode state save. */ \
ld.w sp_save_loc, sp; /* Reload kernel stack-pointer. */ \
st.w sp, (PT_GPR(GPR_SP)-PT_SIZE)[sp]; /* Save original SP. */ \
PUSH_STATE(type); \
mov 1, r19; /* Was in kernel-mode. */ \
sst.w r19, PTO+PT_KERNEL_MODE[ep]; /* [ep is set by PUSH_STATE] */ \
br 2f; \
1: /* User-mode state save. */ \
ld.w KSP, sp; /* Switch to kernel stack. */ \
PUSH_STATE(type); \
sst.w r0, PTO+PT_KERNEL_MODE[ep]; /* Was in user-mode. */ \
ld.w sp_save_loc, r19; \
sst.w r19, PTO+PT_GPR(GPR_SP)[ep]; /* Store user SP. */ \
mov 1, r19; \
st.b r19, KM; /* Now we're in kernel-mode. */ \
GET_CURRENT_TASK(CURRENT_TASK); /* Fetch the current task pointer. */ \
2: /* Save away the syscall number. */ \
sst.w syscall_num, PTO+PT_SYSCALL[ep]
/* Save register state not normally saved by PUSH_STATE for TYPE. */
#define SAVE_EXTRA_STATE(type) \
mov sp, ep; \
type ## _EXTRA_STATE_SAVER;
/* Restore register state not normally restored by POP_STATE for TYPE. */
#define RESTORE_EXTRA_STATE(type) \
mov sp, ep; \
type ## _EXTRA_STATE_RESTORER;
/* Save any call-clobbered registers not normally saved by PUSH_STATE
for TYPE. */
#define SAVE_EXTRA_STATE_FOR_FUNCALL(type) \
mov sp, ep; \
type ## _FUNCALL_EXTRA_STATE_SAVER;
/* Restore any call-clobbered registers not normally restored by POP_STATE for
TYPE. */
#define RESTORE_EXTRA_STATE_FOR_FUNCALL(type) \
mov sp, ep; \
type ## _FUNCALL_EXTRA_STATE_RESTORER;
/* These are extra_state_saver/restorer values for a user trap. Note that we
save the argument registers so that restarted syscalls will function
properly (otherwise it wouldn't be necessary), and we must _not_ restore
the return-value registers (so that traps can return a value!), but there
are various options for what happens to other call-clobbered registers,
selected by preprocessor conditionals. */
#if TRAPS_PRESERVE_CALL_CLOBBERED_REGS
/* Traps save/restore all call-clobbered registers (except for rval regs). */
#define TRAP_STATE_SAVER \
SAVE_CALL_CLOBBERED_REGS_NO_RVAL; \
SAVE_SYS_REGS
#define TRAP_STATE_RESTORER \
RESTORE_CALL_CLOBBERED_REGS_NO_RVAL; \
RESTORE_SYS_REGS
#else /* !TRAPS_PRESERVE_CALL_CLOBBERED_REGS */
/* Traps don't save call-clobbered registers (but do still save arg regs). */
#define TRAP_STATE_SAVER \
SAVE_ARG_REGS; \
SAVE_SYS_REGS
#if TRAPS_ZERO_CALL_CLOBBERED_REGS
/* Traps zero call-clobbered registers (except for arg/rval regs) before
returning from a system call, to avoid any internal values from leaking out
of the kernel. */
#define TRAP_STATE_RESTORER \
ZERO_CALL_CLOBBERED_REGS_NO_ARGS_NO_RVAL; \
RESTORE_ARG_REGS; \
RESTORE_SYS_REGS
#else /* !TRAPS_ZERO_CALL_CLOBBERED_REGS */
/* When traps return, they just leave call-clobbered registers (except for arg
regs) with whatever value they have from the kernel. */
#define TRAP_STATE_RESTORER \
RESTORE_ARG_REGS; \
RESTORE_SYS_REGS
#endif /* TRAPS_ZERO_CALL_CLOBBERED_REGS */
#endif /* TRAPS_PRESERVE_CALL_CLOBBERED_REGS */
/* Save registers not normally saved by traps. */
#define TRAP_EXTRA_STATE_SAVER \
SAVE_RVAL_REGS; \
SAVE_CALL_SAVED_REGS
#define TRAP_EXTRA_STATE_RESTORER \
RESTORE_RVAL_REGS; \
RESTORE_CALL_SAVED_REGS
#define TRAP_FUNCALL_EXTRA_STATE_SAVER \
SAVE_RVAL_REGS
#define TRAP_FUNCALL_EXTRA_STATE_RESTORER \
RESTORE_RVAL_REGS
/* Register saving/restoring for maskable interrupts. */
#define IRQ_STATE_SAVER \
SAVE_CALL_CLOBBERED_REGS; \
SAVE_SYS_REGS
#define IRQ_STATE_RESTORER \
RESTORE_CALL_CLOBBERED_REGS; \
RESTORE_SYS_REGS
#define IRQ_EXTRA_STATE_SAVER \
SAVE_CALL_SAVED_REGS
#define IRQ_EXTRA_STATE_RESTORER \
RESTORE_CALL_SAVED_REGS
#define IRQ_FUNCALL_EXTRA_STATE_SAVER /* nothing */
#define IRQ_FUNCALL_EXTRA_STATE_RESTORER /* nothing */
/* Register saving/restoring for non-maskable interrupts. */
#define NMI_STATE_SAVER \
SAVE_CALL_CLOBBERED_REGS; \
SAVE_SYS_REGS_FOR_NMI
#define NMI_STATE_RESTORER \
RESTORE_CALL_CLOBBERED_REGS; \
RESTORE_SYS_REGS_FOR_NMI
#define NMI_EXTRA_STATE_SAVER \
SAVE_CALL_SAVED_REGS
#define NMI_EXTRA_STATE_RESTORER \
RESTORE_CALL_SAVED_REGS
#define NMI_FUNCALL_EXTRA_STATE_SAVER /* nothing */
#define NMI_FUNCALL_EXTRA_STATE_RESTORER /* nothing */
/* Register saving/restoring for a context switch. We don't need to save too
many registers, because context-switching looks like a function call (via
the function `switch_thread'), so callers will save any call-clobbered
registers themselves. The stack pointer and return value are handled by
switch_thread itself. */
#define SWITCH_STATE_SAVER \
SAVE_CALL_SAVED_REGS
#define SWITCH_STATE_RESTORER \
RESTORE_CALL_SAVED_REGS
/* Restore register state from the struct pt_regs on the stack, switch back
to the user stack if necessary, and return from the trap/interrupt.
EXTRA_STATE_RESTORER is a sequence of assembly language statements to
restore anything not restored by this macro. Only registers not saved by
the C compiler are restored (that is, R3(sp), R4(gp), R31(lp), and
anything restored by EXTRA_STATE_RESTORER). */
#define RETURN(type) \
ld.b PTO+PT_KERNEL_MODE[sp], r19; \
di; /* Disable interrupts */ \
cmp r19, r0; /* See if returning to kernel mode, */\
bne 2f; /* ... if so, skip resched &c. */ \
\
/* We're returning to user mode, so check for various conditions that \
trigger rescheduling. */ \
GET_CURRENT_THREAD(r18); \
ld.w TI_FLAGS[r18], r19; \
andi _TIF_NEED_RESCHED, r19, r0; \
bnz 3f; /* Call the scheduler. */ \
andi _TIF_SIGPENDING, r19, r0; \
bnz 4f; /* Signals to handle, handle them */ \
\
/* Finally, return to user state. */ \
1: st.b r0, KM; /* Now officially in user state. */ \
POP_STATE(type); \
st.w sp, KSP; /* Save the kernel stack pointer. */ \
ld.w PT_GPR(GPR_SP)-PT_SIZE[sp], sp; \
/* Restore user stack pointer. */ \
reti; \
\
/* Return to kernel state. */ \
2: POP_STATE(type); \
reti; \
\
/* Call the scheduler before returning from a syscall/trap. */ \
3: SAVE_EXTRA_STATE_FOR_FUNCALL(type); /* Prepare for funcall. */ \
jarl CSYM(schedule), lp; /* Call scheduler */ \
di; /* The scheduler enables interrupts */\
RESTORE_EXTRA_STATE_FOR_FUNCALL(type); \
br 1b; \
\
/* Handle a signal return. */ \
4: /* Not all registers are saved by the normal trap/interrupt entry \
points (for instance, call-saved registers (because the normal \
C-compiler calling sequence in the kernel makes sure they're \
preserved), and call-clobbered registers in the case of \
traps), but signal handlers may want to examine or change the \
complete register state. Here we save anything not saved by \
the normal entry sequence, so that it may be safely restored \
(in a possibly modified form) after do_signal returns. */ \
SAVE_EXTRA_STATE(type) /* Save state not saved by entry. */ \
movea PTO, sp, r6; /* Arg 1: struct pt_regs *regs */ \
mov r0, r7; /* Arg 2: sigset_t *oldset */ \
jarl CSYM(do_signal), lp; /* Handle any signals */ \
di; /* sig handling enables interrupts */ \
RESTORE_EXTRA_STATE(type); /* Restore extra regs. */ \
br 1b;
/* Jump to the appropriate function for the system call number in r12
(r12 is not preserved), or return an error if r12 is not valid. The
LP register should point to the location where the called function
should return. [note that MAKE_SYS_CALL uses label 1] */
#define MAKE_SYS_CALL \
/* See if the system call number is valid. */ \
addi -NR_syscalls, r12, r0; \
bnh 1f; \
/* Figure out which function to use for this system call. */ \
shl 2, r12; \
mov hilo(CSYM(sys_call_table)), r19; \
add r19, r12; \
ld.w 0[r12], r12; \
/* Make the system call. */ \
jmp [r12]; \
/* The syscall number is invalid, return an error. */ \
1: addi -ENOSYS, r0, r10; \
jmp [lp];
.text
/*
* User trap.
*
* Trap 0 system calls are also handled here.
*
* The stack-pointer (r3) should have already been saved to the memory
* location ENTRY_SP (the reason for this is that the interrupt vectors may be
* beyond a 22-bit signed offset jump from the actual interrupt handler, and
* this allows them to save the stack-pointer and use that register to do an
* indirect jump).
*
* Syscall protocol:
* Syscall number in r12, args in r6-r9
* Return value in r10
*/
G_ENTRY(trap):
SAVE_STATE (TRAP, r12, ENTRY_SP) // Save registers.
stsr SR_ECR, r19 // Find out which trap it was.
ei // Enable interrupts.
mov hilo(ret_from_trap), lp // where the trap should return
// The following two shifts (1) clear out extraneous NMI data in the
// upper 16-bits, (2) convert the 0x40 - 0x5f range of trap ECR
// numbers into the (0-31) << 2 range we want, (3) set the flags.
shl 27, r19 // chop off all high bits
shr 25, r19 // scale back down and then << 2
bnz 2f // See if not trap 0.
// Trap 0 is a `short' system call, skip general trap table.
MAKE_SYS_CALL // Jump to the syscall function.
2: // For other traps, use a table lookup.
mov hilo(CSYM(trap_table)), r18
add r19, r18
ld.w 0[r18], r18
jmp [r18] // Jump to the trap handler.
END(trap)
/* This is just like ret_from_trap, but first restores extra registers
saved by some wrappers. */
L_ENTRY(restore_extra_regs_and_ret_from_trap):
RESTORE_EXTRA_STATE(TRAP)
// fall through
END(restore_extra_regs_and_ret_from_trap)
/* Entry point used to return from a syscall/trap. */
L_ENTRY(ret_from_trap):
RETURN(TRAP)
END(ret_from_trap)
/* This the initial entry point for a new child thread, with an appropriate
stack in place that makes it look the the child is in the middle of an
syscall. This function is actually `returned to' from switch_thread
(copy_thread makes ret_from_fork the return address in each new thread's
saved context). */
C_ENTRY(ret_from_fork):
#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT)
mov r10, r6 // switch_thread returns the prev task.
jarl CSYM(schedule_tail), lp // ...which is schedule_tail's arg
#endif
mov r0, r10 // Child's fork call should return 0.
br ret_from_trap // Do normal trap return.
C_END(ret_from_fork)
/*
* Trap 1: `long' system calls
* `Long' syscall protocol:
* Syscall number in r12, args in r6-r9, r13-r14
* Return value in r10
*/
L_ENTRY(syscall_long):
// Push extra arguments on the stack. Note that by default, the trap
// handler reserves enough stack space for 6 arguments, so we don't
// have to make any additional room.
st.w r13, 16[sp] // arg 5
st.w r14, 20[sp] // arg 6
#if !TRAPS_PRESERVE_CALL_CLOBBERED_REGS
// Make sure r13 and r14 are preserved, in case we have to restart a
// system call because of a signal (ep has already been set by caller).
st.w r13, PTO+PT_GPR(13)[sp]
st.w r14, PTO+PT_GPR(13)[sp]
mov hilo(ret_from_long_syscall), lp
#endif /* !TRAPS_PRESERVE_CALL_CLOBBERED_REGS */
MAKE_SYS_CALL // Jump to the syscall function.
END(syscall_long)
#if !TRAPS_PRESERVE_CALL_CLOBBERED_REGS
/* Entry point used to return from a long syscall. Only needed to restore
r13/r14 if the general trap mechanism doesnt' do so. */
L_ENTRY(ret_from_long_syscall):
ld.w PTO+PT_GPR(13)[sp], r13 // Restore the extra registers
ld.w PTO+PT_GPR(13)[sp], r14
br ret_from_trap // The rest is the same as other traps
END(ret_from_long_syscall)
#endif /* !TRAPS_PRESERVE_CALL_CLOBBERED_REGS */
/* These syscalls need access to the struct pt_regs on the stack, so we
implement them in assembly (they're basically all wrappers anyway). */
L_ENTRY(sys_fork_wrapper):
#ifdef CONFIG_MMU
// Save state not saved by entry. This is actually slight overkill;
// it's actually only necessary to save any state restored by
// switch_thread that's not saved by the trap entry.
SAVE_EXTRA_STATE(TRAP) // Save state not saved by entry.
addi SIGCHLD, r0, r6 // Arg 0: flags
ld.w PTO+PT_GPR(GPR_SP)[sp], r7 // Arg 1: child SP (use parent's)
movea PTO, sp, r8 // Arg 2: parent context
jr CSYM(fork_common) // Do real work (tail-call).
#else
// fork almost works, enough to trick you into looking elsewhere :-(
addi -EINVAL, r0, r10
jmp [lp]
#endif
END(sys_fork_wrapper)
L_ENTRY(sys_vfork_wrapper):
// Save state not saved by entry. This is actually slight overkill;
// it's actually only necessary to save any state restored by
// switch_thread that's not saved by the trap entry.
SAVE_EXTRA_STATE(TRAP) // Save state not saved by entry.
addi CLONE_VFORK | CLONE_VM | SIGCHLD, r0, r6 // Arg 0: flags
ld.w PTO+PT_GPR(GPR_SP)[sp], r7 // Arg 1: child SP (use parent's)
movea PTO, sp, r8 // Arg 2: parent context
jr CSYM(fork_common) // Do real work (tail-call).
END(sys_vfork_wrapper)
L_ENTRY(sys_clone_wrapper):
// Save state not saved by entry. This is actually slight overkill;
// it's actually only necessary to save any state restored by
// switch_thread that's not saved by the trap entry.
SAVE_EXTRA_STATE(TRAP) // Save state not saved by entry.
ld.w PTO+PT_GPR(GPR_SP)[sp], r19 // parent's stack pointer
cmp r7, r0 // See if child SP arg (arg 1) is 0.
cmov z, r19, r7, r7 // ... and use the parent's if so.
movea PTO, sp, r8 // Arg 2: parent context
jr CSYM(fork_common) // Do real work (tail-call).
END(sys_clone_wrapper)
L_ENTRY(sys_execve_wrapper):
movea PTO, sp, r9 // add user context as 4th arg
jr CSYM(sys_execve) // Do real work (tail-call).
END(sys_execve_wrapper)
L_ENTRY(sys_sigsuspend_wrapper):
SAVE_EXTRA_STATE(TRAP) // Save state not saved by entry.
movea PTO, sp, r7 // add user context as 2nd arg
jarl CSYM(sys_sigsuspend), lp// Do real work.
br restore_extra_regs_and_ret_from_trap
END(sys_sigsuspend_wrapper)
L_ENTRY(sys_rt_sigsuspend_wrapper):
SAVE_EXTRA_STATE(TRAP) // Save state not saved by entry.
movea PTO, sp, r8 // add user context as 3rd arg
jarl CSYM(sys_rt_sigsuspend), lp // Do real work.
br restore_extra_regs_and_ret_from_trap
END(sys_rt_sigsuspend_wrapper)
L_ENTRY(sys_sigreturn_wrapper):
SAVE_EXTRA_STATE(TRAP) // Save state not saved by entry.
movea PTO, sp, r6 // add user context as 1st arg
jarl CSYM(sys_sigreturn), lp // Do real work.
br restore_extra_regs_and_ret_from_trap
END(sys_sigreturn_wrapper)
L_ENTRY(sys_rt_sigreturn_wrapper):
SAVE_EXTRA_STATE(TRAP) // Save state not saved by entry.
movea PTO, sp, r6 // add user context as 1st arg
jarl CSYM(sys_rt_sigreturn), lp // Do real work.
br restore_extra_regs_and_ret_from_trap
END(sys_rt_sigreturn_wrapper)
/*
* Hardware maskable interrupts.
*
* The stack-pointer (r3) should have already been saved to the memory
* location ENTRY_SP (the reason for this is that the interrupt vectors may be
* beyond a 22-bit signed offset jump from the actual interrupt handler, and
* this allows them to save the stack-pointer and use that register to do an
* indirect jump).
*/
G_ENTRY(irq):
SAVE_STATE (IRQ, r0, ENTRY_SP) // Save registers.
stsr SR_ECR, r6 // Find out which interrupt it was.
movea PTO, sp, r7 // User regs are arg2
// All v850 implementations I know about encode their interrupts as
// multiples of 0x10, starting at 0x80 (after NMIs and software
// interrupts). Convert this number into a simple IRQ index for the
// rest of the kernel. We also clear the upper 16 bits, which hold
// NMI info, and don't appear to be cleared when a NMI returns.
shl 16, r6 // clear upper 16 bits
shr 20, r6 // shift back, and remove lower nibble
add -8, r6 // remove bias for irqs
// Call the high-level interrupt handling code.
jarl CSYM(handle_irq), lp
// fall through
/* Entry point used to return from an interrupt (also used by exception
handlers, below). */
ret_from_irq:
RETURN(IRQ)
END(irq)
/*
* Hardware non-maskable interrupts.
*
* The stack-pointer (r3) should have already been saved to the memory
* location ENTRY_SP (the reason for this is that the interrupt vectors may be
* beyond a 22-bit signed offset jump from the actual interrupt handler, and
* this allows them to save the stack-pointer and use that register to do an
* indirect jump).
*/
G_ENTRY(nmi):
SAVE_STATE (NMI, r0, NMI_ENTRY_SP); /* Save registers. */
stsr SR_ECR, r6; /* Find out which nmi it was. */
shr 20, r6; /* Extract NMI code in bits 20-24. */
movea PTO, sp, r7; /* User regs are arg2. */
/* Non-maskable interrupts always lie right after maskable interrupts.
Call the generic IRQ handler, with two arguments, the IRQ number,
and a pointer to the user registers, to handle the specifics.
(we subtract one because the first NMI has code 1). */
addi FIRST_NMI - 1, r6, r6;
jarl CSYM(handle_irq), lp
RETURN(NMI)
END(nmi0)
/*
* Illegal instruction trap.
*
* The stack-pointer (r3) should have already been saved to the memory
* location ENTRY_SP (the reason for this is that the interrupt vectors may be
* beyond a 22-bit signed offset jump from the actual interrupt handler, and
* this allows them to save the stack-pointer and use that register to do an
* indirect jump).
*/
G_ENTRY(illegal_instruction):
SAVE_STATE (IRQ, r0, ENTRY_SP) // Save registers.
ei
addi SIGILL, r0, r6 // Arg 0: signal number
mov CURRENT_TASK, r7 // Arg 1: task
mov hilo(ret_from_irq), lp // where the handler should return
jr CSYM(force_sig)
END(illegal_instruction)
/*
* `Debug' trap
*
* The stack-pointer (r3) should have already been saved to the memory
* location ENTRY_SP (the reason for this is that the interrupt vectors may be
* beyond a 22-bit signed offset jump from the actual interrupt handler, and
* this allows them to save the stack-pointer and use that register to do an
* indirect jump).
*/
G_ENTRY(dbtrap):
SAVE_STATE (IRQ, r0, ENTRY_SP) // Save registers.
ei
movea PTO, sp, r6 // Arg 0: user regs
mov hilo(ret_from_irq), lp // where the handler should return
jr CSYM(debug_trap)
END(dbtrap)
/*
* Trap with no handler
*/
L_ENTRY(bad_trap_wrapper):
mov r19, r6 // Arg 0: trap number
movea PTO, sp, r7 // Arg 1: user regs
jr CSYM(bad_trap) // tail call handler
END(bad_trap_wrapper)
/*
* This is where we switch between two threads. The arguments are:
* r6 -- pointer to the struct thread for the `current' process
* r7 -- pointer to the struct thread for the `new' process.
* when this function returns, it will return to the new thread.
*/
C_ENTRY(switch_thread):
// Return the previous task (r10 is not clobbered by restore below)
mov CURRENT_TASK, r10
// First, push the current processor state on the stack
PUSH_STATE(SWITCH)
// Now save the location of the kernel stack pointer for this thread;
// since we've pushed all other state on the stack, this is enough to
// restore it all later.
st.w sp, THREAD_KSP[r6]
// Now restore the stack pointer from the new process
ld.w THREAD_KSP[r7], sp
// ... and restore all state from that
POP_STATE(SWITCH)
// Update the current task pointer
GET_CURRENT_TASK(CURRENT_TASK)
// Now return into the new thread
jmp [lp]
C_END(switch_thread)
.data
.align 4
.globl CSYM(trap_table)
CSYM(trap_table):
.long bad_trap_wrapper // trap 0, doesn't use trap table.
.long syscall_long // trap 1, `long' syscall.
.long bad_trap_wrapper
.long bad_trap_wrapper
.long bad_trap_wrapper
.long bad_trap_wrapper
.long bad_trap_wrapper
.long bad_trap_wrapper
.long bad_trap_wrapper
.long bad_trap_wrapper
.long bad_trap_wrapper
.long bad_trap_wrapper
.long bad_trap_wrapper
.long bad_trap_wrapper
.long bad_trap_wrapper
.long bad_trap_wrapper
.section .rodata
.align 4
.globl CSYM(sys_call_table)
CSYM(sys_call_table):
.long CSYM(sys_ni_syscall) // 0 - old "setup()" system call
.long CSYM(sys_exit)
.long sys_fork_wrapper
.long CSYM(sys_read)
.long CSYM(sys_write)
.long CSYM(sys_open) // 5
.long CSYM(sys_close)
.long CSYM(sys_waitpid)
.long CSYM(sys_creat)
.long CSYM(sys_link)
.long CSYM(sys_unlink) // 10
.long sys_execve_wrapper
.long CSYM(sys_chdir)
.long CSYM(sys_time)
.long CSYM(sys_mknod)
.long CSYM(sys_chmod) // 15
.long CSYM(sys_chown)
.long CSYM(sys_ni_syscall) // was: break
.long CSYM(sys_ni_syscall) // was: oldstat (aka stat)
.long CSYM(sys_lseek)
.long CSYM(sys_getpid) // 20
.long CSYM(sys_mount)
.long CSYM(sys_oldumount)
.long CSYM(sys_setuid)
.long CSYM(sys_getuid)
.long CSYM(sys_stime) // 25
.long CSYM(sys_ptrace)
.long CSYM(sys_alarm)
.long CSYM(sys_ni_syscall) // was: oldfstat (aka fstat)
.long CSYM(sys_pause)
.long CSYM(sys_utime) // 30
.long CSYM(sys_ni_syscall) // was: stty
.long CSYM(sys_ni_syscall) // was: gtty
.long CSYM(sys_access)
.long CSYM(sys_nice)
.long CSYM(sys_ni_syscall) // 35, was: ftime
.long CSYM(sys_sync)
.long CSYM(sys_kill)
.long CSYM(sys_rename)
.long CSYM(sys_mkdir)
.long CSYM(sys_rmdir) // 40
.long CSYM(sys_dup)
.long CSYM(sys_pipe)
.long CSYM(sys_times)
.long CSYM(sys_ni_syscall) // was: prof
.long CSYM(sys_brk) // 45
.long CSYM(sys_setgid)
.long CSYM(sys_getgid)
.long CSYM(sys_signal)
.long CSYM(sys_geteuid)
.long CSYM(sys_getegid) // 50
.long CSYM(sys_acct)
.long CSYM(sys_umount) // recycled never used phys()
.long CSYM(sys_ni_syscall) // was: lock
.long CSYM(sys_ioctl)
.long CSYM(sys_fcntl) // 55
.long CSYM(sys_ni_syscall) // was: mpx
.long CSYM(sys_setpgid)
.long CSYM(sys_ni_syscall) // was: ulimit
.long CSYM(sys_ni_syscall)
.long CSYM(sys_umask) // 60
.long CSYM(sys_chroot)
.long CSYM(sys_ustat)
.long CSYM(sys_dup2)
.long CSYM(sys_getppid)
.long CSYM(sys_getpgrp) // 65
.long CSYM(sys_setsid)
.long CSYM(sys_sigaction)
.long CSYM(sys_sgetmask)
.long CSYM(sys_ssetmask)
.long CSYM(sys_setreuid) // 70
.long CSYM(sys_setregid)
.long sys_sigsuspend_wrapper
.long CSYM(sys_sigpending)
.long CSYM(sys_sethostname)
.long CSYM(sys_setrlimit) // 75
.long CSYM(sys_getrlimit)
.long CSYM(sys_getrusage)
.long CSYM(sys_gettimeofday)
.long CSYM(sys_settimeofday)
.long CSYM(sys_getgroups) // 80
.long CSYM(sys_setgroups)
.long CSYM(sys_select)
.long CSYM(sys_symlink)
.long CSYM(sys_ni_syscall) // was: oldlstat (aka lstat)
.long CSYM(sys_readlink) // 85
.long CSYM(sys_uselib)
.long CSYM(sys_swapon)
.long CSYM(sys_reboot)
.long CSYM(old_readdir)
.long CSYM(sys_mmap) // 90
.long CSYM(sys_munmap)
.long CSYM(sys_truncate)
.long CSYM(sys_ftruncate)
.long CSYM(sys_fchmod)
.long CSYM(sys_fchown) // 95
.long CSYM(sys_getpriority)
.long CSYM(sys_setpriority)
.long CSYM(sys_ni_syscall) // was: profil
.long CSYM(sys_statfs)
.long CSYM(sys_fstatfs) // 100
.long CSYM(sys_ni_syscall) // i386: ioperm
.long CSYM(sys_socketcall)
.long CSYM(sys_syslog)
.long CSYM(sys_setitimer)
.long CSYM(sys_getitimer) // 105
.long CSYM(sys_newstat)
.long CSYM(sys_newlstat)
.long CSYM(sys_newfstat)
.long CSYM(sys_ni_syscall) // was: olduname (aka uname)
.long CSYM(sys_ni_syscall) // 110, i386: iopl
.long CSYM(sys_vhangup)
.long CSYM(sys_ni_syscall) // was: idle
.long CSYM(sys_ni_syscall) // i386: vm86old
.long CSYM(sys_wait4)
.long CSYM(sys_swapoff) // 115
.long CSYM(sys_sysinfo)
.long CSYM(sys_ipc)
.long CSYM(sys_fsync)
.long sys_sigreturn_wrapper
.long sys_clone_wrapper // 120
.long CSYM(sys_setdomainname)
.long CSYM(sys_newuname)
.long CSYM(sys_ni_syscall) // i386: modify_ldt, m68k: cacheflush
.long CSYM(sys_adjtimex)
.long CSYM(sys_ni_syscall) // 125 - sys_mprotect
.long CSYM(sys_sigprocmask)
.long CSYM(sys_create_module)
.long CSYM(sys_init_module)
.long CSYM(sys_delete_module)
.long CSYM(sys_get_kernel_syms) // 130
.long CSYM(sys_quotactl)
.long CSYM(sys_getpgid)
.long CSYM(sys_fchdir)
.long CSYM(sys_bdflush)
.long CSYM(sys_sysfs) // 135
.long CSYM(sys_personality)
.long CSYM(sys_ni_syscall) // for afs_syscall
.long CSYM(sys_setfsuid)
.long CSYM(sys_setfsgid)
.long CSYM(sys_llseek) // 140
.long CSYM(sys_getdents)
.long CSYM(sys_select) // for backward compat; remove someday
.long CSYM(sys_flock)
.long CSYM(sys_ni_syscall) // sys_msync
.long CSYM(sys_readv) // 145
.long CSYM(sys_writev)
.long CSYM(sys_getsid)
.long CSYM(sys_fdatasync)
.long CSYM(sys_sysctl)
.long CSYM(sys_ni_syscall) // 150 - sys_mlock
.long CSYM(sys_ni_syscall) // sys_munlock
.long CSYM(sys_ni_syscall) // sys_mlockall
.long CSYM(sys_ni_syscall) // sys_munlockall
.long CSYM(sys_sched_setparam)
.long CSYM(sys_sched_getparam) // 155
.long CSYM(sys_sched_setscheduler)
.long CSYM(sys_sched_getscheduler)
.long CSYM(sys_sched_yield)
.long CSYM(sys_sched_get_priority_max)
.long CSYM(sys_sched_get_priority_min) // 160
.long CSYM(sys_sched_rr_get_interval)
.long CSYM(sys_nanosleep)
.long CSYM(sys_ni_syscall) // sys_mremap
.long CSYM(sys_setresuid)
.long CSYM(sys_getresuid) // 165
.long CSYM(sys_ni_syscall) // for vm86
.long CSYM(sys_query_module)
.long CSYM(sys_poll)
.long CSYM(sys_nfsservctl)
.long CSYM(sys_setresgid) // 170
.long CSYM(sys_getresgid)
.long CSYM(sys_prctl)
.long sys_rt_sigreturn_wrapper
.long CSYM(sys_rt_sigaction)
.long CSYM(sys_rt_sigprocmask) // 175
.long CSYM(sys_rt_sigpending)
.long CSYM(sys_rt_sigtimedwait)
.long CSYM(sys_rt_sigqueueinfo)
.long sys_rt_sigsuspend_wrapper
.long CSYM(sys_pread64) // 180
.long CSYM(sys_pwrite64)
.long CSYM(sys_lchown)
.long CSYM(sys_getcwd)
.long CSYM(sys_capget)
.long CSYM(sys_capset) // 185
.long CSYM(sys_sigaltstack)
.long CSYM(sys_sendfile)
.long CSYM(sys_ni_syscall) // streams1
.long CSYM(sys_ni_syscall) // streams2
.long sys_vfork_wrapper // 190
.long CSYM(sys_ni_syscall)
.long CSYM(sys_mmap2)
.long CSYM(sys_truncate64)
.long CSYM(sys_ftruncate64)
.long CSYM(sys_stat64) // 195
.long CSYM(sys_lstat64)
.long CSYM(sys_fstat64)
.long CSYM(sys_fcntl64)
.long CSYM(sys_getdents64)
.long CSYM(sys_pivot_root) // 200
.long CSYM(sys_gettid)
.long CSYM(sys_tkill)
.long CSYM(sys_ni_syscall) // sys_mincore
.long CSYM(sys_ni_syscall) // sys_madvise
.space (NR_syscalls-205)*4
/*
* arch/v850/kernel/fpga85e2c.h -- Machine-dependent defs for
* FPGA implementation of V850E2/NA85E2C
*
* Copyright (C) 2002 NEC Corporation
* Copyright (C) 2002 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/swap.h>
#include <linux/bootmem.h>
#include <linux/irq.h>
#include <asm/atomic.h>
#include <asm/page.h>
#include <asm/machdep.h>
#include <asm/bitops.h>
#include "mach.h"
extern void memcons_setup (void);
#define REG_DUMP_ADDR 0x220000
extern struct irqaction reg_snap_action; /* fwd decl */
void __init mach_early_init (void)
{
int i;
const u32 *src;
register u32 *dst asm ("ep");
extern int panic_timeout;
extern u32 _intv_end, _intv_load_start;
/* Set bus sizes: CS0 32-bit, CS1 16-bit, CS7 8-bit,
everything else 32-bit. */
BSC = 0x2AA6;
for (i = 2; i <= 6; i++)
CSDEV(i) = 0; /* 32 bit */
/* Ensure that the simulator halts on a panic, instead of going
into an infinite loop inside the panic function. */
panic_timeout = -1;
/* Move the interrupt vectors into their real location. Note that
any relocations there are relative to the real location, so we
don't have to fix anything up. We use a loop instead of calling
memcpy to keep this a leaf function (to avoid a function
prologue being generated). */
dst = 0x10; /* &_intv_start + 0x10. */
src = &_intv_load_start;
do {
u32 t0 = src[0], t1 = src[1], t2 = src[2], t3 = src[3];
u32 t4 = src[4], t5 = src[5], t6 = src[6], t7 = src[7];
dst[0] = t0; dst[1] = t1; dst[2] = t2; dst[3] = t3;
dst[4] = t4; dst[5] = t5; dst[6] = t6; dst[7] = t7;
dst += 8;
src += 8;
} while (dst < &_intv_end);
}
void __init mach_setup (char **cmdline)
{
printk (KERN_INFO "CPU: NEC V850E2 (NA85E2C FPGA implementation)\n");
memcons_setup ();
/* Setup up NMI0 to copy the registers to a known memory location.
The FGPA board has a button that produces NMI0 when pressed, so
this allows us to push the button, and then look at memory to see
what's in the registers (there's no other way to easily do so).
We have to use `setup_irq' instead of `request_irq' because it's
still too early to do memory allocation. */
setup_irq (IRQ_NMI (0), &reg_snap_action);
}
void mach_get_physical_ram (unsigned long *ram_start, unsigned long *ram_len)
{
*ram_start = ERAM_ADDR;
*ram_len = ERAM_SIZE;
}
void __init mach_sched_init (struct irqaction *timer_action)
{
/* Setup up the timer interrupt. The FPGA peripheral control
registers _only_ work with single-bit writes (set1/clr1)! */
__clear_bit (RPU_GTMC_CE_BIT, &RPU_GTMC);
__clear_bit (RPU_GTMC_CLK_BIT, &RPU_GTMC);
__set_bit (RPU_GTMC_CE_BIT, &RPU_GTMC);
/* We use the first RPU interrupt, which occurs every 8.192ms. */
setup_irq (IRQ_RPU (0), timer_action);
}
void mach_gettimeofday (struct timespec *tv)
{
tv->tv_sec = 0;
tv->tv_nsec = 0;
}
void machine_halt (void) __attribute__ ((noreturn));
void machine_halt (void)
{
for (;;) {
DWC(0) = 0x7777;
DWC(1) = 0x7777;
ASC = 0xffff;
FLGREG(0) = 1; /* Halt immediately. */
asm ("di; halt; nop; nop; nop; nop; nop");
}
}
void machine_restart (char *__unused)
{
machine_halt ();
}
void machine_power_off (void)
{
machine_halt ();
}
/* Interrupts */
struct nb85e_intc_irq_init irq_inits[] = {
{ "IRQ", 0, NUM_MACH_IRQS, 1, 7 },
{ "RPU", IRQ_RPU(0), IRQ_RPU_NUM, 1, 6 },
{ 0 }
};
#define NUM_IRQ_INITS ((sizeof irq_inits / sizeof irq_inits[0]) - 1)
struct hw_interrupt_type hw_itypes[NUM_IRQ_INITS];
/* Initialize interrupts. */
void __init mach_init_irqs (void)
{
nb85e_intc_init_irq_types (irq_inits, hw_itypes);
}
/* An interrupt handler that copies the registers to a known memory location,
for debugging purposes. */
static void make_reg_snap (int irq, void *dummy, struct pt_regs *regs)
{
(*(unsigned *)REG_DUMP_ADDR)++;
(*(struct pt_regs *)(REG_DUMP_ADDR + sizeof (unsigned))) = *regs;
}
static int reg_snap_dev_id;
static struct irqaction reg_snap_action = {
make_reg_snap, 0, 0, "reg_snap", &reg_snap_dev_id, 0
};
/*
* arch/v850/kernel/gbus_int.c -- Midas labs GBUS interrupt support
*
* Copyright (C) 2001,02 NEC Corporation
* Copyright (C) 2001,02 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#include <linux/types.h>
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/sched.h> /* For some unfathomable reason,
request_irq/free_irq are declared here. */
#include <asm/machdep.h>
#include <asm/irq.h>
/* The number of shared GINT interrupts. */
#define NUM_GINTS 4
/* For each GINT interrupt, how many GBUS interrupts are using it. */
static unsigned gint_num_active_irqs[NUM_GINTS] = { 0 };
/* A table of GINTn interrupts we actually use. */
struct used_gint {
unsigned gint;
unsigned priority;
} used_gint[] = {
{ 1, GBUS_INT_PRIORITY_HIGH },
{ 3, GBUS_INT_PRIORITY_LOW }
};
#define NUM_USED_GINTS (sizeof used_gint / sizeof used_gint[0])
/* A table of which GINT is used by each GBUS interrupts (they are
assigned based on priority). */
static unsigned char gbus_int_gint[IRQ_GBUS_INT_NUM];
/* Interrupt enabling/disabling. */
/* Enable interrupt handling for interrupt IRQ. */
void gbus_int_enable_irq (unsigned irq)
{
unsigned gint = gbus_int_gint[irq - GBUS_INT_BASE_IRQ];
GBUS_INT_ENABLE (GBUS_INT_IRQ_WORD(irq), gint)
|= GBUS_INT_IRQ_MASK (irq);
}
/* Disable interrupt handling for interrupt IRQ. Note that any
interrupts received while disabled will be delivered once the
interrupt is enabled again, unless they are explicitly cleared using
`gbus_int_clear_pending_irq'. */
void gbus_int_disable_irq (unsigned irq)
{
unsigned gint = gbus_int_gint[irq - GBUS_INT_BASE_IRQ];
GBUS_INT_ENABLE (GBUS_INT_IRQ_WORD(irq), gint)
&= ~GBUS_INT_IRQ_MASK (irq);
}
/* Return true if interrupt handling for interrupt IRQ is enabled. */
int gbus_int_irq_enabled (unsigned irq)
{
unsigned gint = gbus_int_gint[irq - GBUS_INT_BASE_IRQ];
return (GBUS_INT_ENABLE (GBUS_INT_IRQ_WORD(irq), gint)
& GBUS_INT_IRQ_MASK(irq));
}
/* Disable all GBUS irqs. */
int gbus_int_disable_irqs ()
{
unsigned w, n;
for (w = 0; w < GBUS_INT_NUM_WORDS; w++)
for (n = 0; n < IRQ_GINT_NUM; n++)
GBUS_INT_ENABLE (w, n) = 0;
}
/* Clear any pending interrupts for IRQ. */
void gbus_int_clear_pending_irq (unsigned irq)
{
GBUS_INT_CLEAR (GBUS_INT_IRQ_WORD(irq)) = GBUS_INT_IRQ_MASK (irq);
}
/* Return true if interrupt IRQ is pending (but disabled). */
int gbus_int_irq_pending (unsigned irq)
{
return (GBUS_INT_STATUS (GBUS_INT_IRQ_WORD(irq))
& GBUS_INT_IRQ_MASK(irq));
}
/* Delegating interrupts. */
/* Handle a shared GINT interrupt by passing to the appropriate GBUS
interrupt handler. */
static void gbus_int_handle_irq (int irq, void *dev_id, struct pt_regs *regs)
{
unsigned w;
unsigned gint = irq - IRQ_GINT (0);
for (w = 0; w < GBUS_INT_NUM_WORDS; w++) {
unsigned status = GBUS_INT_STATUS (w);
unsigned enable = GBUS_INT_ENABLE (w, gint);
/* Only pay attention to enabled interrupts. */
status &= enable;
if (status) {
unsigned base_irq
= IRQ_GBUS_INT (w * GBUS_INT_BITS_PER_WORD);
irq = base_irq;
do {
/* There's an active interrupt in word
W, find out which one, and call its
handler. */
while (! (status & 0x1)) {
irq++;
status >>= 1;
}
status &= ~0x1;
/* Recursively call handle_irq to handle it. */
handle_irq (irq, regs);
} while (status);
}
}
/* Toggle the `all enable' bit back and forth, which should cause
another edge transition if there are any other interrupts
still pending, and so result in another CPU interrupt. */
GBUS_INT_ENABLE (0, gint) &= ~0x1;
GBUS_INT_ENABLE (0, gint) |= 0x1;
}
/* Initialize GBUS interrupt sources. */
static void irq_nop (unsigned irq) { }
static unsigned gbus_int_startup_irq (unsigned irq)
{
unsigned gint = gbus_int_gint[irq - GBUS_INT_BASE_IRQ];
if (gint_num_active_irqs[gint] == 0) {
/* First enable the CPU interrupt. */
int rval =
request_irq (IRQ_GINT(gint), gbus_int_handle_irq,
SA_INTERRUPT,
"gbus_int_handler",
&gint_num_active_irqs[gint]);
if (rval != 0)
return rval;
}
gint_num_active_irqs[gint]++;
gbus_int_clear_pending_irq (irq);
gbus_int_enable_irq (irq);
return 0;
}
static void gbus_int_shutdown_irq (unsigned irq)
{
unsigned gint = gbus_int_gint[irq - GBUS_INT_BASE_IRQ];
gbus_int_disable_irq (irq);
if (--gint_num_active_irqs[gint] == 0)
/* Disable the CPU interrupt. */
free_irq (IRQ_GINT(gint), &gint_num_active_irqs[gint]);
}
/* Initialize HW_IRQ_TYPES for INTC-controlled irqs described in array
INITS (which is terminated by an entry with the name field == 0). */
void __init gbus_int_init_irq_types (struct gbus_int_irq_init *inits,
struct hw_interrupt_type *hw_irq_types)
{
struct gbus_int_irq_init *init;
for (init = inits; init->name; init++) {
int i;
struct hw_interrupt_type *hwit = hw_irq_types++;
hwit->typename = init->name;
hwit->startup = gbus_int_startup_irq;
hwit->shutdown = gbus_int_shutdown_irq;
hwit->enable = gbus_int_enable_irq;
hwit->disable = gbus_int_disable_irq;
hwit->ack = irq_nop;
hwit->end = irq_nop;
/* Initialize kernel IRQ infrastructure for this interrupt. */
init_irq_handlers(init->base, init->num, init->interval, hwit);
/* Set the interrupt priorities. */
for (i = 0; i < init->num; i++) {
int j;
for (j = 0; j < NUM_USED_GINTS; j++)
if (used_gint[j].priority > init->priority)
break;
/* Wherever we stopped looking is one past the
GINT we want. */
gbus_int_gint[init->base + i * init->interval
- GBUS_INT_BASE_IRQ]
= used_gint[j > 0 ? j - 1 : 0].gint;
}
}
}
/* Initialize IRQS. */
/* Chip interrupts (GINTn) shared among GBUS interrupts. */
static struct hw_interrupt_type gint_hw_itypes[NUM_USED_GINTS];
/* GBUS interrupts themselves. */
__init struct gbus_int_irq_init gbus_irq_inits[] = {
/* First set defaults. */
{ "GBUS_INT", IRQ_GBUS_INT(0), IRQ_GBUS_INT_NUM, 1, 6},
{ 0 }
};
#define NUM_GBUS_IRQ_INITS \
((sizeof gbus_irq_inits / sizeof gbus_irq_inits[0]) - 1)
static struct hw_interrupt_type gbus_hw_itypes[NUM_GBUS_IRQ_INITS];
/* Initialize GBUS interrupts. */
void __init gbus_int_init_irqs (void)
{
int i;
/* First initialize the shared gint interrupts. */
for (i = 0; i < NUM_USED_GINTS; i++) {
unsigned gint = used_gint[i].gint;
struct nb85e_intc_irq_init gint_irq_init[2];
/* We initialize one GINT interrupt at a time. */
gint_irq_init[0].name = "GINT";
gint_irq_init[0].base = IRQ_GINT (gint);
gint_irq_init[0].num = 1;
gint_irq_init[0].interval = 1;
gint_irq_init[0].priority = used_gint[i].priority;
gint_irq_init[1].name = 0; /* Terminate the vector. */
nb85e_intc_init_irq_types (gint_irq_init, gint_hw_itypes);
}
/* Then the GBUS interrupts. */
gbus_int_disable_irqs ();
gbus_int_init_irq_types (gbus_irq_inits, gbus_hw_itypes);
/* Turn on the `all enable' bits, which are ANDed with
individual interrupt enable bits; we only want to bother with
the latter. They are the first bit in the first word of each
interrupt-enable area. */
for (i = 0; i < NUM_USED_GINTS; i++)
GBUS_INT_ENABLE (0, used_gint[i].gint) = 0x1;
}
/*
* arch/v850/kernel/head.S -- Lowest-level startup code
*
* Copyright (C) 2001,02 NEC Corporation
* Copyright (C) 2001,02 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#include <asm/clinkage.h>
#include <asm/current.h>
#include <asm/entry.h>
#include <asm/thread_info.h>
#include <asm/irq.h>
/* Make a slightly more convenient alias for C_SYMBOL_NAME. */
#define CSYM C_SYMBOL_NAME
.text
// Define `mach_early_init' as a weak symbol
.global CSYM(mach_early_init)
.weak CSYM(mach_early_init)
C_ENTRY(start):
// Make sure interrupts are turned off, just in case
di
#ifdef CONFIG_RESET_GUARD
// See if we got here via an unexpected reset
ld.w RESET_GUARD, r19 // Check current value of reset guard
mov RESET_GUARD_ACTIVE, r20
cmp r19, r20
bne 1f // Guard was not active
// If we get here, the reset guard was active. Load up some
// interesting values as arguments, and jump to the handler.
st.w r0, RESET_GUARD // Allow further resets to succeed
mov lp, r6 // Arg 0: return address
ld.b KM, r7 // Arg 1: kernel mode
mov sp, r9 // Arg 3: stack pointer
ld.w KSP, r19 // maybe switch to kernel stack
cmp r7, r0 // see if already in kernel mode
cmov z, r19, sp, sp // and switch to kernel stack if not
GET_CURRENT_TASK(r8) // Arg 2: task pointer
jr CSYM(unexpected_reset)
1: st.w r20, RESET_GUARD // Turn on reset guard
#endif /* CONFIG_RESET_GUARD */
// Setup a temporary stack for doing pre-initialization function calls.
//
// We can't use the initial kernel stack, because (1) it may be
// located in memory we're not allowed to touch, and (2) since
// it's in the data segment, calling memcpy to initialize that
// area from ROM will overwrite memcpy's return address.
mov hilo(CSYM(_init_stack_end) - 4), sp
// See if there's a platform-specific early-initialization routine
// defined; it's a weak symbol, so it will have an address of zero if
// there's not.
mov hilo(CSYM(mach_early_init)), r6
cmp r6, r0
bz 3f
// There is one, so call it. If this function is written in C, it
// should be very careful -- the stack pointer is valid, but very
// little else is (e.g., bss is not zeroed yet, and initialized data
// hasn't been).
jarl 2f, lp // first figure out return address
2: add 3f - ., lp
jmp [r6] // do call
3:
#ifdef CONFIG_ROM_KERNEL
// Copy the data area from ROM to RAM
mov hilo(CSYM(_rom_copy_dst_start)), r6
mov hilo(CSYM(_rom_copy_src_start)), r7
mov hilo(CSYM(_rom_copy_dst_end)), r8
sub r6, r8
jarl CSYM(memcpy), lp
#endif
// Load the initial thread's stack, and current task pointer (in r16)
mov hilo(CSYM(init_thread_union)), r19
movea THREAD_SIZE, r19, sp
ld.w TI_TASK[r19], CURRENT_TASK
#ifdef CONFIG_TIME_BOOTUP
/* This stuff must come after mach_early_init, because interrupts may
not work until after its been called. */
jarl CSYM(highres_timer_reset), lp
jarl CSYM(highres_timer_start), lp
#endif
// Kernel stack pointer save location
st.w sp, KSP
// Assert that we're in `kernel mode'
mov 1, r19
st.w r19, KM
#ifdef CONFIG_ZERO_BSS
// Zero bss area, since we can't rely upon any loader to do so
mov hilo(CSYM(_sbss)), r6
mov r0, r7
mov hilo(CSYM(_ebss)), r8
sub r6, r8
jarl CSYM(memset), lp
#endif
// Start Linux kernel.
mov hilo(CSYM(machine_halt)), lp
jr CSYM(start_kernel)
END(start)
/*
* arch/v850/kernel/highres_timer.c -- High resolution timing routines
*
* Copyright (C) 2001,02 NEC Corporation
* Copyright (C) 2001,02 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#include <asm/system.h>
#include <asm/nb85e_timer_d.h>
#include <asm/highres_timer.h>
#define HIGHRES_TIMER_USEC_SHIFT 12
/* Pre-calculated constant used for converting ticks to real time
units. We initialize it to prevent it being put into BSS. */
static u32 highres_timer_usec_prescale = 1;
void highres_timer_slow_tick_irq (void) __attribute__ ((noreturn));
void highres_timer_slow_tick_irq (void)
{
/* This is an interrupt handler, so it must be very careful to
not to trash any registers. At this point, the stack-pointer
(r3) has been saved in the chip ram location ENTRY_SP by the
interrupt vector, so we can use it as a scratch register; we
must also restore it before returning. */
asm ("ld.w %0[r0], sp;"
"add 1, sp;"
"st.w sp, %0[r0];"
"ld.w %1[r0], sp;" /* restore pre-irq stack-pointer */
"reti"
::
"i" (HIGHRES_TIMER_SLOW_TICKS_ADDR),
"i" (ENTRY_SP_ADDR)
: "memory");
}
void highres_timer_reset (void)
{
NB85E_TIMER_D_TMD (HIGHRES_TIMER_TIMER_D_UNIT) = 0;
HIGHRES_TIMER_SLOW_TICKS = 0;
}
void highres_timer_start (void)
{
u32 fast_tick_rate;
/* Start hardware timer. */
nb85e_timer_d_configure (HIGHRES_TIMER_TIMER_D_UNIT,
HIGHRES_TIMER_SLOW_TICK_RATE);
fast_tick_rate =
(NB85E_TIMER_D_BASE_FREQ
>> NB85E_TIMER_D_DIVLOG2 (HIGHRES_TIMER_TIMER_D_UNIT));
/* The obvious way of calculating microseconds from fast ticks
is to do:
usec = fast_ticks * 10^6 / fast_tick_rate
However, divisions are much slower than multiplications, and
the above calculation can overflow, so we do this instead:
usec = fast_ticks * (10^6 * 2^12 / fast_tick_rate) / 2^12
since we can pre-calculate (10^6 * (2^12 / fast_tick_rate))
and use a shift for dividing by 2^12, this avoids division,
and is almost as accurate (it differs by about 2 microseconds
at the extreme value of the fast-tick counter's ranger). */
highres_timer_usec_prescale = ((1000000 << HIGHRES_TIMER_USEC_SHIFT)
/ fast_tick_rate);
/* Enable the interrupt (which is hardwired to this use), and
give it the highest priority. */
NB85E_INTC_IC (IRQ_INTCMD (HIGHRES_TIMER_TIMER_D_UNIT)) = 0;
}
void highres_timer_stop (void)
{
/* Stop the timer. */
NB85E_TIMER_D_TMCD (HIGHRES_TIMER_TIMER_D_UNIT) =
NB85E_TIMER_D_TMCD_CAE;
/* Disable its interrupt, just in case. */
nb85e_intc_disable_irq (IRQ_INTCMD (HIGHRES_TIMER_TIMER_D_UNIT));
}
inline void highres_timer_read_ticks (u32 *slow_ticks, u32 *fast_ticks)
{
int flags;
u32 fast_ticks_1, fast_ticks_2, _slow_ticks;
local_irq_save (flags);
fast_ticks_1 = NB85E_TIMER_D_TMD (HIGHRES_TIMER_TIMER_D_UNIT);
_slow_ticks = HIGHRES_TIMER_SLOW_TICKS;
fast_ticks_2 = NB85E_TIMER_D_TMD (HIGHRES_TIMER_TIMER_D_UNIT);
local_irq_restore (flags);
if (fast_ticks_2 < fast_ticks_1)
_slow_ticks++;
*slow_ticks = _slow_ticks;
*fast_ticks = fast_ticks_2;
}
inline void highres_timer_ticks_to_timeval (u32 slow_ticks, u32 fast_ticks,
struct timeval *tv)
{
unsigned long sec, sec_rem, usec;
usec = ((fast_ticks * highres_timer_usec_prescale)
>> HIGHRES_TIMER_USEC_SHIFT);
sec = slow_ticks / HIGHRES_TIMER_SLOW_TICK_RATE;
sec_rem = slow_ticks % HIGHRES_TIMER_SLOW_TICK_RATE;
usec += sec_rem * (1000000 / HIGHRES_TIMER_SLOW_TICK_RATE);
tv->tv_sec = sec;
tv->tv_usec = usec;
}
void highres_timer_read (struct timeval *tv)
{
u32 fast_ticks, slow_ticks;
highres_timer_read_ticks (&slow_ticks, &fast_ticks);
highres_timer_ticks_to_timeval (slow_ticks, fast_ticks, tv);
}
/*
* arch/v850/kernel/init_task.c -- Initial task/thread structures
*
* Copyright (C) 2002 NEC Corporation
* Copyright (C) 2002 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*/
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <linux/init_task.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
static struct fs_struct init_fs = INIT_FS;
static struct files_struct init_files = INIT_FILES;
static struct signal_struct init_signals = INIT_SIGNALS (init_signals);
struct mm_struct init_mm = INIT_MM (init_mm);
/*
* Initial task structure.
*
* All other task structs will be allocated on slabs in fork.c
*/
struct task_struct init_task = INIT_TASK (init_task);
/*
* Initial thread structure.
*
* We need to make sure that this is 8192-byte aligned due to the
* way process stacks are handled. This is done by having a special
* "init_task" linker map entry.
*/
union thread_union init_thread_union
__attribute__((__section__(".data.init_task"))) =
{ INIT_THREAD_INFO(init_task) };
/*
* arch/v850/kernel/intv.S -- Interrupt vectors
*
* Copyright (C) 2001,02 NEC Corporation
* Copyright (C) 2001,02 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#include <asm/clinkage.h>
#include <asm/irq.h>
#include <asm/machdep.h>
#include <asm/entry.h>
#ifdef CONFIG_V850E_MA1_HIGHRES_TIMER
#include <asm/highres_timer.h>
#endif
/* Jump to an interrupt/trap handler. These handlers (defined in entry.S)
expect the stack-pointer to be saved in ENTRY_SP, so we use sp to do an
indirect jump (which avoids problems when the handler is more than a signed
22-bit offset away). */
#define JUMP_TO_HANDLER(name, sp_save_loc) \
st.w sp, sp_save_loc; \
mov hilo(name), sp; \
jmp [sp]
/* Reset vector. */
.section .intv.reset, "ax"
.org 0x0
mov hilo(C_SYMBOL_NAME(start)), r1;
jmp [r1]
/* Generic interrupt vectors. */
.section .intv.common, "ax"
.balign 0x10
JUMP_TO_HANDLER (nmi, NMI_ENTRY_SP) // NMI0
.balign 0x10
JUMP_TO_HANDLER (nmi, NMI_ENTRY_SP) // NMI1
.balign 0x10
JUMP_TO_HANDLER (nmi, NMI_ENTRY_SP) // NMI2
.balign 0x10
JUMP_TO_HANDLER (trap, ENTRY_SP) // TRAP0n
.balign 0x10
JUMP_TO_HANDLER (trap, ENTRY_SP) // TRAP1n
.balign 0x10
JUMP_TO_HANDLER (illegal_instruction, ENTRY_SP) // illegal insn trap
.balign 0x10
JUMP_TO_HANDLER (dbtrap, ENTRY_SP) // DBTRAP insn
/* Hardware interrupt vectors. */
.section .intv.mach, "ax"
.org 0x0
#if defined (CONFIG_V850E_MA1_HIGHRES_TIMER) && defined (IRQ_INTCMD)
/* Interrupts before the highres timer interrupt. */
.rept IRQ_INTCMD (HIGHRES_TIMER_TIMER_D_UNIT)
.balign 0x10
JUMP_TO_HANDLER (irq, ENTRY_SP)
.endr
/* The highres timer interrupt. */
.balign 0x10
JUMP_TO_HANDLER (C_SYMBOL_NAME (highres_timer_slow_tick_irq), ENTRY_SP)
/* Interrupts after the highres timer interrupt. */
.rept NUM_CPU_IRQS - IRQ_INTCMD (HIGHRES_TIMER_TIMER_D_UNIT) - 1
.balign 0x10
JUMP_TO_HANDLER (irq, ENTRY_SP)
.endr
#else /* No highres timer */
.rept NUM_CPU_IRQS
.balign 0x10
JUMP_TO_HANDLER (irq, ENTRY_SP)
.endr
#endif /* Highres timer */
/*
* arch/v850/kernel/irq.c -- High-level interrupt handling
*
* Copyright (C) 2001,02 NEC Corporation
* Copyright (C) 2001,02 Miles Bader <miles@gnu.org>
* Copyright (C) 1994-2000 Ralf Baechle
* Copyright (C) 1992 Linus Torvalds
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* This file was was derived from the mips version, arch/mips/kernel/irq.c
*/
#include <linux/kernel.h>
#include <linux/irq.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/kernel_stat.h>
#include <linux/slab.h>
#include <linux/mm.h>
#include <linux/random.h>
#include <linux/sched.h>
#include <linux/seq_file.h>
#include <asm/system.h>
/*
* Controller mappings for all interrupt sources:
*/
irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned =
{ [0 ... NR_IRQS-1] = { 0, &no_irq_type, NULL, 0, SPIN_LOCK_UNLOCKED}};
/*
* Special irq handlers.
*/
void no_action(int cpl, void *dev_id, struct pt_regs *regs) { }
/*
* Generic no controller code
*/
static void enable_none(unsigned int irq) { }
static unsigned int startup_none(unsigned int irq) { return 0; }
static void disable_none(unsigned int irq) { }
static void ack_none(unsigned int irq)
{
/*
* 'what should we do if we get a hw irq event on an illegal vector'.
* each architecture has to answer this themselves, it doesnt deserve
* a generic callback i think.
*/
printk("received IRQ %d with unknown interrupt type\n", irq);
}
/* startup is the same as "enable", shutdown is same as "disable" */
#define shutdown_none disable_none
#define end_none enable_none
struct hw_interrupt_type no_irq_type = {
"none",
startup_none,
shutdown_none,
enable_none,
disable_none,
ack_none,
end_none
};
volatile unsigned long irq_err_count, spurious_count;
/*
* Generic, controller-independent functions:
*/
int show_interrupts(struct seq_file *p, void *v)
{
int i;
struct irqaction * action;
seq_puts(p, " ");
for (i=0; i < 1 /*smp_num_cpus*/; i++)
seq_printf(p, "CPU%d ", i);
seq_putc(p, '\n');
for (i = 0 ; i < NR_IRQS ; i++) {
int j, count, num;
const char *type_name = irq_desc[i].handler->typename;
action = irq_desc[i].action;
if (!action)
continue;
count = 0;
num = -1;
for (j = 0; j < NR_IRQS; j++)
if (irq_desc[j].handler->typename == type_name) {
if (i == j)
num = count;
count++;
}
seq_printf(p, "%3d: ",i);
seq_printf(p, "%10u ", kstat_irqs(i));
if (count > 1) {
int prec = (num >= 100 ? 3 : num >= 10 ? 2 : 1);
seq_printf(p, " %*s%d", 14 - prec, type_name, num);
} else
seq_printf(p, " %14s", type_name);
seq_printf(p, " %s", action->name);
for (action=action->next; action; action = action->next)
seq_printf(p, ", %s", action->name);
seq_putc(p, '\n');
}
seq_printf(p, "ERR: %10lu\n", irq_err_count);
return 0;
}
/*
* This should really return information about whether
* we should do bottom half handling etc. Right now we
* end up _always_ checking the bottom half, which is a
* waste of time and is not what some drivers would
* prefer.
*/
int handle_IRQ_event(unsigned int irq, struct pt_regs * regs, struct irqaction * action)
{
int status = 1; /* Force the "do bottom halves" bit */
if (!(action->flags & SA_INTERRUPT))
local_irq_enable();
do {
status |= action->flags;
action->handler(irq, action->dev_id, regs);
action = action->next;
} while (action);
if (status & SA_SAMPLE_RANDOM)
add_interrupt_randomness(irq);
local_irq_disable();
return status;
}
/*
* Generic enable/disable code: this just calls
* down into the PIC-specific version for the actual
* hardware disable after having gotten the irq
* controller lock.
*/
/**
* disable_irq_nosync - disable an irq without waiting
* @irq: Interrupt to disable
*
* Disable the selected interrupt line. Disables of an interrupt
* stack. Unlike disable_irq(), this function does not ensure existing
* instances of the IRQ handler have completed before returning.
*
* This function may be called from IRQ context.
*/
void inline disable_irq_nosync(unsigned int irq)
{
irq_desc_t *desc = irq_desc + irq;
unsigned long flags;
spin_lock_irqsave(&desc->lock, flags);
if (!desc->depth++) {
desc->status |= IRQ_DISABLED;
desc->handler->disable(irq);
}
spin_unlock_irqrestore(&desc->lock, flags);
}
/**
* disable_irq - disable an irq and wait for completion
* @irq: Interrupt to disable
*
* Disable the selected interrupt line. Disables of an interrupt
* stack. That is for two disables you need two enables. This
* function waits for any pending IRQ handlers for this interrupt
* to complete before returning. If you use this function while
* holding a resource the IRQ handler may need you will deadlock.
*
* This function may be called - with care - from IRQ context.
*/
void disable_irq(unsigned int irq)
{
disable_irq_nosync(irq);
synchronize_irq(irq);
}
/**
* enable_irq - enable interrupt handling on an irq
* @irq: Interrupt to enable
*
* Re-enables the processing of interrupts on this IRQ line
* providing no disable_irq calls are now in effect.
*
* This function may be called from IRQ context.
*/
void enable_irq(unsigned int irq)
{
irq_desc_t *desc = irq_desc + irq;
unsigned long flags;
spin_lock_irqsave(&desc->lock, flags);
switch (desc->depth) {
case 1: {
unsigned int status = desc->status & ~IRQ_DISABLED;
desc->status = status;
if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) {
desc->status = status | IRQ_REPLAY;
hw_resend_irq(desc->handler,irq);
}
desc->handler->enable(irq);
/* fall-through */
}
default:
desc->depth--;
break;
case 0:
printk("enable_irq(%u) unbalanced from %p\n", irq,
__builtin_return_address(0));
}
spin_unlock_irqrestore(&desc->lock, flags);
}
/* Handle interrupt IRQ. REGS are the registers at the time of ther
interrupt. */
unsigned int handle_irq (int irq, struct pt_regs *regs)
{
/*
* We ack quickly, we don't want the irq controller
* thinking we're snobs just because some other CPU has
* disabled global interrupts (we have already done the
* INT_ACK cycles, it's too late to try to pretend to the
* controller that we aren't taking the interrupt).
*
* 0 return value means that this irq is already being
* handled by some other CPU. (or is disabled)
*/
int cpu = smp_processor_id();
irq_desc_t *desc = irq_desc + irq;
struct irqaction * action;
unsigned int status;
irq_enter();
kstat.irqs[cpu][irq]++;
spin_lock(&desc->lock);
desc->handler->ack(irq);
/*
REPLAY is when Linux resends an IRQ that was dropped earlier
WAITING is used by probe to mark irqs that are being tested
*/
status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING);
status |= IRQ_PENDING; /* we _want_ to handle it */
/*
* If the IRQ is disabled for whatever reason, we cannot
* use the action we have.
*/
action = NULL;
if (likely(!(status & (IRQ_DISABLED | IRQ_INPROGRESS)))) {
action = desc->action;
status &= ~IRQ_PENDING; /* we commit to handling */
status |= IRQ_INPROGRESS; /* we are handling it */
}
desc->status = status;
/*
* If there is no IRQ handler or it was disabled, exit early.
Since we set PENDING, if another processor is handling
a different instance of this same irq, the other processor
will take care of it.
*/
if (unlikely(!action))
goto out;
/*
* Edge triggered interrupts need to remember
* pending events.
* This applies to any hw interrupts that allow a second
* instance of the same irq to arrive while we are in handle_irq
* or in the handler. But the code here only handles the _second_
* instance of the irq, not the third or fourth. So it is mostly
* useful for irq hardware that does not mask cleanly in an
* SMP environment.
*/
for (;;) {
spin_unlock(&desc->lock);
handle_IRQ_event(irq, regs, action);
spin_lock(&desc->lock);
if (likely(!(desc->status & IRQ_PENDING)))
break;
desc->status &= ~IRQ_PENDING;
}
desc->status &= ~IRQ_INPROGRESS;
out:
/*
* The ->end() handler has to deal with interrupts which got
* disabled while the handler was running.
*/
desc->handler->end(irq);
spin_unlock(&desc->lock);
irq_exit();
return 1;
}
/**
* request_irq - allocate an interrupt line
* @irq: Interrupt line to allocate
* @handler: Function to be called when the IRQ occurs
* @irqflags: Interrupt type flags
* @devname: An ascii name for the claiming device
* @dev_id: A cookie passed back to the handler function
*
* This call allocates interrupt resources and enables the
* interrupt line and IRQ handling. From the point this
* call is made your handler function may be invoked. Since
* your handler function must clear any interrupt the board
* raises, you must take care both to initialise your hardware
* and to set up the interrupt handler in the right order.
*
* Dev_id must be globally unique. Normally the address of the
* device data structure is used as the cookie. Since the handler
* receives this value it makes sense to use it.
*
* If your interrupt is shared you must pass a non NULL dev_id
* as this is required when freeing the interrupt.
*
* Flags:
*
* SA_SHIRQ Interrupt is shared
*
* SA_INTERRUPT Disable local interrupts while processing
*
* SA_SAMPLE_RANDOM The interrupt can be used for entropy
*
*/
int request_irq(unsigned int irq,
void (*handler)(int, void *, struct pt_regs *),
unsigned long irqflags,
const char * devname,
void *dev_id)
{
int retval;
struct irqaction * action;
#if 1
/*
* Sanity-check: shared interrupts should REALLY pass in
* a real dev-ID, otherwise we'll have trouble later trying
* to figure out which interrupt is which (messes up the
* interrupt freeing logic etc).
*/
if (irqflags & SA_SHIRQ) {
if (!dev_id)
printk("Bad boy: %s (at 0x%x) called us without a dev_id!\n", devname, (&irq)[-1]);
}
#endif
if (irq >= NR_IRQS)
return -EINVAL;
if (!handler)
return -EINVAL;
action = (struct irqaction *)
kmalloc(sizeof(struct irqaction), GFP_KERNEL);
if (!action)
return -ENOMEM;
action->handler = handler;
action->flags = irqflags;
action->mask = 0;
action->name = devname;
action->next = NULL;
action->dev_id = dev_id;
retval = setup_irq(irq, action);
if (retval)
kfree(action);
return retval;
}
/**
* free_irq - free an interrupt
* @irq: Interrupt line to free
* @dev_id: Device identity to free
*
* Remove an interrupt handler. The handler is removed and if the
* interrupt line is no longer in use by any driver it is disabled.
* On a shared IRQ the caller must ensure the interrupt is disabled
* on the card it drives before calling this function. The function
* does not return until any executing interrupts for this IRQ
* have completed.
*
* This function may be called from interrupt context.
*
* Bugs: Attempting to free an irq in a handler for the same irq hangs
* the machine.
*/
void free_irq(unsigned int irq, void *dev_id)
{
irq_desc_t *desc;
struct irqaction **p;
unsigned long flags;
if (irq >= NR_IRQS)
return;
desc = irq_desc + irq;
spin_lock_irqsave(&desc->lock,flags);
p = &desc->action;
for (;;) {
struct irqaction * action = *p;
if (action) {
struct irqaction **pp = p;
p = &action->next;
if (action->dev_id != dev_id)
continue;
/* Found it - now remove it from the list of entries */
*pp = action->next;
if (!desc->action) {
desc->status |= IRQ_DISABLED;
desc->handler->shutdown(irq);
}
spin_unlock_irqrestore(&desc->lock,flags);
synchronize_irq(irq);
kfree(action);
return;
}
printk("Trying to free free IRQ%d\n",irq);
spin_unlock_irqrestore(&desc->lock,flags);
return;
}
}
/*
* IRQ autodetection code..
*
* This depends on the fact that any interrupt that
* comes in on to an unassigned handler will get stuck
* with "IRQ_WAITING" cleared and the interrupt
* disabled.
*/
static DECLARE_MUTEX(probe_sem);
/**
* probe_irq_on - begin an interrupt autodetect
*
* Commence probing for an interrupt. The interrupts are scanned
* and a mask of potential interrupt lines is returned.
*
*/
unsigned long probe_irq_on(void)
{
unsigned int i;
irq_desc_t *desc;
unsigned long val;
unsigned long delay;
down(&probe_sem);
/*
* something may have generated an irq long ago and we want to
* flush such a longstanding irq before considering it as spurious.
*/
for (i = NR_IRQS-1; i > 0; i--) {
desc = irq_desc + i;
spin_lock_irq(&desc->lock);
if (!irq_desc[i].action)
irq_desc[i].handler->startup(i);
spin_unlock_irq(&desc->lock);
}
/* Wait for longstanding interrupts to trigger. */
for (delay = jiffies + HZ/50; time_after(delay, jiffies); )
/* about 20ms delay */ barrier();
/*
* enable any unassigned irqs
* (we must startup again here because if a longstanding irq
* happened in the previous stage, it may have masked itself)
*/
for (i = NR_IRQS-1; i > 0; i--) {
desc = irq_desc + i;
spin_lock_irq(&desc->lock);
if (!desc->action) {
desc->status |= IRQ_AUTODETECT | IRQ_WAITING;
if (desc->handler->startup(i))
desc->status |= IRQ_PENDING;
}
spin_unlock_irq(&desc->lock);
}
/*
* Wait for spurious interrupts to trigger
*/
for (delay = jiffies + HZ/10; time_after(delay, jiffies); )
/* about 100ms delay */ barrier();
/*
* Now filter out any obviously spurious interrupts
*/
val = 0;
for (i = 0; i < NR_IRQS; i++) {
irq_desc_t *desc = irq_desc + i;
unsigned int status;
spin_lock_irq(&desc->lock);
status = desc->status;
if (status & IRQ_AUTODETECT) {
/* It triggered already - consider it spurious. */
if (!(status & IRQ_WAITING)) {
desc->status = status & ~IRQ_AUTODETECT;
desc->handler->shutdown(i);
} else
if (i < 32)
val |= 1 << i;
}
spin_unlock_irq(&desc->lock);
}
return val;
}
/*
* Return a mask of triggered interrupts (this
* can handle only legacy ISA interrupts).
*/
/**
* probe_irq_mask - scan a bitmap of interrupt lines
* @val: mask of interrupts to consider
*
* Scan the ISA bus interrupt lines and return a bitmap of
* active interrupts. The interrupt probe logic state is then
* returned to its previous value.
*
* Note: we need to scan all the irq's even though we will
* only return ISA irq numbers - just so that we reset them
* all to a known state.
*/
unsigned int probe_irq_mask(unsigned long val)
{
int i;
unsigned int mask;
mask = 0;
for (i = 0; i < NR_IRQS; i++) {
irq_desc_t *desc = irq_desc + i;
unsigned int status;
spin_lock_irq(&desc->lock);
status = desc->status;
if (status & IRQ_AUTODETECT) {
if (i < 16 && !(status & IRQ_WAITING))
mask |= 1 << i;
desc->status = status & ~IRQ_AUTODETECT;
desc->handler->shutdown(i);
}
spin_unlock_irq(&desc->lock);
}
up(&probe_sem);
return mask & val;
}
/*
* Return the one interrupt that triggered (this can
* handle any interrupt source).
*/
/**
* probe_irq_off - end an interrupt autodetect
* @val: mask of potential interrupts (unused)
*
* Scans the unused interrupt lines and returns the line which
* appears to have triggered the interrupt. If no interrupt was
* found then zero is returned. If more than one interrupt is
* found then minus the first candidate is returned to indicate
* their is doubt.
*
* The interrupt probe logic state is returned to its previous
* value.
*
* BUGS: When used in a module (which arguably shouldnt happen)
* nothing prevents two IRQ probe callers from overlapping. The
* results of this are non-optimal.
*/
int probe_irq_off(unsigned long val)
{
int i, irq_found, nr_irqs;
nr_irqs = 0;
irq_found = 0;
for (i = 0; i < NR_IRQS; i++) {
irq_desc_t *desc = irq_desc + i;
unsigned int status;
spin_lock_irq(&desc->lock);
status = desc->status;
if (status & IRQ_AUTODETECT) {
if (!(status & IRQ_WAITING)) {
if (!nr_irqs)
irq_found = i;
nr_irqs++;
}
desc->status = status & ~IRQ_AUTODETECT;
desc->handler->shutdown(i);
}
spin_unlock_irq(&desc->lock);
}
up(&probe_sem);
if (nr_irqs > 1)
irq_found = -irq_found;
return irq_found;
}
/* this was setup_x86_irq but it seems pretty generic */
int setup_irq(unsigned int irq, struct irqaction * new)
{
int shared = 0;
unsigned long flags;
struct irqaction *old, **p;
irq_desc_t *desc = irq_desc + irq;
/*
* Some drivers like serial.c use request_irq() heavily,
* so we have to be careful not to interfere with a
* running system.
*/
if (new->flags & SA_SAMPLE_RANDOM) {
/*
* This function might sleep, we want to call it first,
* outside of the atomic block.
* Yes, this might clear the entropy pool if the wrong
* driver is attempted to be loaded, without actually
* installing a new handler, but is this really a problem,
* only the sysadmin is able to do this.
*/
rand_initialize_irq(irq);
}
/*
* The following block of code has to be executed atomically
*/
spin_lock_irqsave(&desc->lock,flags);
p = &desc->action;
if ((old = *p) != NULL) {
/* Can't share interrupts unless both agree to */
if (!(old->flags & new->flags & SA_SHIRQ)) {
spin_unlock_irqrestore(&desc->lock,flags);
return -EBUSY;
}
/* add new interrupt at end of irq queue */
do {
p = &old->next;
old = *p;
} while (old);
shared = 1;
}
*p = new;
if (!shared) {
desc->depth = 0;
desc->status &= ~(IRQ_DISABLED | IRQ_AUTODETECT | IRQ_WAITING | IRQ_INPROGRESS);
desc->handler->startup(irq);
}
spin_unlock_irqrestore(&desc->lock,flags);
/* register_irq_proc(irq); */
return 0;
}
/* Initialize irq handling for IRQs.
BASE_IRQ, BASE_IRQ+INTERVAL, ..., BASE_IRQ+NUM*INTERVAL
to IRQ_TYPE. An IRQ_TYPE of 0 means to use a generic interrupt type. */
void __init
init_irq_handlers (int base_irq, int num, int interval,
struct hw_interrupt_type *irq_type)
{
while (num-- > 0) {
irq_desc[base_irq].status = IRQ_DISABLED;
irq_desc[base_irq].action = NULL;
irq_desc[base_irq].depth = 1;
irq_desc[base_irq].handler = irq_type;
base_irq += interval;
}
}
/*
* arch/v850/kernel/ma.c -- V850E/MA series of cpu chips
*
* Copyright (C) 2001,02 NEC Corporation
* Copyright (C) 2001,02 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/swap.h>
#include <linux/bootmem.h>
#include <linux/irq.h>
#include <asm/atomic.h>
#include <asm/page.h>
#include <asm/machdep.h>
#include <asm/nb85e_timer_d.h>
#include "mach.h"
void __init mach_sched_init (struct irqaction *timer_action)
{
/* Start hardware timer. */
nb85e_timer_d_configure (0, HZ);
/* Install timer interrupt handler. */
setup_irq (IRQ_INTCMD(0), timer_action);
}
static struct nb85e_intc_irq_init irq_inits[] = {
{ "IRQ", 0, NUM_MACH_IRQS, 1, 7 },
{ "CMD", IRQ_INTCMD(0), IRQ_INTCMD_NUM, 1, 5 },
{ "DMA", IRQ_INTDMA(0), IRQ_INTDMA_NUM, 1, 2 },
{ "CSI", IRQ_INTCSI(0), IRQ_INTCSI_NUM, 4, 4 },
{ "SER", IRQ_INTSER(0), IRQ_INTSER_NUM, 4, 3 },
{ "SR", IRQ_INTSR(0), IRQ_INTSR_NUM, 4, 4 },
{ "ST", IRQ_INTST(0), IRQ_INTST_NUM, 4, 5 },
{ 0 }
};
#define NUM_IRQ_INITS ((sizeof irq_inits / sizeof irq_inits[0]) - 1)
static struct hw_interrupt_type hw_itypes[NUM_IRQ_INITS];
/* Initialize MA chip interrupts. */
void __init ma_init_irqs (void)
{
nb85e_intc_init_irq_types (irq_inits, hw_itypes);
}
/* Called before configuring an on-chip UART. */
void ma_uart_pre_configure (unsigned chan, unsigned cflags, unsigned baud)
{
/* We only know about the first two UART channels (though
specific chips may have more). */
if (chan < 2) {
unsigned bits = 0x3 << (chan * 3);
/* Specify that the relevent pins on the chip should do
serial I/O, not direct I/O. */
MA_PORT4_PMC |= bits;
/* Specify that we're using the UART, not the CSI device. */
MA_PORT4_PFC |= bits;
}
}
/*
* arch/v850/kernel/mach.c -- Defaults for some things defined by "mach.h"
*
* Copyright (C) 2001 NEC Corporation
* Copyright (C) 2001 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#include "mach.h"
/* Called with each timer tick, if non-zero. */
void (*mach_tick)(void) = 0;
/*
* arch/v850/kernel/mach.h -- Machine-dependent functions used by v850 port
*
* Copyright (C) 2001,02 NEC Corporation
* Copyright (C) 2001,02 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#ifndef __V850_MACH_H__
#define __V850_MACH_H__
#include <linux/kernel.h>
#include <linux/time.h>
#include <linux/spinlock.h>
#include <linux/interrupt.h>
#include <linux/fs.h>
#include <linux/seq_file.h>
#include <asm/ptrace.h>
#include <asm/entry.h>
#include <asm/clinkage.h>
void mach_setup (char **cmdline);
void mach_gettimeofday (struct timespec *tv);
void mach_sched_init (struct irqaction *timer_action);
void mach_get_physical_ram (unsigned long *ram_start, unsigned long *ram_len);
void mach_init_irqs (void);
/* If defined, is called very early in the kernel initialization. The
stack pointer is valid, but very little has been initialized (e.g.,
bss is not zeroed yet) when this is called, so care must taken. */
void mach_early_init (void);
/* If defined, called after the bootmem allocator has been initialized,
to allow the platform-dependent code to reserve any areas of RAM that
the kernel shouldn't touch. */
void mach_reserve_bootmem (void) __attribute__ ((__weak__));
/* Called with each timer tick, if non-zero. */
extern void (*mach_tick) (void);
/* The following establishes aliases for various mach_ functions to the
name by which the rest of the kernal calls them. These statements
should only have an effect in the file that defines the actual functions. */
#define MACH_ALIAS(to, from) \
asm (".global " macrology_stringify (C_SYMBOL_NAME (to)) ";" \
macrology_stringify (C_SYMBOL_NAME (to)) \
" = " macrology_stringify (C_SYMBOL_NAME (from)))
/* e.g.: MACH_ALIAS (kernel_name, arch_spec_name); */
#endif /* __V850_MACH_H__ */
/*
* arch/v850/kernel/memcons.c -- Console I/O to a memory buffer
*
* Copyright (C) 2001,02 NEC Corporation
* Copyright (C) 2001,02 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#include <linux/kernel.h>
#include <linux/console.h>
#include <linux/tty.h>
#include <linux/tty_driver.h>
#include <linux/init.h>
/* If this device is enabled, the linker map should define start and
end points for its buffer. */
extern char memcons_output[], memcons_output_end;
/* Current offset into the buffer. */
static unsigned long memcons_offs = 0;
/* Spinlock protecting memcons_offs. */
static spinlock_t memcons_lock = SPIN_LOCK_UNLOCKED;
static size_t write (const char *buf, size_t len)
{
int flags;
char *point;
spin_lock_irqsave (memcons_lock, flags);
point = memcons_output + memcons_offs;
if (point + len >= &memcons_output_end) {
len = &memcons_output_end - point;
memcons_offs = 0;
} else
memcons_offs += len;
spin_unlock_irqrestore (memcons_lock, flags);
memcpy (point, buf, len);
return len;
}
/* Low-level console. */
static void memcons_write (struct console *co, const char *buf, unsigned len)
{
while (len > 0)
len -= write (buf, len);
}
static kdev_t memcons_device (struct console *co)
{
return MKDEV (TTY_MAJOR, 64 + co->index);
}
static struct console memcons =
{
name: "memcons",
write: memcons_write,
device: memcons_device,
flags: CON_PRINTBUFFER,
index: -1,
};
void memcons_setup (void)
{
register_console (&memcons);
printk (KERN_INFO "Console: static memory buffer (memcons)\n");
}
/* Higher level TTY interface. */
static struct tty_struct *tty_table[1] = { 0 };
static struct termios *tty_termios[1] = { 0 };
static struct termios *tty_termios_locked[1] = { 0 };
static struct tty_driver tty_driver = { 0 };
static int tty_ref_count = 0;
int memcons_tty_open (struct tty_struct *tty, struct file *filp)
{
return 0;
}
int memcons_tty_write (struct tty_struct *tty, int from_user,
const unsigned char *buf, int len)
{
return write (buf, len);
}
int memcons_tty_write_room (struct tty_struct *tty)
{
return &memcons_output_end - (memcons_output + memcons_offs);
}
int memcons_tty_chars_in_buffer (struct tty_struct *tty)
{
/* We have no buffer. */
return 0;
}
int __init memcons_tty_init (void)
{
tty_driver.name = "memcons";
tty_driver.major = TTY_MAJOR;
tty_driver.minor_start = 64;
tty_driver.num = 1;
tty_driver.type = TTY_DRIVER_TYPE_SYSCONS;
tty_driver.refcount = &tty_ref_count;
tty_driver.table = tty_table;
tty_driver.termios = tty_termios;
tty_driver.termios_locked = tty_termios_locked;
tty_driver.init_termios = tty_std_termios;
tty_driver.open = memcons_tty_open;
tty_driver.write = memcons_tty_write;
tty_driver.write_room = memcons_tty_write_room;
tty_driver.chars_in_buffer = memcons_tty_chars_in_buffer;
tty_register_driver (&tty_driver);
}
__initcall (memcons_tty_init);
/*
* arch/v850/kernel/nb85e_intc.c -- NB85E cpu core interrupt controller (INTC)
*
* Copyright (C) 2001,02 NEC Corporation
* Copyright (C) 2001,02 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/irq.h>
#include <asm/nb85e_intc.h>
static void irq_nop (unsigned irq) { }
static unsigned nb85e_intc_irq_startup (unsigned irq)
{
nb85e_intc_clear_pending_irq (irq);
nb85e_intc_enable_irq (irq);
return 0;
}
/* Initialize HW_IRQ_TYPES for INTC-controlled irqs described in array
INITS (which is terminated by an entry with the name field == 0). */
void __init nb85e_intc_init_irq_types (struct nb85e_intc_irq_init *inits,
struct hw_interrupt_type *hw_irq_types)
{
struct nb85e_intc_irq_init *init;
for (init = inits; init->name; init++) {
int i;
struct hw_interrupt_type *hwit = hw_irq_types++;
hwit->typename = init->name;
hwit->startup = nb85e_intc_irq_startup;
hwit->shutdown = nb85e_intc_disable_irq;
hwit->enable = nb85e_intc_enable_irq;
hwit->disable = nb85e_intc_disable_irq;
hwit->ack = irq_nop;
hwit->end = irq_nop;
/* Initialize kernel IRQ infrastructure for this interrupt. */
init_irq_handlers(init->base, init->num, init->interval, hwit);
/* Set the interrupt priorities. */
for (i = 0; i < init->num; i++) {
unsigned irq = init->base + i * init->interval;
/* If the interrupt is currently enabled (all
interrupts are initially disabled), then
assume whoever enabled it has set things up
properly, and avoid messing with it. */
if (! nb85e_intc_irq_enabled (irq))
/* This write also (1) disables the
interrupt, and (2) clears any pending
interrupts. */
NB85E_INTC_IC (irq)
= (NB85E_INTC_IC_PR (init->priority)
| NB85E_INTC_IC_MK);
}
}
}
/*
* include/asm-v850/nb85e_timer_d.c -- `Timer D' component often used
* with the NB85E cpu core
*
* Copyright (C) 2001,02 NEC Corporation
* Copyright (C) 2001,02 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#include <linux/kernel.h>
#include <asm/nb85e_utils.h>
#include <asm/nb85e_timer_d.h>
/* Start interval timer TIMER (0-3). The timer will issue the
corresponding INTCMD interrupt RATE times per second.
This function does not enable the interrupt. */
void nb85e_timer_d_configure (unsigned timer, unsigned rate)
{
unsigned divlog2, count;
/* Calculate params for timer. */
if (! calc_counter_params (
NB85E_TIMER_D_BASE_FREQ, rate,
NB85E_TIMER_D_TMCD_CS_MIN, NB85E_TIMER_D_TMCD_CS_MAX, 16,
&divlog2, &count))
printk (KERN_WARNING
"Cannot find interval timer %d setting suitable"
" for rate of %dHz.\n"
"Using rate of %dHz instead.\n",
timer, rate,
(NB85E_TIMER_D_BASE_FREQ >> divlog2) >> 16);
/* Do the actual hardware timer initialization: */
/* Enable timer. */
NB85E_TIMER_D_TMCD(timer) = NB85E_TIMER_D_TMCD_CAE;
/* Set clock divider. */
NB85E_TIMER_D_TMCD(timer)
= NB85E_TIMER_D_TMCD_CAE
| NB85E_TIMER_D_TMCD_CS(divlog2);
/* Set timer compare register. */
NB85E_TIMER_D_CMD(timer) = count;
/* Start counting. */
NB85E_TIMER_D_TMCD(timer)
= NB85E_TIMER_D_TMCD_CAE
| NB85E_TIMER_D_TMCD_CS(divlog2)
| NB85E_TIMER_D_TMCD_CE;
}
/*
* include/asm-v850/nb85e_utils.h -- Utility functions associated with
* the NB85E cpu core
*
* Copyright (C) 2001 NEC Corporation
* Copyright (C) 2001 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
/* Note: these functions are often associated with the N85E cpu core,
but not always, which is why they're not in `nb85e.c'. */
#include <asm/nb85e_utils.h>
/* Calculate counter clock-divider and count values to attain the
desired frequency RATE from the base frequency BASE_FREQ. The
counter is expected to have a clock-divider, which can divide the
system cpu clock by a power of two value from MIN_DIVLOG2 to
MAX_DIV_LOG2, and a word-size of COUNTER_SIZE bits (the counter
counts up and resets whenever it's equal to the compare register,
generating an interrupt or whatever when it does so). The returned
values are: *DIVLOG2 -- log2 of the desired clock divider and *COUNT
-- the counter compare value to use. Returns true if it was possible
to find a reasonable value, otherwise false (and the other return
values will be set to be as good as possible). */
int calc_counter_params (unsigned long base_freq,
unsigned long rate,
unsigned min_divlog2, unsigned max_divlog2,
unsigned counter_size,
unsigned *divlog2, unsigned *count)
{
unsigned _divlog2;
int ok = 0;
/* Find the lowest clock divider setting that can represent RATE. */
for (_divlog2 = min_divlog2; _divlog2 <= max_divlog2; _divlog2++) {
/* Minimum interrupt rate possible using this divider. */
int min_int_rate
= (base_freq >> _divlog2) >> counter_size;
if (min_int_rate <= rate) {
/* This setting is the highest resolution
setting that's slow enough enough to attain
RATE interrupts per second, so use it. */
ok = 1;
break;
}
}
if (_divlog2 > max_divlog2)
/* Can't find correct setting. */
_divlog2 = max_divlog2;
if (divlog2)
*divlog2 = _divlog2;
if (count)
*count = ((base_freq >> _divlog2) + rate/2) / rate;
return ok;
}
/*
* arch/v850/kernel/process.c -- Arch-dependent process handling
*
* Copyright (C) 2001,02 NEC Corporation
* Copyright (C) 2001,02 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#include <linux/config.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/stddef.h>
#include <linux/unistd.h>
#include <linux/ptrace.h>
#include <linux/slab.h>
#include <linux/user.h>
#include <linux/a.out.h>
#include <linux/reboot.h>
#include <asm/uaccess.h>
#include <asm/system.h>
#include <asm/setup.h>
#include <asm/pgtable.h>
extern void ret_from_fork (void);
/* The idle loop. */
void default_idle (void)
{
while (1) {
while (! need_resched ())
asm ("halt; nop; nop; nop; nop; nop" ::: "cc");
schedule ();
}
}
void (*idle)(void) = default_idle;
/*
* The idle thread. There's no useful work to be
* done, so just try to conserve power and have a
* low exit latency (ie sit in a loop waiting for
* somebody to say that they'd like to reschedule)
*/
void cpu_idle (void)
{
/* endless idle loop with no priority at all */
(*idle) ();
}
struct spec_reg_name {
const char *name;
int gpr;
};
struct spec_reg_name spec_reg_names[] = {
{ "sp", GPR_SP },
{ "gp", GPR_GP },
{ "tp", GPR_TP },
{ "ep", GPR_EP },
{ "lp", GPR_LP },
{ 0, 0 }
};
void show_regs (struct pt_regs *regs)
{
int gpr_base, gpr_offs;
printk (" pc 0x%08lx psw 0x%08lx kernel_mode %d\n",
regs->pc, regs->psw, regs->kernel_mode);
printk (" ctpc 0x%08lx ctpsw 0x%08lx ctbp 0x%08lx\n",
regs->ctpc, regs->ctpsw, regs->ctbp);
for (gpr_base = 0; gpr_base < NUM_GPRS; gpr_base += 4) {
for (gpr_offs = 0; gpr_offs < 4; gpr_offs++) {
int gpr = gpr_base + gpr_offs;
long val = regs->gpr[gpr];
struct spec_reg_name *srn;
for (srn = spec_reg_names; srn->name; srn++)
if (srn->gpr == gpr)
break;
if (srn->name)
printk ("%7s 0x%08lx", srn->name, val);
else
printk (" r%02d 0x%08lx", gpr, val);
}
printk ("\n");
}
}
/*
* This is the mechanism for creating a new kernel thread.
*
* NOTE! Only a kernel-only process (ie the swapper or direct descendants who
* haven't done an "execve()") should use this: it will work within a system
* call from a "real" process, but the process memory space will not be free'd
* until both the parent and the child have exited.
*/
int kernel_thread (int (*fn)(void *), void *arg, unsigned long flags)
{
register mm_segment_t fs = get_fs ();
register unsigned long syscall asm (SYSCALL_NUM);
register unsigned long arg0 asm (SYSCALL_ARG0);
register unsigned long ret asm (SYSCALL_RET);
set_fs (KERNEL_DS);
/* Clone this thread. */
arg0 = flags | CLONE_VM;
syscall = __NR_clone;
asm volatile ("trap " SYSCALL_SHORT_TRAP
: "=r" (ret), "=r" (syscall)
: "1" (syscall), "r" (arg0)
: SYSCALL_SHORT_CLOBBERS);
if (ret == 0) {
/* In child thread, call FN and exit. */
arg0 = (*fn) (arg);
syscall = __NR_exit;
asm volatile ("trap " SYSCALL_SHORT_TRAP
: "=r" (ret), "=r" (syscall)
: "1" (syscall), "r" (arg0)
: SYSCALL_SHORT_CLOBBERS);
}
/* In parent. */
set_fs (fs);
return ret;
}
void flush_thread (void)
{
set_fs (USER_DS);
}
int copy_thread (int nr, unsigned long clone_flags,
unsigned long stack_start, unsigned long stack_size,
struct task_struct *p, struct pt_regs *regs)
{
/* Start pushing stuff from the top of the child's kernel stack. */
unsigned long ksp = (unsigned long)p->thread_info + THREAD_SIZE;
/* We push two `state save' stack fames (see entry.S) on the new
kernel stack:
1) The innermost one is what switch_thread would have
pushed, and is used when we context switch to the child
thread for the first time. It's set up to return to
ret_from_fork in entry.S.
2) The outermost one (nearest the top) is what a syscall
trap would have pushed, and is set up to return to the
same location as the parent thread, but with a return
value of 0. */
struct pt_regs *child_switch_regs, *child_trap_regs;
/* Trap frame. */
ksp -= STATE_SAVE_SIZE;
child_trap_regs = (struct pt_regs *)(ksp + STATE_SAVE_PT_OFFSET);
/* Switch frame. */
ksp -= STATE_SAVE_SIZE;
child_switch_regs = (struct pt_regs *)(ksp + STATE_SAVE_PT_OFFSET);
/* First copy parent's register state to child. */
*child_switch_regs = *regs;
*child_trap_regs = *regs;
/* switch_thread returns to the restored value of the lp
register (r31), so we make that the place where we want to
jump when the child thread begins running. */
child_switch_regs->gpr[GPR_LP] = (v850_reg_t)ret_from_fork;
/* Thread state for the child (everything else is on the stack). */
p->thread.ksp = ksp;
return 0;
}
/*
* fill in the user structure for a core dump..
*/
void dump_thread (struct pt_regs *regs, struct user *dump)
{
#if 0 /* Later. XXX */
dump->magic = CMAGIC;
dump->start_code = 0;
dump->start_stack = regs->gpr[GPR_SP];
dump->u_tsize = ((unsigned long) current->mm->end_code) >> PAGE_SHIFT;
dump->u_dsize = ((unsigned long) (current->mm->brk +
(PAGE_SIZE-1))) >> PAGE_SHIFT;
dump->u_dsize -= dump->u_tsize;
dump->u_ssize = 0;
if (dump->start_stack < TASK_SIZE)
dump->u_ssize = ((unsigned long) (TASK_SIZE - dump->start_stack)) >> PAGE_SHIFT;
dump->u_ar0 = (struct user_regs_struct *)((int)&dump->regs - (int)dump);
dump->regs = *regs;
dump->u_fpvalid = 0;
#endif
}
/*
* sys_execve() executes a new program.
*/
int sys_execve (char *name, char **argv, char **envp, struct pt_regs *regs)
{
char *filename = getname (name);
int error = PTR_ERR (filename);
if (! IS_ERR (filename)) {
error = do_execve (filename, argv, envp, regs);
putname (filename);
}
return error;
}
/* This is the common part of the various fork-like system calls (which
are in entry.S). */
int fork_common (int flags, unsigned long new_sp, struct pt_regs *regs)
{
struct task_struct *p = do_fork (flags, new_sp, regs, 0, 0);
return IS_ERR (p) ? PTR_ERR (p) : p->pid;
}
/*
* These bracket the sleeping functions..
*/
extern void scheduling_functions_start_here (void);
extern void scheduling_functions_end_here (void);
#define first_sched ((unsigned long) scheduling_functions_start_here)
#define last_sched ((unsigned long) scheduling_functions_end_here)
unsigned long get_wchan (struct task_struct *p)
{
#if 0 /* Barf. Figure out the stack-layout later. XXX */
unsigned long fp, pc;
int count = 0;
if (!p || p == current || p->state == TASK_RUNNING)
return 0;
pc = thread_saved_pc (&p->thread);
/* This quite disgusting function walks up the stack, following
saved return address, until it something that's out of bounds
(as defined by `first_sched' and `last_sched'). It then
returns the last PC that was in-bounds. */
do {
if (fp < stack_page + sizeof (struct task_struct) ||
fp >= 8184+stack_page)
return 0;
pc = ((unsigned long *)fp)[1];
/* FIXME: This depends on the order of these functions. */
if (pc < first_sched || pc >= last_sched)
return pc;
fp = *(unsigned long *) fp;
} while (count++ < 16);
#endif
return 0;
}
void show_trace_task (struct task_struct *t)
{
/* blarg XXX */
printk ("show_trace_task: KSP = 0x%lx, USP = 0x%lx, UPC = 0x%lx\n",
t->thread.ksp, KSTK_ESP (t), KSTK_EIP (t));
}
/*
* arch/v850/kernel/procfs.c -- Introspection functions for /proc filesystem
*
* Copyright (C) 2001,02 NEC Corporation
* Copyright (C) 2001,02 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#include "mach.h"
static int cpuinfo_print (struct seq_file *m, void *v)
{
extern unsigned long loops_per_jiffy;
seq_printf (m, "CPU-Family: v850\nCPU-Arch: %s\n", CPU_ARCH);
#ifdef CPU_MODEL_LONG
seq_printf (m, "CPU-Model: %s (%s)\n", CPU_MODEL, CPU_MODEL_LONG);
#else
seq_printf (m, "CPU-Model: %s\n", CPU_MODEL);
#endif
#ifdef CPU_CLOCK_FREQ
seq_printf (m, "CPU-Clock: %ld (%ld MHz)\n",
(long)CPU_CLOCK_FREQ,
(long)CPU_CLOCK_FREQ / 1000000);
#endif
seq_printf (m, "BogoMips: %lu.%02lu\n",
loops_per_jiffy/(500000/HZ),
(loops_per_jiffy/(5000/HZ)) % 100);
#ifdef PLATFORM_LONG
seq_printf (m, "Platform: %s (%s)\n", PLATFORM, PLATFORM_LONG);
#elif defined (PLATFORM)
seq_printf (m, "Platform: %s\n", PLATFORM);
#endif
return 0;
}
static void *cpuinfo_start (struct seq_file *m, loff_t *pos)
{
return *pos < NR_CPUS ? ((void *) 0x12345678) : NULL;
}
static void *cpuinfo_next (struct seq_file *m, void *v, loff_t *pos)
{
++*pos;
return cpuinfo_start (m, pos);
}
static void cpuinfo_stop (struct seq_file *m, void *v)
{
}
struct seq_operations cpuinfo_op = {
start: cpuinfo_start,
next: cpuinfo_next,
stop: cpuinfo_stop,
show: cpuinfo_print
};
/*
* arch/v850/kernel/ptrace.c -- `ptrace' system call
*
* Copyright (C) 2002 NEC Corporation
* Copyright (C) 2002 Miles Bader <miles@gnu.org>
*
* Derived from arch/mips/kernel/ptrace.c:
*
* Copyright (C) 1992 Ross Biro
* Copyright (C) Linus Torvalds
* Copyright (C) 1994, 95, 96, 97, 98, 2000 Ralf Baechle
* Copyright (C) 1996 David S. Miller
* Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
* Copyright (C) 1999 MIPS Technologies, Inc.
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*/
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/smp_lock.h>
#include <linux/ptrace.h>
#include <asm/errno.h>
#include <asm/ptrace.h>
#include <asm/processor.h>
#include <asm/uaccess.h>
int sys_ptrace(long request, long pid, long addr, long data)
{
struct task_struct *child;
int rval;
lock_kernel();
#if 0
printk("ptrace(r=%d,pid=%d,addr=%08lx,data=%08lx)\n",
(int) request, (int) pid, (unsigned long) addr,
(unsigned long) data);
#endif
if (request == PTRACE_TRACEME) {
/* are we already being traced? */
if (current->ptrace & PT_PTRACED) {
rval = -EPERM;
goto out;
}
/* set the ptrace bit in the process flags. */
current->ptrace |= PT_PTRACED;
rval = 0;
goto out;
}
rval = -ESRCH;
read_lock(&tasklist_lock);
child = find_task_by_pid(pid);
if (child)
get_task_struct(child);
read_unlock(&tasklist_lock);
if (!child)
goto out;
rval = -EPERM;
if (pid == 1) /* you may not mess with init */
goto out;
if (request == PTRACE_ATTACH) {
rval = ptrace_attach(child);
goto out_tsk;
}
rval = -ESRCH;
if (!(child->ptrace & PT_PTRACED))
goto out_tsk;
if (child->state != TASK_STOPPED) {
if (request != PTRACE_KILL)
goto out_tsk;
}
if (child->parent != current)
goto out_tsk;
switch (request) {
case PTRACE_PEEKTEXT: /* read word at location addr. */
case PTRACE_PEEKDATA:{
unsigned long tmp;
int copied;
copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
rval = -EIO;
if (copied != sizeof(tmp))
break;
rval = put_user(tmp,(unsigned long *) data);
goto out;
}
/* Read the word at location addr in the USER area. */
case PTRACE_PEEKUSR:
if (addr >= 0 && addr < PT_SIZE && (addr & 0x3) == 0) {
struct pt_regs *regs = task_regs (child);
unsigned long val =
*(unsigned long *)((char *)regs + addr);
rval = put_user (val, (unsigned long *)data);
} else {
rval = 0;
rval = -EIO;
}
goto out;
case PTRACE_POKETEXT: /* write the word at location addr. */
case PTRACE_POKEDATA:
rval = 0;
if (access_process_vm(child, addr, &data, sizeof(data), 1)
== sizeof(data))
break;
rval = -EIO;
goto out;
case PTRACE_POKEUSR:
if (addr >= 0 && addr < PT_SIZE && (addr & 0x3) == 0) {
struct pt_regs *regs = task_regs (child);
unsigned long *loc =
(unsigned long *)((char *)regs + addr);
*loc = data;
} else {
rval = 0;
rval = -EIO;
}
goto out;
case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
case PTRACE_CONT: /* rvaltart after signal. */
rval = -EIO;
if ((unsigned long) data > _NSIG)
break;
if (request == PTRACE_SYSCALL)
set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
else
clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
child->exit_code = data;
wake_up_process(child);
rval = 0;
break;
/*
* make the child exit. Best I can do is send it a sigkill.
* perhaps it should be put in the status that it wants to
* exit.
*/
case PTRACE_KILL:
rval = 0;
if (child->state == TASK_ZOMBIE) /* already dead */
break;
child->exit_code = SIGKILL;
wake_up_process(child);
break;
case PTRACE_DETACH: /* detach a process that was attached. */
rval = ptrace_detach(child, data);
break;
default:
rval = -EIO;
goto out;
}
out_tsk:
put_task_struct(child);
out:
unlock_kernel();
return rval;
}
asmlinkage void syscall_trace(void)
{
if (!test_thread_flag(TIF_SYSCALL_TRACE))
return;
if (!(current->ptrace & PT_PTRACED))
return;
/* The 0x80 provides a way for the tracing parent to distinguish
between a syscall stop and SIGTRAP delivery */
current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
? 0x80 : 0);
current->state = TASK_STOPPED;
notify_parent(current, SIGCHLD);
schedule();
/*
* this isn't the same as continuing with a signal, but it will do
* for normal use. strace only continues with a signal if the
* stopping signal is not SIGTRAP. -brl
*/
if (current->exit_code) {
send_sig(current->exit_code, current, 1);
current->exit_code = 0;
}
}
void ptrace_disable (struct task_struct *child)
{
/* nothing to do */
}
/*
* include/asm-v850/rte_cb.c -- Midas lab RTE-CB series of evaluation boards
*
* Copyright (C) 2001,02 NEC Corporation
* Copyright (C) 2001,02 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#include <linux/config.h>
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/fs.h>
#include <asm/machdep.h>
#include <asm/nb85e_uart.h>
#include "mach.h"
static void led_tick (void);
/* LED access routines. */
extern unsigned read_leds (int pos, char *buf, int len);
extern unsigned write_leds (int pos, const char *buf, int len);
#ifdef CONFIG_RTE_CB_MULTI
extern void multi_init (void);
#endif
#ifdef CONFIG_ROM_KERNEL
/* Initialization for kernel in ROM. */
static inline rom_kernel_init (void)
{
/* If the kernel is in ROM, we have to copy any initialized data
from ROM into RAM. */
extern unsigned long _data_load_start, _sdata, _edata;
register unsigned long *src = &_data_load_start;
register unsigned long *dst = &_sdata, *end = &_edata;
while (dst != end)
*dst++ = *src++;
}
#endif /* CONFIG_ROM_KERNEL */
void __init mach_early_init (void)
{
nb85e_intc_disable_irqs ();
#if defined (CONFIG_ROM_KERNEL)
rom_kernel_init ();
#elif defined (CONFIG_RTE_CB_MULTI)
multi_init ();
#endif
}
void __init mach_setup (char **cmdline)
{
printk (KERN_INFO
"CPU: %s\n"
"Platform: %s%s\n",
CPU_MODEL_LONG,
PLATFORM_LONG,
#ifdef CONFIG_ROM_KERNEL
""
#elif defined (CONFIG_RTE_CB_MULTI)
" (with Multi ROM monitor)"
#else
" (with ROM monitor)"
#endif
);
/* Probe for Mother-A, and print a message if we find it. */
*(volatile long *)MB_A_SRAM_ADDR = 0xDEADBEEF;
if (*(volatile long *)MB_A_SRAM_ADDR == 0xDEADBEEF) {
*(volatile long *)MB_A_SRAM_ADDR = 0x12345678;
if (*(volatile long *)MB_A_SRAM_ADDR == 0x12345678)
printk (KERN_INFO
" NEC SolutionGear/Midas lab"
" RTE-MOTHER-A motherboard\n");
}
#if defined (CONFIG_V850E_NB85E_UART_CONSOLE) && !defined (CONFIG_TIME_BOOTUP)
nb85e_uart_cons_init (0);
#endif
mach_tick = led_tick;
}
#ifdef CONFIG_TIME_BOOTUP
void initial_boot_done (void)
{
#ifdef CONFIG_V850E_NB85E_UART_CONSOLE
nb85e_uart_cons_init (0);
#endif
}
#endif
void machine_restart (char *__unused)
{
#ifdef CONFIG_RESET_GUARD
disable_reset_guard ();
#endif
asm ("jmp r0"); /* Jump to the reset vector. */
}
/* This says `HALt.' in LEDese. */
static unsigned char halt_leds_msg[] = { 0x76, 0x77, 0x38, 0xF8 };
void machine_halt (void)
{
#ifdef CONFIG_RESET_GUARD
disable_reset_guard ();
#endif
/* Ignore all interrupts. */
local_irq_disable ();
/* Write a little message. */
write_leds (0, halt_leds_msg, sizeof halt_leds_msg);
/* Really halt. */
for (;;)
asm ("halt; nop; nop; nop; nop; nop");
}
void machine_power_off (void)
{
machine_halt ();
}
/* Animated LED display for timer tick. */
#define TICK_UPD_FREQ 6
static int tick_frames[][10] = {
{ 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, -1 },
{ 0x63, 0x5c, -1 },
{ 0x5c, 0x00, -1 },
{ 0x63, 0x00, -1 },
{ -1 }
};
static void led_tick ()
{
static unsigned counter = 0;
if (++counter == (HZ / TICK_UPD_FREQ)) {
/* Which frame we're currently displaying for each digit. */
static unsigned frame_nums[LED_NUM_DIGITS] = { 0 };
/* Display image. */
static unsigned char image[LED_NUM_DIGITS] = { 0 };
unsigned char prev_image[LED_NUM_DIGITS];
int write_to_leds = 1; /* true if we should actually display */
int digit;
/* We check to see if the physical LEDs contains what we last
wrote to them; if not, we suppress display (this is so that
users can write to the LEDs, and not have their output
overwritten). As a special case, we start writing again if
all the LEDs are blank, or our display image is all zeros
(indicating that this is the initial update, when the actual
LEDs might contain random data). */
read_leds (0, prev_image, LED_NUM_DIGITS);
for (digit = 0; digit < LED_NUM_DIGITS; digit++)
if (image[digit] != prev_image[digit]
&& image[digit] && prev_image[digit])
{
write_to_leds = 0;
break;
}
/* Update display image. */
for (digit = 0;
digit < LED_NUM_DIGITS && tick_frames[digit][0] >= 0;
digit++)
{
int frame = tick_frames[digit][frame_nums[digit]];
if (frame < 0) {
image[digit] = tick_frames[digit][0];
frame_nums[digit] = 1;
} else {
image[digit] = frame;
frame_nums[digit]++;
break;
}
}
if (write_to_leds)
/* Write the display image to the physical LEDs. */
write_leds (0, image, LED_NUM_DIGITS);
counter = 0;
}
}
/* Mother-A interrupts. */
#ifdef CONFIG_RTE_GBUS_INT
#define L GBUS_INT_PRIORITY_LOW
#define M GBUS_INT_PRIORITY_MEDIUM
#define H GBUS_INT_PRIORITY_HIGH
static struct gbus_int_irq_init gbus_irq_inits[] = {
#ifdef CONFIG_RTE_MB_A_PCI
{ "MB_A_LAN", IRQ_MB_A_LAN, 1, 1, L },
{ "MB_A_PCI1", IRQ_MB_A_PCI1(0), IRQ_MB_A_PCI1_NUM, 1, L },
{ "MB_A_PCI2", IRQ_MB_A_PCI2(0), IRQ_MB_A_PCI2_NUM, 1, L },
{ "MB_A_EXT", IRQ_MB_A_EXT(0), IRQ_MB_A_EXT_NUM, 1, L },
{ "MB_A_USB_OC",IRQ_MB_A_USB_OC(0), IRQ_MB_A_USB_OC_NUM, 1, L },
{ "MB_A_PCMCIA_OC",IRQ_MB_A_PCMCIA_OC, 1, 1, L },
#endif
{ 0 }
};
#define NUM_GBUS_IRQ_INITS \
((sizeof gbus_irq_inits / sizeof gbus_irq_inits[0]) - 1)
static struct hw_interrupt_type gbus_hw_itypes[NUM_GBUS_IRQ_INITS];
#endif /* CONFIG_RTE_GBUS_INT */
void __init rte_cb_init_irqs (void)
{
#ifdef CONFIG_RTE_GBUS_INT
gbus_int_init_irqs ();
gbus_int_init_irq_types (gbus_irq_inits, gbus_hw_itypes);
#endif /* CONFIG_RTE_GBUS_INT */
}
/*
* include/asm-v850/rte_cb_leds.c -- Midas lab RTE-CB board LED device support
*
* Copyright (C) 2002 NEC Corporation
* Copyright (C) 2002 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#include <linux/config.h>
#include <linux/init.h>
#include <linux/spinlock.h>
#include <linux/miscdevice.h>
#include <asm/uaccess.h>
#define LEDS_MINOR 169 /* Minor device number, using misc major. */
/* The actual LED hardware is write-only, so we hold the contents here too. */
static unsigned char leds_image[LED_NUM_DIGITS] = { 0 };
/* Spinlock protecting the above leds. */
static spinlock_t leds_lock = SPIN_LOCK_UNLOCKED;
/* Common body of LED read/write functions, checks POS and LEN for
correctness, declares a variable using IMG_DECL, initialized pointing at
the POS position in the LED image buffer, and and iterates COPY_EXPR
until BUF is equal to the last buffer position; finally, sets LEN to be
the amount actually copied. IMG should be a variable declaration
(without an initializer or a terminating semicolon); POS, BUF, and LEN
should all be simple variables. */
#define DO_LED_COPY(img_decl, pos, buf, len, copy_expr) \
do { \
if (pos > LED_NUM_DIGITS) \
len = 0; \
else { \
if (pos + len > LED_NUM_DIGITS) \
len = LED_NUM_DIGITS - pos; \
\
if (len > 0) { \
int _flags; \
const char *_end = buf + len; \
img_decl = &leds_image[pos]; \
\
spin_lock_irqsave (leds_lock, _flags); \
do \
(copy_expr); \
while (buf != _end); \
spin_unlock_irqrestore (leds_lock, _flags); \
} \
} \
} while (0)
/* Read LEN bytes from LEDs at position POS, into BUF.
Returns actual amount read. */
unsigned read_leds (unsigned pos, char *buf, unsigned len)
{
DO_LED_COPY (const char *img, pos, buf, len, *buf++ = *img++);
return len;
}
/* Write LEN bytes to LEDs at position POS, from BUF.
Returns actual amount written. */
unsigned write_leds (unsigned pos, const char *buf, unsigned len)
{
/* We write the actual LED values backwards, because
increasing memory addresses reflect LEDs right-to-left. */
volatile char *led = &LED (LED_NUM_DIGITS - pos - 1);
/* We invert the value written to the hardware, because 1 = off,
and 0 = on. */
DO_LED_COPY (char *img, pos, buf, len,
*led-- = 0xFF ^ (*img++ = *buf++));
return len;
}
/* Device functions. */
static ssize_t leds_dev_read (struct file *file, char *buf, size_t len,
loff_t *pos)
{
char temp_buf[LED_NUM_DIGITS];
len = read_leds (*pos, temp_buf, len);
if (copy_to_user (buf, temp_buf, len))
return -EFAULT;
*pos += len;
return len;
}
static ssize_t leds_dev_write (struct file *file, const char *buf, size_t len,
loff_t *pos)
{
char temp_buf[LED_NUM_DIGITS];
if (copy_from_user (temp_buf, buf, min_t(size_t, len, LED_NUM_DIGITS)))
return -EFAULT;
len = write_leds (*pos, temp_buf, len);
*pos += len;
return len;
}
static loff_t leds_dev_lseek (struct file *file, loff_t offs, int whence)
{
if (whence == 1)
offs += file->f_pos; /* relative */
else if (whence == 2)
offs += LED_NUM_DIGITS; /* end-relative */
if (offs >= 0 && offs <= LED_NUM_DIGITS)
file->f_pos = offs;
else
return -EINVAL;
}
static struct file_operations leds_fops = {
read: leds_dev_read,
write: leds_dev_write,
llseek: leds_dev_lseek
};
static struct miscdevice leds_miscdev = {
name: "leds",
minor: LEDS_MINOR,
fops: &leds_fops
};
int __init leds_dev_init (void)
{
return misc_register (&leds_miscdev);
}
__initcall (leds_dev_init);
/*
* include/asm-v850/rte_multi.c -- Support for Multi debugger monitor ROM
* on Midas lab RTE-CB series of evaluation boards
*
* Copyright (C) 2001,02 NEC Corporation
* Copyright (C) 2001,02 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#include <linux/init.h>
#include <asm/machdep.h>
/* A table of which interrupt vectors to install, since blindly
installing all of them makes the debugger stop working. This is a
list of offsets in the interrupt vector area; each entry means to
copy that particular 16-byte vector. An entry less than zero ends
the table. */
static long multi_intv_install_table[] = {
0x40, 0x50, /* trap vectors */
/* Note -- illegal insn trap is used by the debugger. */
0xD0, 0xE0, 0xF0, /* GINT1 - GINT3 */
0x240, 0x250, 0x260, 0x270, /* timer D interrupts */
0x2D0, 0x2E0, 0x2F0, /* UART channel 0 */
0x310, 0x320, 0x330, /* UART channel 1 */
0x350, 0x360, 0x370, /* UART channel 2 */
-1
};
/* Early initialization for kernel using Multi debugger ROM monitor. */
void __init multi_init (void)
{
/* We're using the Multi debugger monitor, so we have to install
the interrupt vectors. The monitor doesn't allow them to be
initially downloaded into their final destination because
it's in the monitor's scratch-RAM area. Unfortunately, Multi
also doesn't deal correctly with ELF sections where the LMA
and VMA differ -- it just ignores the LMA -- so we can't use
that feature to work around the problem. What we do instead
is just put the interrupt vectors into a normal section, and
do the necessary copying and relocation here. Since the
interrupt vector basically only contains `jr' instructions
and no-ops, it's not that hard. */
extern unsigned long _intv_load_start, _intv_start;
register unsigned long *src = &_intv_load_start;
register unsigned long *dst = (unsigned long *)INTV_BASE;
register unsigned long jr_fixup = (char *)&_intv_start - (char *)dst;
register long *ii;
/* Copy interupt vectors as instructed by multi_intv_install_table. */
for (ii = multi_intv_install_table; *ii >= 0; ii++) {
/* Copy 16-byte interrupt vector at offset *ii. */
int boffs;
for (boffs = 0; boffs < 0x10; boffs += sizeof *src) {
/* Copy a single word, fixing up the jump offs
if it's a `jr' instruction. */
int woffs = (*ii + boffs) / sizeof *src;
unsigned long word = src[woffs];
if ((word & 0xFC0) == 0x780) {
/* A `jr' insn, fix up its offset (and yes, the
wierd half-word swapping is intentional). */
unsigned short hi = word & 0xFFFF;
unsigned short lo = word >> 16;
unsigned long udisp22
= lo + ((hi & 0x3F) << 16);
long disp22 = (long)(udisp22 << 10) >> 10;
disp22 += jr_fixup;
hi = ((disp22 >> 16) & 0x3F) | 0x780;
lo = disp22 & 0xFFFF;
word = hi + (lo << 16);
}
dst[woffs] = word;
}
}
}
/*
* arch/v850/kernel/rte_ma1_cb.c -- Midas labs RTE-V850E/MA1-CB board
*
* Copyright (C) 2001,02 NEC Corporation
* Copyright (C) 2001,02 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/bootmem.h>
#include <asm/atomic.h>
#include <asm/page.h>
#include <asm/ma1.h>
#include <asm/rte_ma1_cb.h>
#include <asm/nb85e_timer_c.h>
#include "mach.h"
/* SRAM and SDRAM are almost contiguous (with a small hole in between;
see mach_reserve_bootmem for details), so just use both as one big area. */
#define RAM_START SRAM_ADDR
#define RAM_END (SDRAM_ADDR + SDRAM_SIZE)
void __init mach_get_physical_ram (unsigned long *ram_start,
unsigned long *ram_len)
{
*ram_start = RAM_START;
*ram_len = RAM_END - RAM_START;
}
void __init mach_reserve_bootmem ()
{
#ifdef CONFIG_RTE_CB_MULTI
/* Prevent the kernel from touching the monitor's scratch RAM. */
reserve_bootmem (MON_SCRATCH_ADDR, MON_SCRATCH_SIZE);
#endif
/* The space between SRAM and SDRAM is filled with duplicate
images of SRAM. Prevent the kernel from using them. */
reserve_bootmem (SRAM_ADDR + SRAM_SIZE,
SDRAM_ADDR - (SRAM_ADDR + SRAM_SIZE));
}
void mach_gettimeofday (struct timespec *tv)
{
tv->tv_sec = 0;
tv->tv_nsec = 0;
}
/* Called before configuring an on-chip UART. */
void rte_ma1_cb_uart_pre_configure (unsigned chan,
unsigned cflags, unsigned baud)
{
/* The RTE-MA1-CB connects some general-purpose I/O pins on the
CPU to the RTS/CTS lines of UART 0's serial connection.
I/O pins P42 and P43 are RTS and CTS respectively. */
if (chan == 0) {
/* Put P42 & P43 in I/O port mode. */
MA_PORT4_PMC &= ~0xC;
/* Make P42 and output, and P43 an input. */
MA_PORT4_PM = (MA_PORT4_PM & ~0xC) | 0x8;
}
/* Do pre-configuration for the actual UART. */
ma_uart_pre_configure (chan, cflags, baud);
}
void __init mach_init_irqs (void)
{
unsigned tc;
/* Initialize interrupts. */
ma_init_irqs ();
rte_cb_init_irqs ();
/* Use falling-edge-sensitivity for interrupts . */
NB85E_TIMER_C_SESC (0) &= ~0xC;
NB85E_TIMER_C_SESC (1) &= ~0xF;
/* INTP000-INTP011 are shared with `Timer C', so we have to set
up Timer C to pass them through as raw interrupts. */
for (tc = 0; tc < 2; tc++)
/* Turn on the timer. */
NB85E_TIMER_C_TMCC0 (tc) |= NB85E_TIMER_C_TMCC0_CAE;
/* Make sure the relevent port0/port1 pins are assigned
interrupt duty. We used INTP001-INTP011 (don't screw with
INTP000 because the monitor uses it). */
MA_PORT0_PMC |= 0x4; /* P02 (INTP001) in IRQ mode. */
MA_PORT1_PMC |= 0x6; /* P11 (INTP010) & P12 (INTP011) in IRQ mode.*/
}
/*
* arch/v850/kernel/mb_a_pci.c -- PCI support for Midas lab RTE-MOTHER-A board
*
* Copyright (C) 2001,02 NEC Corporation
* Copyright (C) 2001,02 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/pci.h>
#include <asm/machdep.h>
/* __nomods_init is like __devinit, but is a no-op when modules are enabled.
This is used by some routines that can be called either during boot
or by a module. */
#ifdef CONFIG_MODULES
#define __nomods_init /*nothing*/
#else
#define __nomods_init __devinit
#endif
/* PCI devices on the Mother-A board can only do DMA to/from the MB SRAM
(the RTE-V850E/MA1-CB cpu board doesn't support PCI access to
CPU-board memory), and since linux DMA buffers are allocated in
normal kernel memory, we basically have to copy DMA blocks around
(this is like a `bounce buffer'). When a DMA block is `mapped', we
allocate an identically sized block in MB SRAM, and if we're doing
output to the device, copy the CPU-memory block to the MB-SRAM block.
When an active block is `unmapped', we will copy the block back to
CPU memory if necessary, and then deallocate the MB SRAM block.
Ack. */
/* Where the motherboard SRAM is in the PCI-bus address space (the
first 512K of it is also mapped at PCI address 0). */
#define PCI_MB_SRAM_ADDR 0x800000
/* Convert CPU-view MB SRAM address to/from PCI-view addresses of the
same memory. */
#define MB_SRAM_TO_PCI(mb_sram_addr) \
((dma_addr_t)mb_sram_addr - MB_A_SRAM_ADDR + PCI_MB_SRAM_ADDR)
#define PCI_TO_MB_SRAM(pci_addr) \
(void *)(pci_addr - PCI_MB_SRAM_ADDR + MB_A_SRAM_ADDR)
static void pcibios_assign_resources (void);
struct mb_pci_dev_irq {
unsigned dev; /* PCI device number */
unsigned irq_base; /* First IRQ */
unsigned query_pin; /* True if we should read the device's
Interrupt Pin info, and allocate
interrupt IRQ_BASE + PIN. */
};
/* PCI interrupts are mapped statically to GBUS interrupts. */
static struct mb_pci_dev_irq mb_pci_dev_irqs[] = {
/* Motherboard SB82558 ethernet controller */
{ 10, IRQ_MB_A_LAN, 0 },
/* PCI slot 1 */
{ 8, IRQ_MB_A_PCI1(0), 1 },
/* PCI slot 2 */
{ 9, IRQ_MB_A_PCI2(0), 1 }
};
#define NUM_MB_PCI_DEV_IRQS \
(sizeof mb_pci_dev_irqs / sizeof mb_pci_dev_irqs[0])
/* PCI configuration primitives. */
#define CONFIG_DMCFGA(bus, devfn, offs) \
(0x80000000 \
| ((offs) & ~0x3) \
| ((devfn) << 8) \
| ((bus)->number << 16))
static int
mb_pci_read (struct pci_bus *bus, unsigned devfn, int offs, int size, u32 *rval)
{
u32 addr;
int flags;
local_irq_save (flags);
MB_A_PCI_PCICR = 0x7;
MB_A_PCI_DMCFGA = CONFIG_DMCFGA (bus, devfn, offs);
addr = MB_A_PCI_IO_ADDR + (offs & 0x3);
switch (size) {
case 1: *rval = *(volatile u8 *)addr; break;
case 2: *rval = *(volatile u16 *)addr; break;
case 4: *rval = *(volatile u32 *)addr; break;
}
if (MB_A_PCI_PCISR & 0x2000) {
MB_A_PCI_PCISR = 0x2000;
*rval = ~0;
}
MB_A_PCI_DMCFGA = 0;
local_irq_restore (flags);
return PCIBIOS_SUCCESSFUL;
}
static int
mb_pci_write (struct pci_bus *bus, unsigned devfn, int offs, int size, u32 val)
{
u32 addr;
int flags;
local_irq_save (flags);
MB_A_PCI_PCICR = 0x7;
MB_A_PCI_DMCFGA = CONFIG_DMCFGA (bus, devfn, offs);
addr = MB_A_PCI_IO_ADDR + (offs & 0x3);
switch (size) {
case 1: *(volatile u8 *)addr = val; break;
case 2: *(volatile u16 *)addr = val; break;
case 4: *(volatile u32 *)addr = val; break;
}
if (MB_A_PCI_PCISR & 0x2000)
MB_A_PCI_PCISR = 0x2000;
MB_A_PCI_DMCFGA = 0;
local_irq_restore (flags);
return PCIBIOS_SUCCESSFUL;
}
static struct pci_ops mb_pci_config_ops = {
.read = mb_pci_read,
.write = mb_pci_write,
};
/* PCI Initialization. */
static struct pci_bus *mb_pci_bus = 0;
/* Do initial PCI setup. */
static int __devinit pcibios_init (void)
{
u32 id = MB_A_PCI_PCIHIDR;
u16 vendor = id & 0xFFFF;
u16 device = (id >> 16) & 0xFFFF;
if (vendor == PCI_VENDOR_ID_PLX && device == PCI_DEVICE_ID_PLX_9080) {
printk (KERN_INFO
"PCI: PLX Technology PCI9080 HOST/PCI bridge\n");
MB_A_PCI_PCICR = 0x147;
MB_A_PCI_DMLBAM = 0x0;
MB_A_PCI_PCIBAR0 = 0x007FFF00;
MB_A_PCI_PCIBAR1 = 0x0000FF00;
MB_A_PCI_PCIBAR2 = 0x00800000;
MB_A_PCI_PCILTR = 0x20;
MB_A_PCI_PCIPBAM |= 0x3;
MB_A_PCI_PCISR = ~0; /* Clear errors. */
/* Reprogram the motherboard's IO/config address space,
as we don't support the GCS7 address space that the
default uses. Note that we have to give the address
from the motherboard's point of view, which is
different than the CPU's. */
MB_A_PCI_DMLBAI = MB_A_PCI_IO_ADDR - GCS5_ADDR;
MB_A_PCI_DMRR = ~(MB_A_PCI_MEM_SIZE - 1);
mb_pci_bus = pci_scan_bus (0, &mb_pci_config_ops, 0);
pcibios_assign_resources ();
} else
printk (KERN_ERR "PCI: HOST/PCI bridge not found\n");
return 0;
}
subsys_initcall (pcibios_init);
char __devinit *pcibios_setup (char *option)
{
/* Don't handle any options. */
return option;
}
int __nomods_init pcibios_enable_device (struct pci_dev *dev, int mask)
{
u16 cmd, old_cmd;
int idx;
struct resource *r;
pci_read_config_word(dev, PCI_COMMAND, &cmd);
old_cmd = cmd;
for (idx = 0; idx < 6; idx++) {
r = &dev->resource[idx];
if (!r->start && r->end) {
printk(KERN_ERR "PCI: Device %s not available because "
"of resource collisions\n", dev->slot_name);
return -EINVAL;
}
if (r->flags & IORESOURCE_IO)
cmd |= PCI_COMMAND_IO;
if (r->flags & IORESOURCE_MEM)
cmd |= PCI_COMMAND_MEMORY;
}
if (cmd != old_cmd) {
printk("PCI: Enabling device %s (%04x -> %04x)\n",
dev->slot_name, old_cmd, cmd);
pci_write_config_word(dev, PCI_COMMAND, cmd);
}
return 0;
}
/* Resource allocation. */
static void __devinit pcibios_assign_resources (void)
{
struct pci_dev *dev;
struct resource *r;
pci_for_each_dev (dev) {
int di_num;
unsigned class = dev->class >> 8;
if (class && class != PCI_CLASS_BRIDGE_HOST) {
unsigned r_num;
for(r_num = 0; r_num < 6; r_num++) {
r = &dev->resource[r_num];
if (!r->start && r->end)
pci_assign_resource (dev, r_num);
}
}
/* Assign interrupts. */
for (di_num = 0; di_num < NUM_MB_PCI_DEV_IRQS; di_num++) {
struct mb_pci_dev_irq *di = &mb_pci_dev_irqs[di_num];
if (di->dev == PCI_SLOT (dev->devfn)) {
unsigned irq = di->irq_base;
if (di->query_pin) {
/* Find out which interrupt pin
this device uses (each PCI
slot has 4). */
u8 irq_pin;
pci_read_config_byte (dev,
PCI_INTERRUPT_PIN,
&irq_pin);
if (irq_pin == 0)
/* Doesn't use interrupts. */
continue;
else
irq += irq_pin - 1;
}
pcibios_update_irq (dev, irq);
}
}
}
}
void __devinit pcibios_update_irq (struct pci_dev *dev, int irq)
{
dev->irq = irq;
pci_write_config_byte (dev, PCI_INTERRUPT_LINE, irq);
}
void __nomods_init
pcibios_update_resource (struct pci_dev *dev, struct resource *root,
struct resource *r, int resource)
{
u32 new, check;
int reg;
if (r->flags & IORESOURCE_IO)
new = (((r->start - MB_A_PCI_IO_ADDR)
& PCI_BASE_ADDRESS_IO_MASK)
| PCI_BASE_ADDRESS_SPACE_IO);
else if (r->flags & IORESOURCE_MEM)
new = (((r->start - MB_A_PCI_MEM_ADDR)
& PCI_BASE_ADDRESS_MEM_MASK)
| PCI_BASE_ADDRESS_MEM_TYPE_32
| ((r->flags & IORESOURCE_PREFETCH)
? PCI_BASE_ADDRESS_MEM_PREFETCH
: 0)
| PCI_BASE_ADDRESS_SPACE_MEMORY);
else
panic ("pcibios_update_resource: unknown resource type");
if (resource < 6)
reg = PCI_BASE_ADDRESS_0 + 4*resource;
else if (resource == PCI_ROM_RESOURCE) {
r->flags |= PCI_ROM_ADDRESS_ENABLE;
new |= PCI_ROM_ADDRESS_ENABLE;
reg = dev->rom_base_reg;
} else
return;
pci_write_config_dword(dev, reg, new);
pci_read_config_dword(dev, reg, &check);
if ((new ^ check) & ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) {
printk (KERN_ERR "PCI: Error while updating region "
"%s/%d (%08x != %08x)\n", dev->slot_name, resource,
new, check);
}
}
/* Stubs for things we don't use. */
struct pci_fixup pcibios_fixups[] = { { 0 } };
/* Called after each bus is probed, but before its children are examined. */
void pcibios_fixup_bus(struct pci_bus *b)
{
}
void
pcibios_align_resource (void *data, struct resource *res,
unsigned long size, unsigned long align)
{
}
void pcibios_set_master (struct pci_dev *dev)
{
}
/* Mother-A SRAM memory allocation. This is a simple first-fit allocator. */
/* A memory free-list node. */
struct mb_sram_free_area {
void *mem;
unsigned long size;
struct mb_sram_free_area *next;
};
/* The tail of the free-list, which starts out containing all the SRAM. */
static struct mb_sram_free_area mb_sram_free_tail = {
(void *)MB_A_SRAM_ADDR, MB_A_SRAM_SIZE, 0
};
/* The free-list. */
static struct mb_sram_free_area *mb_sram_free_areas = &mb_sram_free_tail;
/* The free-list of free free-list nodes. (:-) */
static struct mb_sram_free_area *mb_sram_free_free_areas = 0;
/* Spinlock protecting the above globals. */
static spinlock_t mb_sram_lock = SPIN_LOCK_UNLOCKED;
/* Allocate a memory block at least SIZE bytes long in the Mother-A SRAM
space. */
static void *alloc_mb_sram (size_t size)
{
struct mb_sram_free_area *prev, *fa;
int flags;
void *mem = 0;
spin_lock_irqsave (mb_sram_lock, flags);
/* Look for a free area that can contain SIZE bytes. */
for (prev = 0, fa = mb_sram_free_areas; fa; prev = fa, fa = fa->next)
if (fa->size >= size) {
/* Found one! */
mem = fa->mem;
if (fa->size == size) {
/* In fact, it fits exactly, so remove
this node from the free-list. */
if (prev)
prev->next = fa->next;
else
mb_sram_free_areas = fa->next;
/* Put it on the free-list-entry-free-list. */
fa->next = mb_sram_free_free_areas;
mb_sram_free_free_areas = fa;
} else {
/* FA is bigger than SIZE, so just
reduce its size to account for this
allocation. */
fa->mem += size;
fa->size -= size;
}
break;
}
spin_unlock_irqrestore (mb_sram_lock, flags);
return mem;
}
/* Return the memory area MEM of size SIZE to the MB SRAM free pool. */
static void free_mb_sram (void *mem, size_t size)
{
struct mb_sram_free_area *prev, *fa, *new_fa;
int flags;
void *end = mem + size;
spin_lock_irqsave (mb_sram_lock, flags);
retry:
/* Find an adjacent free-list entry. */
for (prev = 0, fa = mb_sram_free_areas; fa; prev = fa, fa = fa->next)
if (fa->mem == end) {
/* FA is just after MEM, grow down to encompass it. */
fa->mem = mem;
fa->size += size;
goto done;
} else if (fa->mem + fa->size == mem) {
struct mb_sram_free_area *next_fa = fa->next;
/* FA is just before MEM, expand to encompass it. */
fa->size += size;
/* See if FA can now be merged with its successor. */
if (next_fa && fa->mem + fa->size == next_fa->mem) {
/* Yup; merge NEXT_FA's info into FA. */
fa->size += next_fa->size;
fa->next = next_fa->next;
/* Free NEXT_FA. */
next_fa->next = mb_sram_free_free_areas;
mb_sram_free_free_areas = next_fa;
}
goto done;
} else if (fa->mem > mem)
/* We've reached the right spot in the free-list
without finding an adjacent free-area, so add
a new free area to hold mem. */
break;
/* Make a new free-list entry. */
/* First, get a free-list entry. */
if (! mb_sram_free_free_areas) {
/* There are none, so make some. */
void *block;
size_t block_size = sizeof (struct mb_sram_free_area) * 8;
/* Don't hold the lock while calling kmalloc (I'm not
sure whether it would be a problem, since we use
GFP_ATOMIC, but it makes me nervous). */
spin_unlock_irqrestore (mb_sram_lock, flags);
block = kmalloc (block_size, GFP_ATOMIC);
if (! block)
panic ("free_mb_sram: can't allocate free-list entry");
/* Now get the lock back. */
spin_lock_irqsave (mb_sram_lock, flags);
/* Add the new free free-list entries. */
while (block_size > 0) {
struct mb_sram_free_area *nfa = block;
nfa->next = mb_sram_free_free_areas;
mb_sram_free_free_areas = nfa;
block += sizeof *nfa;
block_size -= sizeof *nfa;
}
/* Since we dropped the lock to call kmalloc, the
free-list could have changed, so retry from the
beginning. */
goto retry;
}
/* Remove NEW_FA from the free-list of free-list entries. */
new_fa = mb_sram_free_free_areas;
mb_sram_free_free_areas = new_fa->next;
/* NEW_FA initially holds only MEM. */
new_fa->mem = mem;
new_fa->size = size;
/* Insert NEW_FA in the free-list between PREV and FA. */
new_fa->next = fa;
if (prev)
prev->next = new_fa;
else
mb_sram_free_areas = new_fa;
done:
spin_unlock_irqrestore (mb_sram_lock, flags);
}
/* Maintainence of CPU -> Mother-A DMA mappings. */
struct dma_mapping {
void *cpu_addr;
void *mb_sram_addr;
size_t size;
struct dma_mapping *next;
};
/* A list of mappings from CPU addresses to MB SRAM addresses for active
DMA blocks (that have been `granted' to the PCI device). */
static struct dma_mapping *active_dma_mappings = 0;
/* A list of free mapping objects. */
static struct dma_mapping *free_dma_mappings = 0;
/* Spinlock protecting the above globals. */
static spinlock_t dma_mappings_lock = SPIN_LOCK_UNLOCKED;
static struct dma_mapping *new_dma_mapping (size_t size)
{
int flags;
struct dma_mapping *mapping;
void *mb_sram_block = alloc_mb_sram (size);
if (! mb_sram_block)
return 0;
spin_lock_irqsave (dma_mappings_lock, flags);
if (! free_dma_mappings) {
/* We're out of mapping structures, make more. */
void *mblock;
size_t mblock_size = sizeof (struct dma_mapping) * 8;
/* Don't hold the lock while calling kmalloc (I'm not
sure whether it would be a problem, since we use
GFP_ATOMIC, but it makes me nervous). */
spin_unlock_irqrestore (dma_mappings_lock, flags);
mblock = kmalloc (mblock_size, GFP_ATOMIC);
if (! mblock) {
free_mb_sram (mb_sram_block, size);
return 0;
}
/* Get the lock back. */
spin_lock_irqsave (dma_mappings_lock, flags);
/* Add the new mapping structures to the free-list. */
while (mblock_size > 0) {
struct dma_mapping *fm = mblock;
fm->next = free_dma_mappings;
free_dma_mappings = fm;
mblock += sizeof *fm;
mblock_size -= sizeof *fm;
}
}
/* Get a mapping struct from the freelist. */
mapping = free_dma_mappings;
free_dma_mappings = mapping->next;
/* Initialize the mapping. Other fields should be filled in by
caller. */
mapping->mb_sram_addr = mb_sram_block;
mapping->size = size;
/* Add it to the list of active mappings. */
mapping->next = active_dma_mappings;
active_dma_mappings = mapping;
spin_unlock_irqrestore (dma_mappings_lock, flags);
return mapping;
}
static struct dma_mapping *find_dma_mapping (void *mb_sram_addr)
{
int flags;
struct dma_mapping *mapping;
spin_lock_irqsave (dma_mappings_lock, flags);
for (mapping = active_dma_mappings; mapping; mapping = mapping->next)
if (mapping->mb_sram_addr == mb_sram_addr) {
spin_unlock_irqrestore (dma_mappings_lock, flags);
return mapping;
}
panic ("find_dma_mapping: unmapped PCI DMA addr 0x%x",
MB_SRAM_TO_PCI (mb_sram_addr));
}
static struct dma_mapping *deactivate_dma_mapping (void *mb_sram_addr)
{
int flags;
struct dma_mapping *mapping, *prev;
spin_lock_irqsave (dma_mappings_lock, flags);
for (prev = 0, mapping = active_dma_mappings;
mapping;
prev = mapping, mapping = mapping->next)
{
if (mapping->mb_sram_addr == mb_sram_addr) {
/* This is the MAPPING; deactivate it. */
if (prev)
prev->next = mapping->next;
else
active_dma_mappings = mapping->next;
spin_unlock_irqrestore (dma_mappings_lock, flags);
return mapping;
}
}
panic ("deactivate_dma_mapping: unmapped PCI DMA addr 0x%x",
MB_SRAM_TO_PCI (mb_sram_addr));
}
/* Return MAPPING to the freelist. */
static inline void
free_dma_mapping (struct dma_mapping *mapping)
{
int flags;
free_mb_sram (mapping->mb_sram_addr, mapping->size);
spin_lock_irqsave (dma_mappings_lock, flags);
mapping->next = free_dma_mappings;
free_dma_mappings = mapping;
spin_unlock_irqrestore (dma_mappings_lock, flags);
}
/* Single PCI DMA mappings. */
/* `Grant' to PDEV the memory block at CPU_ADDR, for doing DMA. The
32-bit PCI bus mastering address to use is returned. the device owns
this memory until either pci_unmap_single or pci_dma_sync_single is
performed. */
dma_addr_t
pci_map_single (struct pci_dev *pdev, void *cpu_addr, size_t size, int dir)
{
struct dma_mapping *mapping = new_dma_mapping (size);
if (! mapping)
return 0;
mapping->cpu_addr = cpu_addr;
if (dir == PCI_DMA_BIDIRECTIONAL || dir == PCI_DMA_TODEVICE)
memcpy (mapping->mb_sram_addr, cpu_addr, size);
return MB_SRAM_TO_PCI (mapping->mb_sram_addr);
}
/* Return to the CPU the PCI DMA memory block previously `granted' to
PDEV, at DMA_ADDR. */
void pci_unmap_single (struct pci_dev *pdev, dma_addr_t dma_addr, size_t size,
int dir)
{
void *mb_sram_addr = PCI_TO_MB_SRAM (dma_addr);
struct dma_mapping *mapping = deactivate_dma_mapping (mb_sram_addr);
if (size != mapping->size)
panic ("pci_unmap_single: size (%d) doesn't match"
" size of mapping at PCI DMA addr 0x%x (%d)\n",
size, dma_addr, mapping->size);
/* Copy back the DMA'd contents if necessary. */
if (dir == PCI_DMA_BIDIRECTIONAL || dir == PCI_DMA_FROMDEVICE)
memcpy (mapping->cpu_addr, mb_sram_addr, size);
/* Return mapping to the freelist. */
free_dma_mapping (mapping);
}
/* Make physical memory consistant for a single streaming mode DMA
translation after a transfer.
If you perform a pci_map_single() but wish to interrogate the
buffer using the cpu, yet do not wish to teardown the PCI dma
mapping, you must call this function before doing so. At the next
point you give the PCI dma address back to the card, the device
again owns the buffer. */
void
pci_dma_sync_single (struct pci_dev *pdev, dma_addr_t dma_addr, size_t size,
int dir)
{
void *mb_sram_addr = PCI_TO_MB_SRAM (dma_addr);
struct dma_mapping *mapping = find_dma_mapping (mb_sram_addr);
/* Synchronize the DMA buffer with the CPU buffer if necessary. */
if (dir == PCI_DMA_FROMDEVICE)
memcpy (mapping->cpu_addr, mb_sram_addr, size);
else if (dir == PCI_DMA_TODEVICE)
memcpy (mb_sram_addr, mapping->cpu_addr, size);
else
panic("pci_dma_sync_single: unsupported sync dir: %d", dir);
}
/* Scatter-gather PCI DMA mappings. */
/* Do multiple DMA mappings at once. */
int
pci_map_sg (struct pci_dev *pdev, struct scatterlist *sg, int sg_len, int dir)
{
BUG ();
return 0;
}
/* Unmap multiple DMA mappings at once. */
void
pci_unmap_sg (struct pci_dev *pdev, struct scatterlist *sg, int sg_len,int dir)
{
BUG ();
}
/* Make physical memory consistant for a set of streaming mode DMA
translations after a transfer. The same as pci_dma_sync_single but
for a scatter-gather list, same rules and usage. */
void
pci_dma_sync_sg (struct pci_dev *dev, struct scatterlist *sg, int sg_len,
int dir)
{
BUG ();
}
/* PCI mem mapping. */
/* Allocate and map kernel buffer using consistent mode DMA for PCI
device. Returns non-NULL cpu-view pointer to the buffer if
successful and sets *DMA_ADDR to the pci side dma address as well,
else DMA_ADDR is undefined. */
void *
pci_alloc_consistent (struct pci_dev *pdev, size_t size, dma_addr_t *dma_addr)
{
void *mb_sram_mem = alloc_mb_sram (size);
if (mb_sram_mem)
*dma_addr = MB_SRAM_TO_PCI (mb_sram_mem);
return mb_sram_mem;
}
/* Free and unmap a consistent DMA buffer. CPU_ADDR and DMA_ADDR must
be values that were returned from pci_alloc_consistent. SIZE must be
the same as what as passed into pci_alloc_consistent. References to
the memory and mappings assosciated with CPU_ADDR or DMA_ADDR past
this call are illegal. */
void
pci_free_consistent (struct pci_dev *pdev, size_t size, void *cpu_addr,
dma_addr_t dma_addr)
{
void *mb_sram_mem = PCI_TO_MB_SRAM (dma_addr);
free_mb_sram (mb_sram_mem, size);
}
/* symbol exports (for modules) */
EXPORT_SYMBOL (pci_map_single);
EXPORT_SYMBOL (pci_unmap_single);
EXPORT_SYMBOL (pci_alloc_consistent);
EXPORT_SYMBOL (pci_free_consistent);
EXPORT_SYMBOL (pci_dma_sync_single);
/*
* arch/v850/kernel/rte_nb85e_cb.c -- Midas labs RTE-V850E/NB85E-CB board
*
* Copyright (C) 2001,02 NEC Corporation
* Copyright (C) 2001,02 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/swap.h>
#include <linux/bootmem.h>
#include <linux/irq.h>
#include <asm/atomic.h>
#include <asm/page.h>
#include <asm/nb85e.h>
#include <asm/rte_nb85e_cb.h>
#include "mach.h"
void __init mach_get_physical_ram (unsigned long *ram_start,
unsigned long *ram_len)
{
/* We just use SDRAM here; the kernel itself is in SRAM. */
*ram_start = SDRAM_ADDR;
*ram_len = SDRAM_SIZE;
}
void __init mach_reserve_bootmem ()
{
extern char _root_fs_image_start, _root_fs_image_end;
u32 root_fs_image_start = (u32)&_root_fs_image_start;
u32 root_fs_image_end = (u32)&_root_fs_image_end;
/* Reserve the memory used by the root filesystem image if it's
in RAM. */
if (root_fs_image_start >= RAM_START && root_fs_image_start < RAM_END)
reserve_bootmem (root_fs_image_start,
root_fs_image_end - root_fs_image_start);
}
void mach_gettimeofday (struct timespec *tv)
{
tv->tv_sec = 0;
tv->tv_nsec = 0;
}
/*
* arch/v850/kernel/semaphore.c -- Semaphore support
*
* Copyright (C) 1998-2000 IBM Corporation
* Copyright (C) 1999 Linus Torvalds
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* This file is a copy of the s390 version, arch/s390/kernel/semaphore.c
* Author(s): Martin Schwidefsky
* which was derived from the i386 version, linux/arch/i386/kernel/semaphore.c
*/
#include <linux/sched.h>
#include <asm/semaphore.h>
/*
* Semaphores are implemented using a two-way counter:
* The "count" variable is decremented for each process
* that tries to acquire the semaphore, while the "sleeping"
* variable is a count of such acquires.
*
* Notably, the inline "up()" and "down()" functions can
* efficiently test if they need to do any extra work (up
* needs to do something only if count was negative before
* the increment operation.
*
* "sleeping" and the contention routine ordering is
* protected by the semaphore spinlock.
*
* Note that these functions are only called when there is
* contention on the lock, and as such all this is the
* "non-critical" part of the whole semaphore business. The
* critical part is the inline stuff in <asm/semaphore.h>
* where we want to avoid any extra jumps and calls.
*/
/*
* Logic:
* - only on a boundary condition do we need to care. When we go
* from a negative count to a non-negative, we wake people up.
* - when we go from a non-negative count to a negative do we
* (a) synchronize with the "sleeper" count and (b) make sure
* that we're on the wakeup list before we synchronize so that
* we cannot lose wakeup events.
*/
void __up(struct semaphore *sem)
{
wake_up(&sem->wait);
}
static spinlock_t semaphore_lock = SPIN_LOCK_UNLOCKED;
void __down(struct semaphore * sem)
{
struct task_struct *tsk = current;
DECLARE_WAITQUEUE(wait, tsk);
tsk->state = TASK_UNINTERRUPTIBLE;
add_wait_queue_exclusive(&sem->wait, &wait);
spin_lock_irq(&semaphore_lock);
sem->sleepers++;
for (;;) {
int sleepers = sem->sleepers;
/*
* Add "everybody else" into it. They aren't
* playing, because we own the spinlock.
*/
if (!atomic_add_negative(sleepers - 1, &sem->count)) {
sem->sleepers = 0;
break;
}
sem->sleepers = 1; /* us - see -1 above */
spin_unlock_irq(&semaphore_lock);
schedule();
tsk->state = TASK_UNINTERRUPTIBLE;
spin_lock_irq(&semaphore_lock);
}
spin_unlock_irq(&semaphore_lock);
remove_wait_queue(&sem->wait, &wait);
tsk->state = TASK_RUNNING;
wake_up(&sem->wait);
}
int __down_interruptible(struct semaphore * sem)
{
int retval = 0;
struct task_struct *tsk = current;
DECLARE_WAITQUEUE(wait, tsk);
tsk->state = TASK_INTERRUPTIBLE;
add_wait_queue_exclusive(&sem->wait, &wait);
spin_lock_irq(&semaphore_lock);
sem->sleepers ++;
for (;;) {
int sleepers = sem->sleepers;
/*
* With signals pending, this turns into
* the trylock failure case - we won't be
* sleeping, and we* can't get the lock as
* it has contention. Just correct the count
* and exit.
*/
if (signal_pending(current)) {
retval = -EINTR;
sem->sleepers = 0;
atomic_add(sleepers, &sem->count);
break;
}
/*
* Add "everybody else" into it. They aren't
* playing, because we own the spinlock. The
* "-1" is because we're still hoping to get
* the lock.
*/
if (!atomic_add_negative(sleepers - 1, &sem->count)) {
sem->sleepers = 0;
break;
}
sem->sleepers = 1; /* us - see -1 above */
spin_unlock_irq(&semaphore_lock);
schedule();
tsk->state = TASK_INTERRUPTIBLE;
spin_lock_irq(&semaphore_lock);
}
spin_unlock_irq(&semaphore_lock);
tsk->state = TASK_RUNNING;
remove_wait_queue(&sem->wait, &wait);
wake_up(&sem->wait);
return retval;
}
/*
* Trylock failed - make sure we correct for
* having decremented the count.
*/
int __down_trylock(struct semaphore * sem)
{
unsigned long flags;
int sleepers;
spin_lock_irqsave(&semaphore_lock, flags);
sleepers = sem->sleepers + 1;
sem->sleepers = 0;
/*
* Add "everybody else" and us into it. They aren't
* playing, because we own the spinlock.
*/
if (!atomic_add_negative(sleepers, &sem->count))
wake_up(&sem->wait);
spin_unlock_irqrestore(&semaphore_lock, flags);
return 1;
}
/*
* arch/v850/kernel/setup.c -- Arch-dependent initialization functions
*
* Copyright (C) 2001,02 NEC Corporation
* Copyright (C) 2001,02 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/bootmem.h>
#include <linux/irq.h>
#include <linux/reboot.h>
#include <linux/personality.h>
#include <linux/major.h>
#include <linux/root_dev.h>
#include <linux/mtd/mtd.h>
#include <asm/irq.h>
#include "mach.h"
/* These symbols are all defined in the linker map to delineate various
statically allocated regions of memory. */
extern char _intv_start, _intv_end;
/* `kram' is only used if the kernel uses part of normal user RAM. */
extern char _kram_start __attribute__ ((__weak__));
extern char _kram_end __attribute__ ((__weak__));
extern char _init_start, _init_end;
extern char _bootmap;
extern char _stext, _etext, _sdata, _edata, _sbss, _ebss;
/* Many platforms use an embedded root image. */
extern char _root_fs_image_start __attribute__ ((__weak__));
extern char _root_fs_image_end __attribute__ ((__weak__));
char command_line[512];
char saved_command_line[512];
/* Memory not used by the kernel. */
static unsigned long total_ram_pages;
/* System RAM. */
static unsigned long ram_start = 0, ram_len = 0;
#define ADDR_TO_PAGE_UP(x) ((((unsigned long)x) + PAGE_SIZE-1) >> PAGE_SHIFT)
#define ADDR_TO_PAGE(x) (((unsigned long)x) >> PAGE_SHIFT)
#define PAGE_TO_ADDR(x) (((unsigned long)x) << PAGE_SHIFT)
static void init_mem_alloc (unsigned long ram_start, unsigned long ram_len);
void set_mem_root (void *addr, size_t len, char *cmd_line);
void __init setup_arch (char **cmdline)
{
/* Keep a copy of command line */
*cmdline = command_line;
memcpy (saved_command_line, command_line, sizeof saved_command_line);
saved_command_line[sizeof saved_command_line - 1] = '\0';
console_verbose ();
init_mm.start_code = (unsigned long) &_stext;
init_mm.end_code = (unsigned long) &_etext;
init_mm.end_data = (unsigned long) &_edata;
init_mm.brk = (unsigned long) &_kram_end;
/* Find out what mem this machine has. */
mach_get_physical_ram (&ram_start, &ram_len);
/* ... and tell the kernel about it. */
init_mem_alloc (ram_start, ram_len);
/* do machine-specific setups. */
mach_setup (cmdline);
#ifdef CONFIG_MTD
if (!ROOT_DEV && &_root_fs_image_end > &_root_fs_image_start)
set_mem_root (&_root_fs_image_start,
&_root_fs_image_end - &_root_fs_image_start,
*cmdline);
#endif
}
void __init trap_init (void)
{
}
#ifdef CONFIG_MTD
/* Set the root filesystem to be the given memory region.
Some parameter may be appended to CMD_LINE. */
void set_mem_root (void *addr, size_t len, char *cmd_line)
{
/* The only way to pass info to the MTD slram driver is via
the command line. */
if (*cmd_line) {
cmd_line += strlen (cmd_line);
*cmd_line++ = ' ';
}
sprintf (cmd_line, "slram=root,0x%x,+0x%x", (u32)addr, (u32)len);
ROOT_DEV = MKDEV (MTD_BLOCK_MAJOR, 0);
}
#endif
static void irq_nop (unsigned irq) { }
static unsigned irq_zero (unsigned irq) { return 0; }
static void nmi_end (unsigned irq)
{
if (irq != IRQ_NMI (0)) {
printk (KERN_CRIT "NMI %d is unrecoverable; restarting...",
irq - IRQ_NMI (0));
machine_restart (0);
}
}
static struct hw_interrupt_type nmi_irq_type = {
"NMI",
irq_zero, /* startup */
irq_nop, /* shutdown */
irq_nop, /* enable */
irq_nop, /* disable */
irq_nop, /* ack */
nmi_end, /* end */
};
void __init init_IRQ (void)
{
init_irq_handlers (0, NUM_MACH_IRQS, 1, 0);
init_irq_handlers (IRQ_NMI (0), NUM_NMIS, 1, &nmi_irq_type);
mach_init_irqs ();
}
void __init mem_init (void)
{
max_mapnr = MAP_NR (ram_start + ram_len);
num_physpages = ADDR_TO_PAGE (ram_len);
total_ram_pages = free_all_bootmem ();
printk (KERN_INFO
"Memory: %luK/%luK available"
" (%luK kernel code, %luK data)\n",
PAGE_TO_ADDR (nr_free_pages()) / 1024,
ram_len / 1024,
((unsigned long)&_etext - (unsigned long)&_stext) / 1024,
((unsigned long)&_ebss - (unsigned long)&_sdata) / 1024);
}
void free_initmem (void)
{
unsigned long ram_end = ram_start + ram_len;
unsigned long start = PAGE_ALIGN ((unsigned long)(&_init_start));
if (start >= ram_start && start < ram_end) {
unsigned long addr;
unsigned long end = PAGE_ALIGN ((unsigned long)(&_init_end));
if (end > ram_end)
end = ram_end;
printk("Freeing unused kernel memory: %ldK freed\n",
(end - start) / 1024);
for (addr = start; addr < end; addr += PAGE_SIZE) {
struct page *page = virt_to_page (addr);
ClearPageReserved (page);
set_page_count (page, 1);
__free_page (page);
total_ram_pages++;
}
}
}
/* Initialize the `bootmem allocator'. RAM_START and RAM_LEN identify
what RAM may be used. */
static void __init
init_bootmem_alloc (unsigned long ram_start, unsigned long ram_len)
{
/* The part of the kernel that's in the same managed RAM space
used for general allocation. */
unsigned long kram_start = (unsigned long)&_kram_start;
unsigned long kram_end = (unsigned long)&_kram_end;
/* End of the managed RAM space. */
unsigned long ram_end = ram_start + ram_len;
/* Address range of the interrupt vector table. */
unsigned long intv_start = (unsigned long)&_intv_start;
unsigned long intv_end = (unsigned long)&_intv_end;
/* True if the interrupt vectors are in the managed RAM area. */
int intv_in_ram = (intv_end > ram_start && intv_start < ram_end);
/* True if the interrupt vectors are inside the kernel's RAM. */
int intv_in_kram = (intv_end > kram_start && intv_start < kram_end);
/* A pointer to an optional function that reserves platform-specific
memory regions. We declare the pointer `volatile' to avoid gcc
turning the call into a static call (the problem is that since
it's a weak symbol, a static call may end up trying to reference
the location 0x0, which is not always reachable). */
void (*volatile mrb) (void) = mach_reserve_bootmem;
/* The bootmem allocator's allocation bitmap. */
unsigned long bootmap = (unsigned long)&_bootmap;
unsigned long bootmap_len;
/* Round bootmap location up to next page. */
bootmap = PAGE_TO_ADDR (ADDR_TO_PAGE_UP (bootmap));
/* Initialize bootmem allocator. */
bootmap_len = init_bootmem_node (NODE_DATA (0),
ADDR_TO_PAGE (bootmap),
ADDR_TO_PAGE (PAGE_OFFSET),
ADDR_TO_PAGE (ram_end));
/* Now make the RAM actually allocatable (it starts out `reserved'). */
free_bootmem (ram_start, ram_len);
if (kram_end > kram_start)
/* Reserve the RAM part of the kernel's address space, so it
doesn't get allocated. */
reserve_bootmem (kram_start, kram_end - kram_start);
if (intv_in_ram && !intv_in_kram)
/* Reserve the interrupt vector space. */
reserve_bootmem (intv_start, intv_end - intv_start);
if (bootmap >= ram_start && bootmap < ram_end)
/* Reserve the bootmap space. */
reserve_bootmem (bootmap, bootmap_len);
/* Reserve the memory used by the root filesystem image if it's
in RAM. */
if (&_root_fs_image_end > &_root_fs_image_start
&& (unsigned long)&_root_fs_image_start >= ram_start
&& (unsigned long)&_root_fs_image_start < ram_end)
reserve_bootmem ((unsigned long)&_root_fs_image_start,
&_root_fs_image_end - &_root_fs_image_start);
/* Let the platform-dependent code reserve some too. */
if (mrb)
(*mrb) ();
}
/* Tell the kernel about what RAM it may use for memory allocation. */
static void __init
init_mem_alloc (unsigned long ram_start, unsigned long ram_len)
{
unsigned i;
unsigned long zones_size[MAX_NR_ZONES];
init_bootmem_alloc (ram_start, ram_len);
for (i = 0; i < MAX_NR_ZONES; i++)
zones_size[i] = 0;
/* We stuff all the memory into one area, which includes the
initial gap from PAGE_OFFSET to ram_start. */
zones_size[ZONE_DMA]
= ADDR_TO_PAGE (ram_len + (ram_start - PAGE_OFFSET));
free_area_init_node (0, NODE_DATA(0), 0, zones_size,
ADDR_TO_PAGE (PAGE_OFFSET), 0);
mem_map = NODE_DATA(0)->node_mem_map;
}
/*
* arch/v850/kernel/signal.c -- Signal handling
*
* Copyright (C) 2001,02 NEC Corporation
* Copyright (C) 2001,02 Miles Bader <miles@gnu.org>
* Copyright (C) 1999,2000,2002 Niibe Yutaka & Kaz Kojima
* Copyright (C) 1991,1992 Linus Torvalds
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* 1997-11-28 Modified for POSIX.1b signals by Richard Henderson
*
* This file was derived from the sh version, arch/sh/kernel/signal.c
*/
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/kernel.h>
#include <linux/signal.h>
#include <linux/errno.h>
#include <linux/wait.h>
#include <linux/ptrace.h>
#include <linux/unistd.h>
#include <linux/stddef.h>
#include <linux/personality.h>
#include <linux/tty.h>
#include <asm/ucontext.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
#include <asm/pgalloc.h>
#include <asm/thread_info.h>
#include <asm/cacheflush.h>
#define DEBUG_SIG 0
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset);
/*
* Atomically swap in the new signal mask, and wait for a signal.
*/
asmlinkage int
sys_sigsuspend(old_sigset_t mask, struct pt_regs *regs)
{
sigset_t saveset;
mask &= _BLOCKABLE;
spin_lock_irq(&current->sig->siglock);
saveset = current->blocked;
siginitset(&current->blocked, mask);
recalc_sigpending();
spin_unlock_irq(&current->sig->siglock);
regs->gpr[GPR_RVAL] = -EINTR;
while (1) {
current->state = TASK_INTERRUPTIBLE;
schedule();
if (do_signal(regs, &saveset))
return -EINTR;
}
}
asmlinkage int
sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize,
struct pt_regs *regs)
{
sigset_t saveset, newset;
/* XXX: Don't preclude handling different sized sigset_t's. */
if (sigsetsize != sizeof(sigset_t))
return -EINVAL;
if (copy_from_user(&newset, unewset, sizeof(newset)))
return -EFAULT;
sigdelsetmask(&newset, ~_BLOCKABLE);
spin_lock_irq(&current->sig->siglock);
saveset = current->blocked;
current->blocked = newset;
recalc_sigpending();
spin_unlock_irq(&current->sig->siglock);
regs->gpr[GPR_RVAL] = -EINTR;
while (1) {
current->state = TASK_INTERRUPTIBLE;
schedule();
if (do_signal(regs, &saveset))
return -EINTR;
}
}
asmlinkage int
sys_sigaction(int sig, const struct old_sigaction *act,
struct old_sigaction *oact)
{
struct k_sigaction new_ka, old_ka;
int ret;
if (act) {
old_sigset_t mask;
if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
__get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
__get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
return -EFAULT;
__get_user(new_ka.sa.sa_flags, &act->sa_flags);
__get_user(mask, &act->sa_mask);
siginitset(&new_ka.sa.sa_mask, mask);
}
ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
if (!ret && oact) {
if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
__put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
__put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
return -EFAULT;
__put_user(old_ka.sa.sa_flags, &oact->sa_flags);
__put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
}
return ret;
}
asmlinkage int
sys_sigaltstack(const stack_t *uss, stack_t *uoss,
struct pt_regs *regs)
{
return do_sigaltstack(uss, uoss, regs->gpr[GPR_SP]);
}
/*
* Do a signal return; undo the signal stack.
*/
struct sigframe
{
struct sigcontext sc;
unsigned long extramask[_NSIG_WORDS-1];
unsigned long tramp[2]; /* signal trampoline */
};
struct rt_sigframe
{
struct siginfo *pinfo;
void *puc;
struct siginfo info;
struct ucontext uc;
unsigned long tramp[2]; /* signal trampoline */
};
static int
restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc, int *rval_p)
{
unsigned int err = 0;
#define COPY(x) err |= __get_user(regs->x, &sc->regs.x)
COPY(gpr[0]); COPY(gpr[1]); COPY(gpr[2]); COPY(gpr[3]);
COPY(gpr[4]); COPY(gpr[5]); COPY(gpr[6]); COPY(gpr[7]);
COPY(gpr[8]); COPY(gpr[9]); COPY(gpr[10]); COPY(gpr[11]);
COPY(gpr[12]); COPY(gpr[13]); COPY(gpr[14]); COPY(gpr[15]);
COPY(gpr[16]); COPY(gpr[17]); COPY(gpr[18]); COPY(gpr[19]);
COPY(gpr[20]); COPY(gpr[21]); COPY(gpr[22]); COPY(gpr[23]);
COPY(gpr[24]); COPY(gpr[25]); COPY(gpr[26]); COPY(gpr[27]);
COPY(gpr[28]); COPY(gpr[29]); COPY(gpr[30]); COPY(gpr[31]);
COPY(pc); COPY(psw);
COPY(ctpc); COPY(ctpsw); COPY(ctbp);
#undef COPY
return err;
}
asmlinkage int sys_sigreturn(struct pt_regs *regs)
{
struct sigframe *frame = (struct sigframe *)regs->gpr[GPR_SP];
sigset_t set;
int rval;
if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
goto badframe;
if (__get_user(set.sig[0], &frame->sc.oldmask)
|| (_NSIG_WORDS > 1
&& __copy_from_user(&set.sig[1], &frame->extramask,
sizeof(frame->extramask))))
goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE);
spin_lock_irq(&current->sig->siglock);
current->blocked = set;
recalc_sigpending();
spin_unlock_irq(&current->sig->siglock);
if (restore_sigcontext(regs, &frame->sc, &rval))
goto badframe;
return rval;
badframe:
force_sig(SIGSEGV, current);
return 0;
}
asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
{
struct rt_sigframe *frame = (struct rt_sigframe *)regs->gpr[GPR_SP];
sigset_t set;
stack_t st;
int rval;
if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
goto badframe;
if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE);
spin_lock_irq(&current->sig->siglock);
current->blocked = set;
recalc_sigpending();
spin_unlock_irq(&current->sig->siglock);
if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &rval))
goto badframe;
if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st)))
goto badframe;
/* It is more difficult to avoid calling this function than to
call it and ignore errors. */
do_sigaltstack(&st, NULL, regs->gpr[GPR_SP]);
return rval;
badframe:
force_sig(SIGSEGV, current);
return 0;
}
/*
* Set up a signal frame.
*/
static int
setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs,
unsigned long mask)
{
int err = 0;
#define COPY(x) err |= __put_user(regs->x, &sc->regs.x)
COPY(gpr[0]); COPY(gpr[1]); COPY(gpr[2]); COPY(gpr[3]);
COPY(gpr[4]); COPY(gpr[5]); COPY(gpr[6]); COPY(gpr[7]);
COPY(gpr[8]); COPY(gpr[9]); COPY(gpr[10]); COPY(gpr[11]);
COPY(gpr[12]); COPY(gpr[13]); COPY(gpr[14]); COPY(gpr[15]);
COPY(gpr[16]); COPY(gpr[17]); COPY(gpr[18]); COPY(gpr[19]);
COPY(gpr[20]); COPY(gpr[21]); COPY(gpr[22]); COPY(gpr[23]);
COPY(gpr[24]); COPY(gpr[25]); COPY(gpr[26]); COPY(gpr[27]);
COPY(gpr[28]); COPY(gpr[29]); COPY(gpr[30]); COPY(gpr[31]);
COPY(pc); COPY(psw);
COPY(ctpc); COPY(ctpsw); COPY(ctbp);
#undef COPY
err |= __put_user(mask, &sc->oldmask);
return err;
}
/*
* Determine which stack to use..
*/
static inline void *
get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
{
/* Default to using normal stack */
unsigned long sp = regs->gpr[GPR_SP];
if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! on_sig_stack(sp))
sp = current->sas_ss_sp + current->sas_ss_size;
return (void *)((sp - frame_size) & -8UL);
}
static void setup_frame(int sig, struct k_sigaction *ka,
sigset_t *set, struct pt_regs *regs)
{
struct sigframe *frame;
int err = 0;
int signal;
frame = get_sigframe(ka, regs, sizeof(*frame));
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
goto give_sigsegv;
signal = current_thread_info()->exec_domain
&& current_thread_info()->exec_domain->signal_invmap
&& sig < 32
? current_thread_info()->exec_domain->signal_invmap[sig]
: sig;
err |= setup_sigcontext(&frame->sc, regs, set->sig[0]);
if (_NSIG_WORDS > 1) {
err |= __copy_to_user(frame->extramask, &set->sig[1],
sizeof(frame->extramask));
}
/* Set up to return from userspace. If provided, use a stub
already in userspace. */
if (ka->sa.sa_flags & SA_RESTORER) {
regs->gpr[GPR_LP] = (unsigned long) ka->sa.sa_restorer;
} else {
/* Note, these encodings are _little endian_! */
/* addi __NR_sigreturn, r0, r12 */
err |= __put_user(0x6600 | (__NR_sigreturn << 16),
frame->tramp + 0);
/* trap 0 */
err |= __put_user(0x010007e0,
frame->tramp + 1);
regs->gpr[GPR_LP] = (unsigned long)frame->tramp;
flush_cache_sigtramp (regs->gpr[GPR_LP]);
}
if (err)
goto give_sigsegv;
/* Set up registers for signal handler */
regs->gpr[GPR_SP] = (unsigned long) frame;
regs->gpr[GPR_ARG0] = signal; /* Arg for signal handler */
regs->pc = (unsigned long) ka->sa.sa_handler;
set_fs(USER_DS);
#if DEBUG_SIG
printk("SIG deliver (%s:%d): sp=%p pc=%08lx ra=%08lx\n",
current->comm, current->pid, frame, regs->pc, );
#endif
return;
give_sigsegv:
if (sig == SIGSEGV)
ka->sa.sa_handler = SIG_DFL;
force_sig(SIGSEGV, current);
}
static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
sigset_t *set, struct pt_regs *regs)
{
struct rt_sigframe *frame;
int err = 0;
int signal;
frame = get_sigframe(ka, regs, sizeof(*frame));
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
goto give_sigsegv;
signal = current_thread_info()->exec_domain
&& current_thread_info()->exec_domain->signal_invmap
&& sig < 32
? current_thread_info()->exec_domain->signal_invmap[sig]
: sig;
err |= __put_user(&frame->info, &frame->pinfo);
err |= __put_user(&frame->uc, &frame->puc);
err |= copy_siginfo_to_user(&frame->info, info);
/* Create the ucontext. */
err |= __put_user(0, &frame->uc.uc_flags);
err |= __put_user(0, &frame->uc.uc_link);
err |= __put_user((void *)current->sas_ss_sp,
&frame->uc.uc_stack.ss_sp);
err |= __put_user(sas_ss_flags(regs->gpr[GPR_SP]),
&frame->uc.uc_stack.ss_flags);
err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
err |= setup_sigcontext(&frame->uc.uc_mcontext,
regs, set->sig[0]);
err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
/* Set up to return from userspace. If provided, use a stub
already in userspace. */
if (ka->sa.sa_flags & SA_RESTORER) {
regs->gpr[GPR_LP] = (unsigned long) ka->sa.sa_restorer;
} else {
/* Note, these encodings are _little endian_! */
/* addi __NR_sigreturn, r0, r12 */
err |= __put_user(0x6600 | (__NR_sigreturn << 16),
frame->tramp + 0);
/* trap 0 */
err |= __put_user(0x010007e0,
frame->tramp + 1);
regs->gpr[GPR_LP] = (unsigned long)frame->tramp;
flush_cache_sigtramp (regs->gpr[GPR_LP]);
}
if (err)
goto give_sigsegv;
/* Set up registers for signal handler */
regs->gpr[GPR_SP] = (unsigned long) frame;
regs->gpr[GPR_ARG0] = signal; /* Arg for signal handler */
regs->pc = (unsigned long) ka->sa.sa_handler;
set_fs(USER_DS);
#if DEBUG_SIG
printk("SIG deliver (%s:%d): sp=%p pc=%08lx pr=%08lx\n",
current->comm, current->pid, frame, regs->pc, regs->pr);
#endif
return;
give_sigsegv:
if (sig == SIGSEGV)
ka->sa.sa_handler = SIG_DFL;
force_sig(SIGSEGV, current);
}
/*
* OK, we're invoking a handler
*/
static void
handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset,
struct pt_regs * regs)
{
struct k_sigaction *ka = &current->sig->action[sig-1];
/* Are we from a system call? */
if (PT_REGS_SYSCALL (regs)) {
/* If so, check system call restarting.. */
switch (regs->gpr[GPR_RVAL]) {
case -ERESTARTNOHAND:
regs->gpr[GPR_RVAL] = -EINTR;
break;
case -ERESTARTSYS:
if (!(ka->sa.sa_flags & SA_RESTART)) {
regs->gpr[GPR_RVAL] = -EINTR;
break;
}
/* fallthrough */
case -ERESTARTNOINTR:
regs->gpr[12] = PT_REGS_SYSCALL (regs);
regs->pc -= 4; /* Size of `trap 0' insn. */
}
PT_REGS_SET_SYSCALL (regs, 0);
}
/* Set up the stack frame */
if (ka->sa.sa_flags & SA_SIGINFO)
setup_rt_frame(sig, ka, info, oldset, regs);
else
setup_frame(sig, ka, oldset, regs);
if (ka->sa.sa_flags & SA_ONESHOT)
ka->sa.sa_handler = SIG_DFL;
if (!(ka->sa.sa_flags & SA_NODEFER)) {
spin_lock_irq(&current->sig->siglock);
sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
sigaddset(&current->blocked,sig);
recalc_sigpending();
spin_unlock_irq(&current->sig->siglock);
}
}
/*
* Note that 'init' is a special process: it doesn't get signals it doesn't
* want to handle. Thus you cannot kill init even with a SIGKILL even by
* mistake.
*
* Note that we go through the signals twice: once to check the signals that
* the kernel can handle, and then we build all the user-level signal handling
* stack-frames in one go after that.
*/
int do_signal(struct pt_regs *regs, sigset_t *oldset)
{
siginfo_t info;
int signr;
/*
* We want the common case to go fast, which
* is why we may in certain cases get here from
* kernel mode. Just return without doing anything
* if so.
*/
if (!user_mode(regs))
return 1;
if (!oldset)
oldset = &current->blocked;
signr = get_signal_to_deliver(&info, regs);
if (signr > 0) {
/* Whee! Actually deliver the signal. */
handle_signal(signr, &info, oldset, regs);
return 1;
}
/* Did we come from a system call? */
if (PT_REGS_SYSCALL (regs)) {
/* Restart the system call - no handlers present */
if (regs->gpr[GPR_RVAL] == -ERESTARTNOHAND ||
regs->gpr[GPR_RVAL] == -ERESTARTSYS ||
regs->gpr[GPR_RVAL] == -ERESTARTNOINTR) {
regs->gpr[12] = PT_REGS_SYSCALL (regs);
regs->pc -= 4; /* Size of `trap 0' insn. */
}
}
return 0;
}
/*
* arch/v850/kernel/sim.c -- Machine-specific stuff for GDB v850e simulator
*
* Copyright (C) 2001,02 NEC Corporation
* Copyright (C) 2001,02 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/swap.h>
#include <linux/bootmem.h>
#include <linux/irq.h>
#include <asm/atomic.h>
#include <asm/page.h>
#include <asm/machdep.h>
#include <asm/simsyscall.h>
#include "mach.h"
/* The name of a file containing the root filesystem. */
#define ROOT_FS "rootfs.image"
extern void simcons_setup (void);
extern void simcons_poll_ttys (void);
extern void set_mem_root (void *addr, size_t len, char *cmd_line);
static int read_file (const char *name,
unsigned long *addr, unsigned long *len,
const char **err);
void __init mach_setup (char **cmdline)
{
const char *err;
unsigned long root_dev_addr, root_dev_len;
printk (KERN_INFO "CPU: NEC V850E (GDB simulator)\n");
simcons_setup ();
printk (KERN_INFO "Reading root filesystem: %s", ROOT_FS);
if (read_file (ROOT_FS, &root_dev_addr, &root_dev_len, &err)) {
printk (" (size %luK)\n", root_dev_len / 1024);
set_mem_root ((void *)root_dev_addr, (size_t)root_dev_len,
*cmdline);
} else
printk ("...%s failed!\n", err);
}
void mach_get_physical_ram (unsigned long *ram_start, unsigned long *ram_len)
{
*ram_start = RAM_ADDR;
*ram_len = RAM_SIZE;
}
void __init mach_sched_init (struct irqaction *timer_action)
{
/* ...do magic timer initialization?... */
mach_tick = simcons_poll_ttys;
setup_irq (0, timer_action);
}
static void irq_nop (unsigned irq) { }
static unsigned irq_zero (unsigned irq) { return 0; }
static struct hw_interrupt_type sim_irq_type = {
"IRQ",
irq_zero, /* startup */
irq_nop, /* shutdown */
irq_nop, /* enable */
irq_nop, /* disable */
irq_nop, /* ack */
irq_nop, /* end */
};
void __init mach_init_irqs (void)
{
init_irq_handlers (0, NUM_MACH_IRQS, 1, &sim_irq_type);
}
void mach_gettimeofday (struct timespec *tv)
{
long timeval[2], timezone[2];
int rval = V850_SIM_SYSCALL (gettimeofday, timeval, timezone);
if (rval == 0) {
tv->tv_sec = timeval[0];
tv->tv_nsec = timeval[1] * 1000;
}
}
void machine_restart (char *__unused)
{
V850_SIM_SYSCALL (write, 1, "RESTART\n", 8);
V850_SIM_SYSCALL (exit, 0);
}
void machine_halt (void)
{
V850_SIM_SYSCALL (write, 1, "HALT\n", 5);
V850_SIM_SYSCALL (exit, 0);
}
void machine_power_off (void)
{
V850_SIM_SYSCALL (write, 1, "POWER OFF\n", 10);
V850_SIM_SYSCALL (exit, 0);
}
/* Load data from a file called NAME into ram. The address and length
of the data image are returned in ADDR and LEN. */
static int __init
read_file (const char *name,
unsigned long *addr, unsigned long *len,
const char **err)
{
int rval, fd;
unsigned long cur, left;
/* Note this is not a normal stat buffer, it's an ad-hoc
structure defined by the simulator. */
unsigned long stat_buf[10];
/* Stat the file to find out the length. */
rval = V850_SIM_SYSCALL (stat, name, stat_buf);
if (rval < 0) {
if (err) *err = "stat";
return 0;
}
*len = stat_buf[4];
/* Open the file; `0' is O_RDONLY. */
fd = V850_SIM_SYSCALL (open, name, 0);
if (fd < 0) {
if (err) *err = "open";
return 0;
}
*addr = (unsigned long)alloc_bootmem(*len);
if (! *addr) {
V850_SIM_SYSCALL (close, fd);
if (err) *err = "alloc_bootmem";
return 0;
}
cur = *addr;
left = *len;
while (left > 0) {
int chunk = V850_SIM_SYSCALL (read, fd, cur, left);
if (chunk <= 0)
break;
cur += chunk;
left -= chunk;
}
V850_SIM_SYSCALL (close, fd);
if (left > 0) {
/* Some read failed. */
free_bootmem (*addr, *len);
if (err) *err = "read";
return 0;
}
return 1;
}
/*
* arch/v850/kernel/sim85e2c.c -- Machine-specific stuff for
* V850E2 RTL simulator
*
* Copyright (C) 2002 NEC Corporation
* Copyright (C) 2002 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/swap.h>
#include <linux/bootmem.h>
#include <linux/irq.h>
#include <asm/atomic.h>
#include <asm/page.h>
#include <asm/machdep.h>
#include "mach.h"
extern void memcons_setup (void);
void __init mach_early_init (void)
{
extern int panic_timeout;
/* Don't stop the simulator at `halt' instructions. */
NOTHAL = 1;
/* The sim85e2c simulator tracks `undefined' values, so to make
debugging easier, we begin by zeroing out all otherwise
undefined registers. This is not strictly necessary.
The registers we zero are:
Every GPR except:
stack-pointer (r3)
task-pointer (r16)
our return addr (r31)
Every system register (SPR) that we know about except for
the PSW (SPR 5), which we zero except for the
disable-interrupts bit.
*/
/* GPRs */
asm volatile (" mov r0, r1 ; mov r0, r2 ");
asm volatile ("mov r0, r4 ; mov r0, r5 ; mov r0, r6 ; mov r0, r7 ");
asm volatile ("mov r0, r8 ; mov r0, r9 ; mov r0, r10; mov r0, r11");
asm volatile ("mov r0, r12; mov r0, r13; mov r0, r14; mov r0, r15");
asm volatile (" mov r0, r17; mov r0, r18; mov r0, r19");
asm volatile ("mov r0, r20; mov r0, r21; mov r0, r22; mov r0, r23");
asm volatile ("mov r0, r24; mov r0, r25; mov r0, r26; mov r0, r27");
asm volatile ("mov r0, r28; mov r0, r29; mov r0, r30");
/* SPRs */
asm volatile ("ldsr r0, 0; ldsr r0, 1; ldsr r0, 2; ldsr r0, 3");
asm volatile ("ldsr r0, 4");
asm volatile ("addi 0x20, r0, r1; ldsr r1, 5"); /* PSW */
asm volatile ("ldsr r0, 16; ldsr r0, 17; ldsr r0, 18; ldsr r0, 19");
asm volatile ("ldsr r0, 20");
/* Turn on the caches. */
NA85E2C_CACHE_BTSC
|= (NA85E2C_CACHE_BTSC_ICM | NA85E2C_CACHE_BTSC_DCM0);
NA85E2C_BUSM_BHC = 0xFFFF;
/* Ensure that the simulator halts on a panic, instead of going
into an infinite loop inside the panic function. */
panic_timeout = -1;
}
void __init mach_setup (char **cmdline)
{
printk (KERN_INFO "CPU: NEC V850E2 (sim85e2c simulator)\n");
memcons_setup ();
}
void mach_get_physical_ram (unsigned long *ram_start, unsigned long *ram_len)
{
/* There are 3 possible areas we can use:
IRAM (1MB) is fast for instruction fetches, but slow for data
DRAM (1020KB) is fast for data, but slow for instructions
ERAM is cached, so should be fast for both insns and data,
_but_ currently only supports write-through caching, so
writes are slow.
Since there's really no area that's good for general kernel
use, we use DRAM -- it won't be good for user programs
(which will be loaded into kernel allocated memory), but
currently we're more concerned with testing the kernel. */
*ram_start = DRAM_ADDR;
*ram_len = R0_RAM_ADDR - DRAM_ADDR;
}
void __init mach_sched_init (struct irqaction *timer_action)
{
/* The simulator actually cycles through all interrupts
periodically. We just pay attention to IRQ0, which gives us
1/64 the rate of the periodic interrupts. */
setup_irq (0, timer_action);
}
void mach_gettimeofday (struct timespec *tv)
{
tv->tv_sec = 0;
tv->tv_nsec = 0;
}
/* Interrupts */
struct nb85e_intc_irq_init irq_inits[] = {
{ "IRQ", 0, NUM_MACH_IRQS, 1, 7 },
{ 0 }
};
struct hw_interrupt_type hw_itypes[1];
/* Initialize interrupts. */
void __init mach_init_irqs (void)
{
nb85e_intc_init_irq_types (irq_inits, hw_itypes);
}
void machine_halt (void) __attribute__ ((noreturn));
void machine_halt (void)
{
SIMFIN = 0; /* Halt immediately. */
for (;;) {}
}
void machine_restart (char *__unused)
{
machine_halt ();
}
void machine_power_off (void)
{
machine_halt ();
}
/*
* arch/v850/kernel/simcons.c -- Console I/O for GDB v850e simulator
*
* Copyright (C) 2001,02 NEC Corporation
* Copyright (C) 2001,02 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#include <linux/kernel.h>
#include <linux/console.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/tty_driver.h>
#include <linux/init.h>
#include <asm/poll.h>
#include <asm/simsyscall.h>
/* Low-level console. */
static void simcons_write (struct console *co, const char *buf, unsigned len)
{
V850_SIM_SYSCALL (write, 1, buf, len);
}
static int simcons_read (struct console *co, const char *buf, unsigned len)
{
return V850_SIM_SYSCALL (read, 0, buf, len);
}
static kdev_t simcons_device (struct console *c)
{
return mk_kdev (TTY_MAJOR, 64 + c->index);
}
static struct console simcons =
{
.name = "simcons",
.write = simcons_write,
.read = simcons_read,
.device = simcons_device,
.flags = CON_PRINTBUFFER,
.index = -1,
};
/* Higher level TTY interface. */
static struct tty_struct *tty_table[1] = { 0 };
static struct termios *tty_termios[1] = { 0 };
static struct termios *tty_termios_locked[1] = { 0 };
static struct tty_driver tty_driver = { 0 };
static int tty_refcount = 0;
int simcons_tty_open (struct tty_struct *tty, struct file *filp)
{
return 0;
}
int simcons_tty_write (struct tty_struct *tty, int from_user,
const unsigned char *buf, int count)
{
return V850_SIM_SYSCALL (write, 1, buf, count);
}
int simcons_tty_write_room (struct tty_struct *tty)
{
/* Completely arbitrary. */
return 0x100000;
}
int simcons_tty_chars_in_buffer (struct tty_struct *tty)
{
/* We have no buffer. */
return 0;
}
int __init simcons_tty_init (void)
{
tty_driver.name = "simcons";
tty_driver.major = TTY_MAJOR;
tty_driver.minor_start = 64;
tty_driver.num = 1;
tty_driver.type = TTY_DRIVER_TYPE_SYSCONS;
tty_driver.refcount = &tty_refcount;
tty_driver.table = tty_table;
tty_driver.termios = tty_termios;
tty_driver.termios_locked = tty_termios_locked;
tty_driver.init_termios = tty_std_termios;
tty_driver.open = simcons_tty_open;
tty_driver.write = simcons_tty_write;
tty_driver.write_room = simcons_tty_write_room;
tty_driver.chars_in_buffer = simcons_tty_chars_in_buffer;
tty_register_driver (&tty_driver);
}
__initcall (simcons_tty_init);
/* Poll for input on the console, and if there's any, deliver it to the
tty driver. */
void simcons_poll_tty (struct tty_struct *tty)
{
int flip = 0, send_break = 0;
struct pollfd pfd;
pfd.fd = 0;
pfd.events = POLLIN;
if (V850_SIM_SYSCALL (poll, &pfd, 1, 0) > 0) {
if (pfd.revents & POLLIN) {
int left = TTY_FLIPBUF_SIZE - tty->flip.count;
if (left > 0) {
unsigned char *buf = tty->flip.char_buf_ptr;
int rd = V850_SIM_SYSCALL (read, 0, buf, left);
if (rd > 0) {
tty->flip.count += rd;
tty->flip.char_buf_ptr += rd;
memset (tty->flip.flag_buf_ptr, 0, rd);
tty->flip.flag_buf_ptr += rd;
flip = 1;
} else
send_break = 1;
}
} else if (pfd.revents & POLLERR)
send_break = 1;
}
if (send_break) {
tty_insert_flip_char (tty, 0, TTY_BREAK);
flip = 1;
}
if (flip)
tty_schedule_flip (tty);
}
void simcons_poll_ttys (void)
{
if (tty_table[0])
simcons_poll_tty (tty_table[0]);
}
void simcons_setup (void)
{
V850_SIM_SYSCALL (make_raw, 0);
register_console (&simcons);
printk (KERN_INFO "Console: GDB/v850e simulator stdio\n");
}
/*
* arch/v850/kernel/syscalls.c -- Various system-call definitions not
* defined in machine-independent code
*
* Copyright (C) 2001,02 NEC Corporation
* Copyright (C) 2001,02 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* This file was derived the ppc version, arch/ppc/kernel/syscalls.c
* ... which was derived from "arch/i386/kernel/sys_i386.c" by Gary Thomas;
* modified by Cort Dougan (cort@cs.nmt.edu)
* and Paul Mackerras (paulus@cs.anu.edu.au).
*/
#include <linux/config.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/sem.h>
#include <linux/msg.h>
#include <linux/shm.h>
#include <linux/stat.h>
#include <linux/mman.h>
#include <linux/sys.h>
#include <linux/ipc.h>
#include <linux/utsname.h>
#include <linux/file.h>
#include <asm/uaccess.h>
#include <asm/ipc.h>
#include <asm/semaphore.h>
/*
* sys_ipc() is the de-multiplexer for the SysV IPC calls..
*
* This is really horribly ugly.
*/
int
sys_ipc (uint call, int first, int second, int third, void *ptr, long fifth)
{
int version, ret;
version = call >> 16; /* hack for backward compatibility */
call &= 0xffff;
ret = -EINVAL;
switch (call) {
case SEMOP:
ret = sys_semop (first, (struct sembuf *)ptr, second);
break;
case SEMGET:
ret = sys_semget (first, second, third);
break;
case SEMCTL:
{
union semun fourth;
if (!ptr)
break;
if ((ret = verify_area (VERIFY_READ, ptr, sizeof(long)))
|| (ret = get_user(fourth.__pad, (void **)ptr)))
break;
ret = sys_semctl (first, second, third, fourth);
break;
}
case MSGSND:
ret = sys_msgsnd (first, (struct msgbuf *) ptr, second, third);
break;
case MSGRCV:
switch (version) {
case 0: {
struct ipc_kludge tmp;
if (!ptr)
break;
if ((ret = verify_area (VERIFY_READ, ptr, sizeof(tmp)))
|| (ret = copy_from_user(&tmp,
(struct ipc_kludge *) ptr,
sizeof (tmp))))
break;
ret = sys_msgrcv (first, tmp.msgp, second, tmp.msgtyp,
third);
break;
}
default:
ret = sys_msgrcv (first, (struct msgbuf *) ptr,
second, fifth, third);
break;
}
break;
case MSGGET:
ret = sys_msgget ((key_t) first, second);
break;
case MSGCTL:
ret = sys_msgctl (first, second, (struct msqid_ds *) ptr);
break;
case SHMAT:
switch (version) {
default: {
ulong raddr;
if ((ret = verify_area(VERIFY_WRITE, (ulong*) third,
sizeof(ulong))))
break;
ret = sys_shmat (first, (char *) ptr, second, &raddr);
if (ret)
break;
ret = put_user (raddr, (ulong *) third);
break;
}
case 1: /* iBCS2 emulator entry point */
if (!segment_eq(get_fs(), get_ds()))
break;
ret = sys_shmat (first, (char *) ptr, second,
(ulong *) third);
break;
}
break;
case SHMDT:
ret = sys_shmdt ((char *)ptr);
break;
case SHMGET:
ret = sys_shmget (first, second, third);
break;
case SHMCTL:
ret = sys_shmctl (first, second, (struct shmid_ds *) ptr);
break;
}
return ret;
}
/*
* sys_pipe() is the normal C calling standard for creating
* a pipe. It's not the way unix traditionally does this, though.
*/
int sys_pipe (int *fildes)
{
int fd[2];
int error;
error = do_pipe (fd);
if (!error) {
if (copy_to_user (fildes, fd, 2*sizeof (int)))
error = -EFAULT;
}
return error;
}
static inline unsigned long
do_mmap2 (unsigned long addr, size_t len,
unsigned long prot, unsigned long flags,
unsigned long fd, unsigned long pgoff)
{
struct file * file = NULL;
int ret = -EBADF;
flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
if (! (flags & MAP_ANONYMOUS)) {
if (!(file = fget (fd)))
goto out;
}
down_write (&current->mm->mmap_sem);
ret = do_mmap_pgoff (file, addr, len, prot, flags, pgoff);
up_write (&current->mm->mmap_sem);
if (file)
fput (file);
out:
return ret;
}
unsigned long sys_mmap2 (unsigned long addr, size_t len,
unsigned long prot, unsigned long flags,
unsigned long fd, unsigned long pgoff)
{
return do_mmap2 (addr, len, prot, flags, fd, pgoff);
}
unsigned long sys_mmap (unsigned long addr, size_t len,
unsigned long prot, unsigned long flags,
unsigned long fd, off_t offset)
{
int err = -EINVAL;
if (offset & ~PAGE_MASK)
goto out;
err = do_mmap2 (addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
out:
return err;
}
/*
* linux/arch/v850/kernel/time.c -- Arch-dependent timer functions
*
* Copyright (C) 1991, 1992, 1995, 2001, 2002 Linus Torvalds
*
* This file contains the v850-specific time handling details.
* Most of the stuff is located in the machine specific files.
*
* 1997-09-10 Updated NTP code according to technical memorandum Jan '96
* "A Kernel Model for Precision Timekeeping" by Dave Mills
*/
#include <linux/config.h> /* CONFIG_HEARTBEAT */
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/param.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
#include <linux/timex.h>
#include <linux/profile.h>
#include <asm/io.h>
#include "mach.h"
u64 jiffies_64;
#define TICK_SIZE (tick_nsec / 1000)
static inline void do_profile (unsigned long pc)
{
if (prof_buffer && current->pid) {
extern int _stext;
pc -= (unsigned long) &_stext;
pc >>= prof_shift;
if (pc < prof_len)
++prof_buffer[pc];
else
/*
* Don't ignore out-of-bounds PC values silently,
* put them into the last histogram slot, so if
* present, they will show up as a sharp peak.
*/
++prof_buffer[prof_len-1];
}
}
/*
* timer_interrupt() needs to keep up the real-time clock,
* as well as call the "do_timer()" routine every clocktick
*/
static void timer_interrupt (int irq, void *dummy, struct pt_regs *regs)
{
#if 0
/* last time the cmos clock got updated */
static long last_rtc_update=0;
#endif
/* may need to kick the hardware timer */
if (mach_tick)
mach_tick ();
do_timer (regs);
if (! user_mode (regs))
do_profile (regs->pc);
#if 0
/*
* If we have an externally synchronized Linux clock, then update
* CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
* called as close as possible to 500 ms before the new second starts.
*/
if ((time_status & STA_UNSYNC) == 0 &&
xtime.tv_sec > last_rtc_update + 660 &&
(xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 &&
(xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2) {
if (set_rtc_mmss (xtime.tv_sec) == 0)
last_rtc_update = xtime.tv_sec;
else
last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
}
#ifdef CONFIG_HEARTBEAT
/* use power LED as a heartbeat instead -- much more useful
for debugging -- based on the version for PReP by Cort */
/* acts like an actual heart beat -- ie thump-thump-pause... */
if (mach_heartbeat) {
static unsigned cnt = 0, period = 0, dist = 0;
if (cnt == 0 || cnt == dist)
mach_heartbeat ( 1 );
else if (cnt == 7 || cnt == dist+7)
mach_heartbeat ( 0 );
if (++cnt > period) {
cnt = 0;
/* The hyperbolic function below modifies the heartbeat period
* length in dependency of the current (5min) load. It goes
* through the points f(0)=126, f(1)=86, f(5)=51,
* f(inf)->30. */
period = ((672<<FSHIFT)/(5*avenrun[0]+(7<<FSHIFT))) + 30;
dist = period / 4;
}
}
#endif /* CONFIG_HEARTBEAT */
#endif /* 0 */
}
extern rwlock_t xtime_lock;
/*
* This version of gettimeofday has near microsecond resolution.
*/
void do_gettimeofday (struct timeval *tv)
{
#if 0 /* DAVIDM later if possible */
extern volatile unsigned long lost_ticks;
unsigned long lost;
#endif
unsigned long flags;
unsigned long usec, sec;
read_lock_irqsave (&xtime_lock, flags);
#if 0
usec = mach_gettimeoffset ? mach_gettimeoffset () : 0;
#else
usec = 0;
#endif
#if 0 /* DAVIDM later if possible */
lost = lost_ticks;
if (lost)
usec += lost * (1000000/HZ);
#endif
sec = xtime.tv_sec;
usec += xtime.tv_nsec / 1000;
read_unlock_irqrestore (&xtime_lock, flags);
while (usec >= 1000000) {
usec -= 1000000;
sec++;
}
tv->tv_sec = sec;
tv->tv_usec = usec;
}
void do_settimeofday (struct timeval *tv)
{
write_lock_irq (&xtime_lock);
/* This is revolting. We need to set the xtime.tv_nsec
* correctly. However, the value in this location is
* is value at the last tick.
* Discover what correction gettimeofday
* would have done, and then undo it!
*/
#if 0
tv->tv_usec -= mach_gettimeoffset ();
#endif
while (tv->tv_usec < 0) {
tv->tv_usec += 1000000;
tv->tv_sec--;
}
xtime.tv_sec = tv->tv_sec;
xtime.tv_nsec = tv->tv_usec * 1000;
time_adjust = 0; /* stop active adjtime () */
time_status |= STA_UNSYNC;
time_maxerror = NTP_PHASE_LIMIT;
time_esterror = NTP_PHASE_LIMIT;
write_unlock_irq (&xtime_lock);
}
static int timer_dev_id;
static struct irqaction timer_irqaction = {
timer_interrupt,
SA_INTERRUPT,
0,
"timer",
&timer_dev_id,
NULL
};
void time_init (void)
{
mach_gettimeofday (&xtime);
mach_sched_init (&timer_irqaction);
}
#include <linux/module.h>
#include <linux/linkage.h>
#include <linux/sched.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/user.h>
#include <linux/elfcore.h>
#include <linux/in6.h>
#include <linux/interrupt.h>
#include <linux/config.h>
#include <asm/setup.h>
#include <asm/pgalloc.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/semaphore.h>
#include <asm/checksum.h>
#include <asm/hardirq.h>
#include <asm/softirq.h>
#include <asm/current.h>
extern void *trap_table;
EXPORT_SYMBOL (trap_table);
/* platform dependent support */
extern void dump_thread (struct pt_regs *, struct user *);
EXPORT_SYMBOL (dump_thread);
EXPORT_SYMBOL (kernel_thread);
EXPORT_SYMBOL (__bug);
/* Networking helper routines. */
EXPORT_SYMBOL (csum_partial_copy);
EXPORT_SYMBOL (csum_partial_copy_from_user);
EXPORT_SYMBOL (ip_compute_csum);
EXPORT_SYMBOL (ip_fast_csum);
/* string / mem functions */
EXPORT_SYMBOL_NOVERS (strcpy);
EXPORT_SYMBOL_NOVERS (strncpy);
EXPORT_SYMBOL_NOVERS (strcat);
EXPORT_SYMBOL_NOVERS (strncat);
EXPORT_SYMBOL_NOVERS (strcmp);
EXPORT_SYMBOL_NOVERS (strncmp);
EXPORT_SYMBOL_NOVERS (strchr);
EXPORT_SYMBOL_NOVERS (strlen);
EXPORT_SYMBOL_NOVERS (strnlen);
EXPORT_SYMBOL_NOVERS (strpbrk);
EXPORT_SYMBOL_NOVERS (strtok);
EXPORT_SYMBOL_NOVERS (strrchr);
EXPORT_SYMBOL_NOVERS (strstr);
EXPORT_SYMBOL_NOVERS (memset);
EXPORT_SYMBOL_NOVERS (memcpy);
EXPORT_SYMBOL_NOVERS (memmove);
EXPORT_SYMBOL_NOVERS (memcmp);
EXPORT_SYMBOL_NOVERS (memscan);
/* semaphores */
EXPORT_SYMBOL_NOVERS (__down);
EXPORT_SYMBOL_NOVERS (__down_interruptible);
EXPORT_SYMBOL_NOVERS (__down_trylock);
EXPORT_SYMBOL_NOVERS (__up);
/*
* libgcc functions - functions that are used internally by the
* compiler... (prototypes are not correct though, but that
* doesn't really matter since they're not versioned).
*/
extern void __ashldi3 (void);
extern void __ashrdi3 (void);
extern void __lshrdi3 (void);
extern void __muldi3 (void);
extern void __negdi2 (void);
EXPORT_SYMBOL_NOVERS (__ashldi3);
EXPORT_SYMBOL_NOVERS (__ashrdi3);
EXPORT_SYMBOL_NOVERS (__lshrdi3);
EXPORT_SYMBOL_NOVERS (__muldi3);
EXPORT_SYMBOL_NOVERS (__negdi2);
#
# arch/v850/lib/Makefile
#
L_TARGET = lib.a
obj-y = ashrdi3.o ashldi3.o lshrdi3.o muldi3.o negdi2.o \
checksum.o memcpy.o memset.o
include $(TOPDIR)/Rules.make
/* ashldi3.c extracted from gcc-2.95.2/libgcc2.c which is: */
/* Copyright (C) 1989, 92-98, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
GNU CC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU CC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#define BITS_PER_UNIT 8
typedef int SItype __attribute__ ((mode (SI)));
typedef unsigned int USItype __attribute__ ((mode (SI)));
typedef int DItype __attribute__ ((mode (DI)));
typedef int word_type __attribute__ ((mode (__word__)));
struct DIstruct {SItype high, low;};
typedef union
{
struct DIstruct s;
DItype ll;
} DIunion;
DItype
__ashldi3 (DItype u, word_type b)
{
DIunion w;
word_type bm;
DIunion uu;
if (b == 0)
return u;
uu.ll = u;
bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
if (bm <= 0)
{
w.s.low = 0;
w.s.high = (USItype)uu.s.low << -bm;
}
else
{
USItype carries = (USItype)uu.s.low >> bm;
w.s.low = (USItype)uu.s.low << b;
w.s.high = ((USItype)uu.s.high << b) | carries;
}
return w.ll;
}
/* ashrdi3.c extracted from gcc-2.7.2/libgcc2.c which is: */
/* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
This file is part of GNU CC.
GNU CC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU CC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#define BITS_PER_UNIT 8
typedef int SItype __attribute__ ((mode (SI)));
typedef unsigned int USItype __attribute__ ((mode (SI)));
typedef int DItype __attribute__ ((mode (DI)));
typedef int word_type __attribute__ ((mode (__word__)));
struct DIstruct {SItype high, low;};
typedef union
{
struct DIstruct s;
DItype ll;
} DIunion;
DItype
__ashrdi3 (DItype u, word_type b)
{
DIunion w;
word_type bm;
DIunion uu;
if (b == 0)
return u;
uu.ll = u;
bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
if (bm <= 0)
{
/* w.s.high = 1..1 or 0..0 */
w.s.high = uu.s.high >> (sizeof (SItype) * BITS_PER_UNIT - 1);
w.s.low = uu.s.high >> -bm;
}
else
{
USItype carries = (USItype)uu.s.high << bm;
w.s.high = uu.s.high >> b;
w.s.low = ((USItype)uu.s.low >> b) | carries;
}
return w.ll;
}
/*
* INET An implementation of the TCP/IP protocol suite for the LINUX
* operating system. INET is implemented using the BSD Socket
* interface as the means of communication with the user level.
*
* MIPS specific IP/TCP/UDP checksumming routines
*
* Authors: Ralf Baechle, <ralf@waldorf-gmbh.de>
* Lots of code moved from tcp.c and ip.c; see those files
* for more names.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
* $Id: checksum.c,v 1.1 2002/09/28 14:58:40 gerg Exp $
*/
#include <net/checksum.h>
#include <linux/types.h>
#include <asm/byteorder.h>
#include <asm/string.h>
#include <asm/uaccess.h>
static inline unsigned short from32to16 (unsigned long sum)
{
unsigned int result;
/*
%0 %1
hsw %1, %0 H L L H
add %1, %0 H L H+L+C H+L
*/
asm ("hsw %1, %0; add %1, %0" : "=&r" (result) : "r" (sum));
return result >> 16;
}
static inline unsigned int do_csum(const unsigned char * buff, int len)
{
int odd, count;
unsigned int result = 0;
if (len <= 0)
goto out;
odd = 1 & (unsigned long) buff;
if (odd) {
result = be16_to_cpu(*buff);
len--;
buff++;
}
count = len >> 1; /* nr of 16-bit words.. */
if (count) {
if (2 & (unsigned long) buff) {
result += *(unsigned short *) buff;
count--;
len -= 2;
buff += 2;
}
count >>= 1; /* nr of 32-bit words.. */
if (count) {
unsigned int carry = 0;
do {
unsigned int w = *(unsigned int *) buff;
count--;
buff += 4;
result += carry;
result += w;
carry = (w > result);
} while (count);
result += carry;
result = (result & 0xffff) + (result >> 16);
}
if (len & 2) {
result += *(unsigned short *) buff;
buff += 2;
}
}
if (len & 1)
result += le16_to_cpu(*buff);
result = from32to16(result);
if (odd)
result = ((result >> 8) & 0xff) | ((result & 0xff) << 8);
out:
return result;
}
/*
* This is a version of ip_compute_csum() optimized for IP headers,
* which always checksum on 4 octet boundaries.
*/
unsigned short ip_fast_csum(unsigned char * iph, unsigned int ihl)
{
return ~do_csum(iph,ihl*4);
}
/*
* this routine is used for miscellaneous IP-like checksums, mainly
* in icmp.c
*/
unsigned short ip_compute_csum(const unsigned char * buff, int len)
{
return ~do_csum(buff,len);
}
/*
* computes a partial checksum, e.g. for TCP/UDP fragments
*/
unsigned int csum_partial(const unsigned char *buff, int len, unsigned int sum)
{
unsigned int result = do_csum(buff, len);
/* add in old sum, and carry.. */
result += sum;
if(sum > result)
result += 1;
return result;
}
/*
* copy while checksumming, otherwise like csum_partial
*/
unsigned int csum_partial_copy(const char *src, char *dst,
int len, unsigned int sum)
{
/*
* It's 2:30 am and I don't feel like doing it real ...
* This is lots slower than the real thing (tm)
*/
sum = csum_partial(src, len, sum);
memcpy(dst, src, len);
return sum;
}
/*
* Copy from userspace and compute checksum. If we catch an exception
* then zero the rest of the buffer.
*/
unsigned int csum_partial_copy_from_user (const char *src, char *dst,
int len, unsigned int sum,
int *err_ptr)
{
int missing;
missing = copy_from_user(dst, src, len);
if (missing) {
memset(dst + len - missing, 0, missing);
*err_ptr = -EFAULT;
}
return csum_partial(dst, len, sum);
}
/* lshrdi3.c extracted from gcc-2.7.2/libgcc2.c which is: */
/* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
This file is part of GNU CC.
GNU CC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU CC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#define BITS_PER_UNIT 8
typedef int SItype __attribute__ ((mode (SI)));
typedef unsigned int USItype __attribute__ ((mode (SI)));
typedef int DItype __attribute__ ((mode (DI)));
typedef int word_type __attribute__ ((mode (__word__)));
struct DIstruct {SItype high, low;};
typedef union
{
struct DIstruct s;
DItype ll;
} DIunion;
DItype
__lshrdi3 (DItype u, word_type b)
{
DIunion w;
word_type bm;
DIunion uu;
if (b == 0)
return u;
uu.ll = u;
bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
if (bm <= 0)
{
w.s.high = 0;
w.s.low = (USItype)uu.s.high >> -bm;
}
else
{
USItype carries = (USItype)uu.s.high << bm;
w.s.high = (USItype)uu.s.high >> b;
w.s.low = ((USItype)uu.s.low >> b) | carries;
}
return w.ll;
}
/*
* arch/v850/lib/memcpy.c -- Memory copying
*
* Copyright (C) 2001,02 NEC Corporation
* Copyright (C) 2001,02 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#include <linux/types.h>
#include <asm/string.h>
#define CHUNK_SIZE 32 /* bytes */
#define CHUNK_ALIGNED(addr) (((unsigned long)addr & 0x3) == 0)
/* Note that this macro uses 8 call-clobbered registers (not including
R1), which are few enough so that the following functions don't need
to spill anything to memory. It also uses R1, which is nominally
reserved for the assembler, but here it should be OK. */
#define COPY_CHUNK(src, dst) \
asm ("mov %0, ep;" \
"sld.w 0[ep], r1; sld.w 4[ep], r12;" \
"sld.w 8[ep], r13; sld.w 12[ep], r14;" \
"sld.w 16[ep], r15; sld.w 20[ep], r17;" \
"sld.w 24[ep], r18; sld.w 28[ep], r19;" \
"mov %1, ep;" \
"sst.w r1, 0[ep]; sst.w r12, 4[ep];" \
"sst.w r13, 8[ep]; sst.w r14, 12[ep];" \
"sst.w r15, 16[ep]; sst.w r17, 20[ep];" \
"sst.w r18, 24[ep]; sst.w r19, 28[ep]" \
:: "r" (src), "r" (dst) \
: "r1", "r12", "r13", "r14", "r15", \
"r17", "r18", "r19", "ep", "memory");
void *memcpy (void *dst, const void *src, __kernel_size_t size)
{
char *_dst = dst;
const char *_src = src;
if (size >= CHUNK_SIZE && CHUNK_ALIGNED(_src) && CHUNK_ALIGNED(_dst)) {
/* Copy large blocks efficiently. */
unsigned count;
for (count = size / CHUNK_SIZE; count; count--) {
COPY_CHUNK (_src, _dst);
_src += CHUNK_SIZE;
_dst += CHUNK_SIZE;
}
size %= CHUNK_SIZE;
}
if (size > 0)
do
*_dst++ = *_src++;
while (--size);
return dst;
}
void bcopy (const char *src, char *dst, int size)
{
memcpy (dst, src, size);
}
void *memmove (void *dst, const void *src, __kernel_size_t size)
{
if ((unsigned long)dst < (unsigned long)src
|| (unsigned long)src + size < (unsigned long)dst)
return memcpy (dst, src, size);
else {
char *_dst = dst + size;
const char *_src = src + size;
if (size >= CHUNK_SIZE
&& CHUNK_ALIGNED (_src) && CHUNK_ALIGNED (_dst))
{
/* Copy large blocks efficiently. */
unsigned count;
for (count = size / CHUNK_SIZE; count; count--) {
_src -= CHUNK_SIZE;
_dst -= CHUNK_SIZE;
COPY_CHUNK (_src, _dst);
}
size %= CHUNK_SIZE;
}
if (size > 0)
do
*--_dst = *--_src;
while (--size);
return _dst;
}
}
/*
* arch/v850/lib/memset.c -- Memory initialization
*
* Copyright (C) 2001,02 NEC Corporation
* Copyright (C) 2001,02 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#include <linux/types.h>
void *memset (void *dst, int val, __kernel_size_t count)
{
if (count) {
register unsigned loop;
register void *ptr asm ("ep") = dst;
/* replicate VAL into a long. */
val &= 0xff;
val |= val << 8;
val |= val << 16;
/* copy initial unaligned bytes. */
if ((long)ptr & 1) {
*((char *)ptr)++ = val;
count--;
}
if (count > 2 && ((long)ptr & 2)) {
*((short *)ptr)++ = val;
count -= 2;
}
/* 32-byte copying loop. */
for (loop = count / 32; loop; loop--) {
asm ("sst.w %0, 0[ep]; sst.w %0, 4[ep];"
"sst.w %0, 8[ep]; sst.w %0, 12[ep];"
"sst.w %0, 16[ep]; sst.w %0, 20[ep];"
"sst.w %0, 24[ep]; sst.w %0, 28[ep]"
:: "r" (val) : "memory");
ptr += 32;
}
count %= 32;
/* long copying loop. */
for (loop = count / 4; loop; loop--)
*((long *)ptr)++ = val;
count %= 4;
/* finish up with any trailing bytes. */
if (count & 2)
*((short *)ptr)++ = val;
if (count & 1)
*(char *)ptr = val;
}
return dst;
}
/* muldi3.c extracted from gcc-2.7.2.3/libgcc2.c and
gcc-2.7.2.3/longlong.h which is: */
/* Copyright (C) 1989, 1992, 1993, 1994, 1995, 2001 Free Software Foundation, Inc.
This file is part of GNU CC.
GNU CC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU CC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#define umul_ppmm(w1, w0, u, v) \
__asm__ ("mulu %3, %0, %1" \
: "=r" ((USItype)(w0)), \
"=r" ((USItype)(w1)) \
: "%0" ((USItype)(u)), \
"r" ((USItype)(v)))
#define __umulsidi3(u, v) \
({DIunion __w; \
umul_ppmm (__w.s.high, __w.s.low, u, v); \
__w.ll; })
typedef int SItype __attribute__ ((mode (SI)));
typedef unsigned int USItype __attribute__ ((mode (SI)));
typedef int DItype __attribute__ ((mode (DI)));
typedef int word_type __attribute__ ((mode (__word__)));
struct DIstruct {SItype high, low;};
typedef union
{
struct DIstruct s;
DItype ll;
} DIunion;
DItype
__muldi3 (DItype u, DItype v)
{
DIunion w;
DIunion uu, vv;
uu.ll = u,
vv.ll = v;
w.ll = __umulsidi3 (uu.s.low, vv.s.low);
w.s.high += ((USItype) uu.s.low * (USItype) vv.s.high
+ (USItype) uu.s.high * (USItype) vv.s.low);
return w.ll;
}
/*
* arch/v850/lib/negdi2.c -- 64-bit negation
*
* Copyright (C) 2001 NEC Corporation
* Copyright (C) 2001 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
typedef int DItype __attribute__ ((mode (DI)));
DItype __negdi2 (DItype x)
{
__asm__ __volatile__
("not r6, r10;"
"add 1, r10;"
"setf c, r6;"
"not r7, r11;"
"add r6, r11"
::: "r6", "r7", "r10", "r11");
}
/* Linker script for the Midas labs RTE-V850E/MA1-CB evaluation board
(CONFIG_RTE_CB_MA1), with kernel in SRAM, under Multi debugger. */
/* Note, all symbols are prefixed with an extra `_' for compatibility with
the existing linux sources. */
_jiffies = _jiffies_64 ;
MEMORY {
/* 1MB of SRAM; we can't use the last 32KB, because it's used by
the monitor scratch-RAM. This memory is mirrored 4 times. */
SRAM : ORIGIN = 0x00400000, LENGTH = 0x000F8000
/* Monitor scratch RAM; only the interrupt vectors should go here. */
MRAM : ORIGIN = 0x004F8000, LENGTH = 0x00008000
/* 32MB of SDRAM. */
SDRAM : ORIGIN = 0x00800000, LENGTH = 0x02000000
}
SECTIONS {
.text : {
__kram_start = . ;
__stext = . ;
*(.text)
*(.exit.text) /* 2.5 convention */
*(.text.exit) /* 2.4 convention */
*(.text.lock)
*(.exitcall.exit)
__real_etext = . ; /* There may be data after here. */
*(.rodata)
. = ALIGN (0x4) ;
*(.kstrtab)
. = ALIGN (4) ;
*(.call_table_data)
*(.call_table_text)
. = ALIGN (16) ; /* Exception table. */
___start___ex_table = . ;
*(__ex_table)
___stop___ex_table = . ;
___start___ksymtab = . ;/* Kernel symbol table. */
*(__ksymtab)
___stop___ksymtab = . ;
. = ALIGN (4) ;
__etext = . ;
} > SRAM
.data ALIGN (0x4) : {
__sdata = . ;
___data_start = . ;
*(.data)
*(.exit.data) /* 2.5 convention */
*(.data.exit) /* 2.4 convention */
. = ALIGN (16) ;
*(.data.cacheline_aligned)
. = ALIGN (0x2000) ;
*(.data.init_task)
. = ALIGN (0x2000) ;
__edata = . ;
} > SRAM
.bss ALIGN (0x4) : {
__sbss = . ;
*(.bss)
*(COMMON)
. = ALIGN (4) ;
__init_stack_end = . ;
__ebss = . ;
} > SRAM
.init ALIGN (4096) : {
__init_start = . ;
*(.init.text) /* 2.5 convention */
*(.init.data)
*(.text.init) /* 2.4 convention */
*(.data.init)
. = ALIGN (16) ;
___setup_start = . ;
*(.init.setup) /* 2.5 convention */
*(.setup.init) /* 2.4 convention */
___setup_end = . ;
___initcall_start = . ;
*(.initcall.init)
*(.initcall1.init)
*(.initcall2.init)
*(.initcall3.init)
*(.initcall4.init)
*(.initcall5.init)
*(.initcall6.init)
*(.initcall7.init)
. = ALIGN (4) ;
___initcall_end = . ;
} > SRAM
/* This provides address at which the interrupt vectors are
initially loaded by the loader. */
__intv_load_start = ALIGN (0x10) ;
/* Interrupt vector space. Because we're using the monitor
ROM, Instead of the native interrupt vector, we must use the
`alternate interrupt vector' area. Note that this is in
`SRAM' space, which is not currently used by the kernel (the
kernel uses `SDRAM' space). */
/* We can't load the interrupt vectors directly into their
target location, because the monitor ROM for the GHS Multi
debugger barfs if we try. Unfortunately, Multi also doesn't
deal correctly with ELF sections where the LMA and VMA differ
(it just ignores the LMA), so we can't use that feature to
work around the problem! What we do instead is just put the
interrupt vectors into a normal section, and have the
`mach_early_init' function for Midas boards do the necessary
copying and relocation at runtime (this section basically
only contains `jr' instructions, so it's not that hard).
This the section structure I initially tried to use (which more
accurately expresses the intent):
.intv 0x007F8000 : AT (ADDR (.init) + SIZEOF (.init)) {
...
} > MRAM
*/
.intv ALIGN (0x10) : {
__intv_start = . ;
*(.intv.reset) /* Reset vector */
*(.intv.common) /* Vectors common to all v850e proc. */
*(.intv.mach) /* Machine-specific int. vectors. */
__intv_end = . ;
/* This is here so that when we free init memory, the initial
load-area of the interrupt vectors is freed too. */
__init_end = __intv_end;
__kram_end = __init_end ;
} > SRAM
.bootmap ALIGN (4096) : {
__bootmap = . ;
. = . + 4096 ; /* enough for 128MB. */
} > SRAM
/* Device contents for the root filesystem. */
.root : {
__root_fs_image_start = . ;
*(.root)
__root_fs_image_end = . ;
} > SDRAM
}
/* Linker script for the Midas labs RTE-V850E/MA1-CB evaluation board
(CONFIG_RTE_CB_MA1), with kernel in ROM. */
/* Note, all symbols are prefixed with an extra `_' for compatibility with
the existing linux sources. */
_jiffies = _jiffies_64 ;
MEMORY {
ROM : ORIGIN = 0x00000000, LENGTH = 0x00100000
/* 1MB of SRAM. This memory is mirrored 4 times. */
SRAM : ORIGIN = 0x00400000, LENGTH = 0x00100000
/* 32MB of SDRAM. */
SDRAM : ORIGIN = 0x00800000, LENGTH = 0x02000000
}
SECTIONS {
/* Interrupt vector space. */
.intv {
__intv_start = . ;
*(.intv.reset) /* Reset vector */
*(.intv.common) /* Vectors common to all v850e proc. */
*(.intv.mach) /* Machine-specific int. vectors. */
__intv_end = . ;
} > ROM
.text : {
__stext = . ;
*(.text)
*(.exit.text) /* 2.5 convention */
*(.text.exit) /* 2.4 convention */
*(.text.lock)
*(.exitcall.exit)
__real_etext = . ; /* There may be data after here. */
*(.rodata)
. = ALIGN (0x4) ;
*(.kstrtab)
. = ALIGN (16) ; /* Exception table. */
___start___ex_table = . ;
*(__ex_table)
___stop___ex_table = . ;
___start___ksymtab = . ;/* Kernel symbol table. */
*(__ksymtab)
___stop___ksymtab = . ;
. = ALIGN (4) ;
__etext = . ;
} > ROM
__data_load_start = . ;
.data : {
__kram_start = . ;
__sdata = . ;
___data_start = . ;
*(.data)
*(.exit.data) /* 2.5 convention */
*(.data.exit) /* 2.4 convention */
. = ALIGN (16) ;
*(.data.cacheline_aligned)
. = ALIGN (0x2000) ;
*(.data.init_task)
. = ALIGN (0x2000) ;
__edata = . ;
} > SRAM AT> ROM
.bss ALIGN (0x4) : {
__sbss = . ;
*(.bss)
*(COMMON)
. = ALIGN (4) ;
__init_stack_end = . ;
__ebss = . ;
} > SRAM
.init ALIGN (4096) : {
__init_start = . ;
*(.init.text) /* 2.5 convention */
*(.init.data)
*(.text.init) /* 2.4 convention */
*(.data.init)
. = ALIGN (16) ;
___setup_start = . ;
*(.init.setup) /* 2.5 convention */
*(.setup.init) /* 2.4 convention */
___setup_end = . ;
___initcall_start = . ;
*(.initcall.init)
*(.initcall1.init)
*(.initcall2.init)
*(.initcall3.init)
*(.initcall4.init)
*(.initcall5.init)
*(.initcall6.init)
*(.initcall7.init)
. = ALIGN (4) ;
___initcall_end = . ;
__init_end = . ;
__kram_end = . ;
} > SRAM
.bootmap ALIGN (4096) : {
__bootmap = . ;
. = . + 4096 ; /* enough for 128MB. */
} > SRAM
/* device contents for the root filesystem. */
.root ALIGN (4096) {
__root_fs_image_start = . ;
*(.root)
__root_fs_image_end = . ;
} > SDRAM
}
/* Linker script for the Midas labs RTE-V850E/MA1-CB evaluation board
(CONFIG_RTE_CB_MA1), with kernel in SDRAM, under Multi debugger. */
/* Note, all symbols are prefixed with an extra `_' for compatibility with
the existing linux sources. */
_jiffies = _jiffies_64 ;
MEMORY {
/* 1MB of SRAM; we can't use the last 32KB, because it's used by
the monitor scratch-RAM. This memory is mirrored 4 times. */
SRAM : ORIGIN = 0x00400000, LENGTH = 0x000F8000
/* Monitor scratch RAM; only the interrupt vectors should go here. */
MRAM : ORIGIN = 0x004F8000, LENGTH = 0x00008000
/* 32MB of SDRAM. */
SDRAM : ORIGIN = 0x00800000, LENGTH = 0x02000000
}
SECTIONS {
.bootmap : {
__bootmap = . ;
. = . + 4096 ; /* enough for 128MB. */
} > SRAM
.text : {
__kram_start = . ;
__stext = . ;
*(.text)
*(.exit.text) /* 2.5 convention */
*(.text.exit) /* 2.4 convention */
*(.text.lock)
*(.exitcall.exit)
__real_etext = . ; /* There may be data after here. */
*(.rodata)
. = ALIGN (0x4) ;
*(.kstrtab)
. = ALIGN (4) ;
*(.call_table_data)
*(.call_table_text)
. = ALIGN (16) ; /* Exception table. */
___start___ex_table = . ;
*(__ex_table)
___stop___ex_table = . ;
___start___ksymtab = . ;/* Kernel symbol table. */
*(__ksymtab)
___stop___ksymtab = . ;
. = ALIGN (4) ;
__etext = . ;
} > SDRAM
.data ALIGN (0x4) : {
__sdata = . ;
___data_start = . ;
*(.data)
*(.exit.data) /* 2.5 convention */
*(.data.exit) /* 2.4 convention */
. = ALIGN (16) ;
*(.data.cacheline_aligned)
. = ALIGN (0x2000) ;
*(.data.init_task)
. = ALIGN (0x2000) ;
__edata = . ;
} > SDRAM
.bss ALIGN (0x4) : {
__sbss = . ;
*(.bss)
*(COMMON)
. = ALIGN (4) ;
__init_stack_end = . ;
__ebss = . ;
} > SDRAM
.init ALIGN (4096) : {
__init_start = . ;
*(.init.text) /* 2.5 convention */
*(.init.data)
*(.text.init) /* 2.4 convention */
*(.data.init)
. = ALIGN (16) ;
___setup_start = . ;
*(.init.setup) /* 2.5 convention */
*(.setup.init) /* 2.4 convention */
___setup_end = . ;
___initcall_start = . ;
*(.initcall.init)
*(.initcall1.init)
*(.initcall2.init)
*(.initcall3.init)
*(.initcall4.init)
*(.initcall5.init)
*(.initcall6.init)
*(.initcall7.init)
. = ALIGN (4) ;
___initcall_end = . ;
} > SDRAM
/* This provides address at which the interrupt vectors are
initially loaded by the loader. */
__intv_load_start = ALIGN (0x10) ;
/* Interrupt vector space. Because we're using the monitor
ROM, Instead of the native interrupt vector, we must use the
`alternate interrupt vector' area. Note that this is in
`SRAM' space, which is not currently used by the kernel (the
kernel uses `SDRAM' space). */
/* We can't load the interrupt vectors directly into their
target location, because the monitor ROM for the GHS Multi
debugger barfs if we try. Unfortunately, Multi also doesn't
deal correctly with ELF sections where the LMA and VMA differ
(it just ignores the LMA), so we can't use that feature to
work around the problem! What we do instead is just put the
interrupt vectors into a normal section, and have the
`mach_early_init' function for Midas boards do the necessary
copying and relocation at runtime (this section basically
only contains `jr' instructions, so it's not that hard).
This the section structure I initially tried to use (which more
accurately expresses the intent):
.intv 0x007F8000 : AT (ADDR (.init) + SIZEOF (.init)) {
...
} > MRAM
*/
.intv ALIGN (0x10) : {
__intv_start = . ;
*(.intv.reset) /* Reset vector */
*(.intv.common) /* Vectors common to all v850e proc. */
*(.intv.mach) /* Machine-specific int. vectors. */
__intv_end = . ;
/* This is here so that when we free init memory, the initial
load-area of the interrupt vectors is freed too. */
__init_end = __intv_end;
__kram_end = . ;
} > SDRAM
/* Device contents for the root filesystem. */
.root ALIGN (4096) : {
__root_fs_image_start = . ;
*(.root)
__root_fs_image_end = . ;
} > SDRAM
}
/* Linker script for the gdb v850e simulator (CONFIG_V850E_SIM). */
/* Note, all symbols are prefixed with an extra `_' for compatibility with
the existing linux sources. */
_jiffies = _jiffies_64 ;
MEMORY {
/* Interrupt vectors. */
INTV : ORIGIN = 0x0, LENGTH = 0xe0
/* 16MB of RAM.
This must match RAM_ADDR and RAM_SIZE in include/asm-v580/sim.h */
RAM : ORIGIN = 0x8F000000, LENGTH = 0x01000000
}
SECTIONS {
.intv : {
__intv_start = . ;
*(.intv.reset) /* Reset vector */
*(.intv.common) /* Vectors common to all v850e proc. */
*(.intv.mach) /* Machine-specific int. vectors. */
__intv_end = . ;
} > INTV
.text : {
__kram_start = . ;
__stext = . ;
*(.text)
*(.exit.text) /* 2.5 convention */
*(.text.exit) /* 2.4 convention */
*(.text.lock)
*(.exitcall.exit)
__real_etext = . ; /* There may be data after here. */
*(.rodata)
. = ALIGN (0x4) ;
*(.kstrtab)
. = ALIGN (4) ;
*(.call_table_data)
*(.call_table_text)
. = ALIGN (16) ; /* Exception table. */
___start___ex_table = . ;
*(__ex_table)
___stop___ex_table = . ;
___start___ksymtab = . ;/* Kernel symbol table. */
*(__ksymtab)
___stop___ksymtab = . ;
. = ALIGN (4) ;
__etext = . ;
} > RAM
.data ALIGN (0x4) : {
__sdata = . ;
*(.data)
*(.exit.data) /* 2.5 convention */
*(.data.exit) /* 2.4 convention */
. = ALIGN (16) ;
*(.data.cacheline_aligned)
. = ALIGN (0x2000) ;
*(.data.init_task)
. = ALIGN (0x2000) ;
__edata = . ;
} > RAM
.bss ALIGN (0x4) : {
__sbss = . ;
*(.bss)
*(COMMON)
. = ALIGN (4) ;
__init_stack_end = . ;
__ebss = . ;
} > RAM
.init ALIGN (4096) : {
__init_start = . ;
*(.init.text) /* 2.5 convention */
*(.init.data)
*(.text.init) /* 2.4 convention */
*(.data.init)
. = ALIGN (16) ;
___setup_start = . ;
*(.init.setup) /* 2.5 convention */
*(.setup.init) /* 2.4 convention */
___setup_end = . ;
___initcall_start = . ;
*(.initcall.init)
*(.initcall1.init)
*(.initcall2.init)
*(.initcall3.init)
*(.initcall4.init)
*(.initcall5.init)
*(.initcall6.init)
*(.initcall7.init)
. = ALIGN (4) ;
___initcall_end = . ;
__init_end = . ;
__kram_end = . ;
} > RAM
.bootmap ALIGN (4096) : {
__bootmap = . ;
. = . + 4096 ; /* enough for 128MB. */
} > RAM
}
/* Linker script for the sim85e2c simulator, which is a verilog simulation of
the V850E2 NA85E2C cpu core (CONFIG_V850E2_SIM85E2C). */
/* Note, all symbols are prefixed with an extra `_' for compatibility with
the existing linux sources. */
_jiffies = _jiffies_64 ;
MEMORY {
/* 1MB of `instruction RAM', starting at 0.
Instruction fetches are much faster from IRAM than from DRAM.
This should match IRAM_ADDR in "include/asm-v580/sim85e2c.h". */
IRAM : ORIGIN = 0x00000000, LENGTH = 0x00100000
/* 1MB of `data RAM', below and contiguous with the I/O space.
Data fetches are much faster from DRAM than from IRAM.
This should match DRAM_ADDR in "include/asm-v580/sim85e2c.h". */
DRAM : ORIGIN = 0xfff00000, LENGTH = 0x000ff000
/* We have to load DRAM at a mirror-address of 0x1ff00000,
because the simulator's preprocessing script isn't smart
enough to deal with the above LMA. */
DRAM_LOAD : ORIGIN = 0x1ff00000, LENGTH = 0x000ff000
/* `external ram' (CS1 area), comes after IRAM.
This should match ERAM_ADDR in "include/asm-v580/sim85e2c.h". */
ERAM : ORIGIN = 0x00100000, LENGTH = 0x07f00000
}
SECTIONS {
.intv : {
__intv_start = . ;
*(.intv) /* Interrupt vectors. */
*(.intv.reset) /* Reset vector */
*(.intv.common) /* Vectors common to all v850e proc. */
*(.intv.mach) /* Machine-specific int. vectors. */
__intv_end = . ;
} > IRAM
.text : {
__stext = . ;
*(.text)
*(.exit.text) /* 2.5 convention */
*(.text.exit) /* 2.4 convention */
*(.text.lock)
*(.exitcall.exit)
__real_etext = . ; /* There may be data after here. */
*(.rodata)
. = ALIGN (0x4) ;
*(.kstrtab)
. = ALIGN (4) ;
*(.call_table_data)
*(.call_table_text)
. = ALIGN (16) ; /* Exception table. */
___start___ex_table = . ;
*(__ex_table)
___stop___ex_table = . ;
___start___ksymtab = . ;/* Kernel symbol table. */
*(__ksymtab)
___stop___ksymtab = . ;
. = ALIGN (4) ;
__etext = . ;
} > IRAM
.init ALIGN (4096) : {
__init_start = . ;
*(.init.text) /* 2.5 convention */
*(.init.data)
*(.text.init) /* 2.4 convention */
*(.data.init)
. = ALIGN (16) ;
___setup_start = . ;
*(.init.setup) /* 2.5 convention */
*(.setup.init) /* 2.4 convention */
___setup_end = . ;
___initcall_start = . ;
*(.initcall.init)
*(.initcall1.init)
*(.initcall2.init)
*(.initcall3.init)
*(.initcall4.init)
*(.initcall5.init)
*(.initcall6.init)
*(.initcall7.init)
. = ALIGN (4) ;
___initcall_end = . ;
__init_end = . ;
} > IRAM
.data : {
__kram_start = . ;
__sdata = . ;
*(.data)
*(.exit.data) /* 2.5 convention */
*(.data.exit) /* 2.4 convention */
. = ALIGN (16) ;
*(.data.cacheline_aligned)
. = ALIGN (0x2000) ;
*(.data.init_task)
. = ALIGN (0x2000) ;
__edata = . ;
} > DRAM AT> DRAM_LOAD
.bss ALIGN (0x4) : {
__sbss = . ;
*(.bss)
*(COMMON)
. = ALIGN (4) ;
__init_stack_end = . ;
__ebss = . ;
} > DRAM AT> DRAM_LOAD
/* Device contents for the root filesystem. */
.root ALIGN (4096) : {
__root_fs_image_start = . ;
*(.root)
__root_fs_image_end = . ;
} > DRAM AT> DRAM_LOAD
.memcons : {
_memcons_output = . ;
. = . + 0x8000 ;
_memcons_output_end = . ;
__kram_end = . ;
} > DRAM AT> DRAM_LOAD
.bootmap ALIGN (4096) : {
__bootmap = . ;
. = . + 4096 ; /* enough for 128MB. */
} > DRAM AT> DRAM_LOAD
}
#include <linux/config.h>
#ifdef CONFIG_V850E_SIM
# include "sim.ld"
#endif
#ifdef CONFIG_V850E2_SIM85E2C
# include "sim85e2c.ld"
#endif
#ifdef CONFIG_V850E2_FPGA85E2C
# include "fpga85e2c.ld"
#endif
#ifdef CONFIG_V850E2_ANNA
# ifdef CONFIG_ROM_KERNEL
# include "anna-rom.ld"
# else
# include "anna.ld"
# endif
#endif
#ifdef CONFIG_RTE_CB_MA1
# ifdef CONFIG_ROM_KERNEL
# include "rte_ma1_cb-rom.ld"
# elif CONFIG_RTE_CB_MA1_KSRAM
# include "rte_ma1_cb-ksram.ld"
# else /* !CONFIG_ROM_KERNEL && !CONFIG_RTE_CB_MA1_KSRAM */
# include "rte_ma1_cb.ld"
# endif /* CONFIG_ROM_KERNEL */
#endif /* CONFIG_RTE_CB_MA1 */
#ifndef __V850_A_OUT_H__
#define __V850_A_OUT_H__
struct exec
{
unsigned long a_info; /* Use macros N_MAGIC, etc for access */
unsigned a_text; /* length of text, in bytes */
unsigned a_data; /* length of data, in bytes */
unsigned a_bss; /* length of uninitialized data area for file, in bytes */
unsigned a_syms; /* length of symbol table data in file, in bytes */
unsigned a_entry; /* start address */
unsigned a_trsize; /* length of relocation info for text, in bytes */
unsigned a_drsize; /* length of relocation info for data, in bytes */
};
#define N_TRSIZE(a) ((a).a_trsize)
#define N_DRSIZE(a) ((a).a_drsize)
#define N_SYMSIZE(a) ((a).a_syms)
#endif /* __V850_A_OUT_H__ */
/*
* include/asm-v850/anna.h -- Anna V850E2 evaluation cpu chip/board
*
* Copyright (C) 2001,2002 NEC Corporation
* Copyright (C) 2001,2002 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#ifndef __V850_ANNA_H__
#define __V850_ANNA_H__
#define CPU_ARCH "v850e2"
#define CPU_MODEL "v850e2/anna"
#define CPU_MODEL_LONG "NEC V850E2/Anna"
#define PLATFORM "anna"
#define PLATFORM_LONG "NEC/Midas lab V850E2/Anna evaluation board"
#define CPU_CLOCK_FREQ 200000000 /* 200MHz */
#define SYS_CLOCK_FREQ 33300000 /* 33.3MHz */
/* 1MB of static RAM. This memory is mirrored 64 times. */
#define SRAM_ADDR 0x04000000
#define SRAM_SIZE 0x00100000 /* 1MB */
/* 64MB of DRAM. */
#define SDRAM_ADDR 0x08000000
#define SDRAM_SIZE 0x04000000 /* 64MB */
/* For <asm/page.h> */
#define PAGE_OFFSET SRAM_ADDR
/* We use on-chip RAM, for a few miscellaneous variables that must be
accessible using a load instruction relative to R0. The Anna chip has
128K of `dLB' ram nominally located at 0xFFF00000, but it's mirrored
every 128K, so we can use the `last mirror' (except for the portion at
the top which is overridden by I/O space). In addition, the early
sample chip we're using has lots of memory errors in the dLB ram, so we
use a specially chosen location that has at least 20 bytes of contiguous
valid memory (xxxF0020 - xxxF003F). */
#define R0_RAM_ADDR 0xFFFF8020
/* Anna specific control registers. */
#define ANNA_CSC_ADDR(n) (0xFFFFF060 + (n) * 2)
#define ANNA_CSC(n) (*(volatile u16 *)ANNA_CSC_ADDR(n))
#define ANNA_BPC_ADDR 0xFFFFF064
#define ANNA_BPC (*(volatile u16 *)ANNA_BPC_ADDR)
#define ANNA_BSC_ADDR 0xFFFFF066
#define ANNA_BSC (*(volatile u16 *)ANNA_BSC_ADDR)
#define ANNA_BEC_ADDR 0xFFFFF068
#define ANNA_BEC (*(volatile u16 *)ANNA_BEC_ADDR)
#define ANNA_BHC_ADDR 0xFFFFF06A
#define ANNA_BHC (*(volatile u16 *)ANNA_BHC_ADDR)
#define ANNA_BCT_ADDR(n) (0xFFFFF480 + (n) * 2)
#define ANNA_BCT(n) (*(volatile u16 *)ANNA_BCT_ADDR(n))
#define ANNA_DWC_ADDR(n) (0xFFFFF484 + (n) * 2)
#define ANNA_DWC(n) (*(volatile u16 *)ANNA_DWC_ADDR(n))
#define ANNA_BCC_ADDR 0xFFFFF488
#define ANNA_BCC (*(volatile u16 *)ANNA_BCC_ADDR)
#define ANNA_ASC_ADDR 0xFFFFF48A
#define ANNA_ASC (*(volatile u16 *)ANNA_ASC_ADDR)
#define ANNA_LBS_ADDR 0xFFFFF48E
#define ANNA_LBS (*(volatile u16 *)ANNA_LBS_ADDR)
#define ANNA_SCR3_ADDR 0xFFFFF4AC
#define ANNA_SCR3 (*(volatile u16 *)ANNA_SCR3_ADDR)
#define ANNA_RFS3_ADDR 0xFFFFF4AE
#define ANNA_RFS3 (*(volatile u16 *)ANNA_RFS3_ADDR)
#define ANNA_ILBEN_ADDR 0xFFFFF7F2
#define ANNA_ILBEN (*(volatile u16 *)ANNA_ILBEN_ADDR)
/* I/O port P0-P3. */
/* Direct I/O. Bits 0-7 are pins Pn0-Pn7. */
#define ANNA_PORT_IO_ADDR(n) (0xFFFFF400 + (n) * 2)
#define ANNA_PORT_IO(n) (*(volatile u8 *)ANNA_PORT_IO_ADDR(n))
/* Port mode (for direct I/O, 0 = output, 1 = input). */
#define ANNA_PORT_PM_ADDR(n) (0xFFFFF410 + (n) * 2)
#define ANNA_PORT_PM(n) (*(volatile u8 *)ANNA_PORT_PM_ADDR(n))
/* NB85E-style interrupt system. */
#include <asm/nb85e_intc.h>
/* Hardware-specific interrupt numbers (in the kernel IRQ namespace). */
#define IRQ_INTP(n) (n) /* Pnnn (pin) interrupts 0-15 */
#define IRQ_INTP_NUM 16
#define IRQ_INTOV(n) (0x10 + (n)) /* 0-2 */
#define IRQ_INTOV_NUM 2
#define IRQ_INTCCC(n) (0x12 + (n))
#define IRQ_INTCCC_NUM 4
#define IRQ_INTCMD(n) (0x16 + (n)) /* interval timer interrupts 0-5 */
#define IRQ_INTCMD_NUM 6
#define IRQ_INTDMA(n) (0x1C + (n)) /* DMA interrupts 0-3 */
#define IRQ_INTDMA_NUM 4
#define IRQ_INTDMXER 0x20
#define IRQ_INTSRE(n) (0x21 + (n)*3) /* UART 0-1 reception error */
#define IRQ_INTSRE_NUM 2
#define IRQ_INTSR(n) (0x22 + (n)*3) /* UART 0-1 reception completion */
#define IRQ_INTSR_NUM 2
#define IRQ_INTST(n) (0x23 + (n)*3) /* UART 0-1 transmission completion */
#define IRQ_INTST_NUM 2
#define NUM_CPU_IRQS 64
#ifndef __ASSEMBLY__
/* Initialize chip interrupts. */
extern void anna_init_irqs (void);
#endif
/* Anna UART details (basically the same as the V850E/MA1, but 2 channels). */
#define NB85E_UART_NUM_CHANNELS 2
#define NB85E_UART_BASE_FREQ (SYS_CLOCK_FREQ / 2)
#define NB85E_UART_CHIP_NAME "V850E2/NA85E2A"
/* This is a function that gets called before configuring the UART. */
#define NB85E_UART_PRE_CONFIGURE anna_uart_pre_configure
#ifndef __ASSEMBLY__
extern void anna_uart_pre_configure (unsigned chan,
unsigned cflags, unsigned baud);
#endif
/* Timer C details. */
#define NB85E_TIMER_C_BASE_ADDR 0xFFFFF600
/* Timer D details (the Anna actually has 5 of these; should change later). */
#define NB85E_TIMER_D_BASE_ADDR 0xFFFFF540
#define NB85E_TIMER_D_TMD_BASE_ADDR (NB85E_TIMER_D_BASE_ADDR + 0x0)
#define NB85E_TIMER_D_CMD_BASE_ADDR (NB85E_TIMER_D_BASE_ADDR + 0x2)
#define NB85E_TIMER_D_TMCD_BASE_ADDR (NB85E_TIMER_D_BASE_ADDR + 0x4)
#define NB85E_TIMER_D_BASE_FREQ SYS_CLOCK_FREQ
#define NB85E_TIMER_D_TMCD_CS_MIN 1 /* min 2^1 divider */
/* For <asm/param.h> */
#ifndef HZ
#define HZ 100
#endif
#endif /* __V850_ANNA_H__ */
/*
* include/asm-v850/asm.h -- Macros for writing assembly code
*
* Copyright (C) 2001,02 NEC Corporation
* Copyright (C) 2001,02 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#define G_ENTRY(name) \
.align 4; \
.globl name; \
.type name,@function; \
name
#define END(name) \
.size name,.-name
#define L_ENTRY(name) \
.align 4; \
.type name,@function; \
name
/*
* include/asm-v850/atomic.h -- Atomic operations
*
* Copyright (C) 2001,02 NEC Corporation
* Copyright (C) 2001,02 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#ifndef __V850_ATOMIC_H__
#define __V850_ATOMIC_H__
#include <linux/config.h>
#include <asm/system.h>
#ifdef CONFIG_SMP
#error SMP not supported
#endif
typedef struct { int counter; } atomic_t;
#define ATOMIC_INIT(i) { (i) }
#ifdef __KERNEL__
#define atomic_read(v) ((v)->counter)
#define atomic_set(v,i) (((v)->counter) = (i))
extern __inline__ int atomic_add_return (int i, volatile atomic_t *v)
{
unsigned long flags;
int res;
local_irq_save (flags);
res = v->counter + i;
v->counter = res;
local_irq_restore (flags);
return res;
}
static __inline__ int atomic_sub_return (int i, volatile atomic_t *v)
{
unsigned long flags;
int res;
local_irq_save (flags);
res = v->counter - i;
v->counter = res;
local_irq_restore (flags);
return res;
}
static __inline__ void atomic_clear_mask (unsigned long mask, unsigned long *addr)
{
unsigned long flags;
local_irq_save (flags);
*addr &= ~mask;
local_irq_restore (flags);
}
#endif
#define atomic_add(i, v) atomic_add_return ((i), (v))
#define atomic_sub(i, v) atomic_sub_return ((i), (v))
#define atomic_dec_return(v) atomic_sub_return (1, (v))
#define atomic_inc_return(v) atomic_add_return (1, (v))
#define atomic_inc(v) atomic_inc_return (v)
#define atomic_dec(v) atomic_dec_return (v)
#define atomic_sub_and_test(i,v) (atomic_sub_return ((i), (v)) == 0)
#define atomic_dec_and_test(v) (atomic_sub_return (1, (v)) == 0)
#define atomic_add_negative(i,v) (atomic_add_return ((i), (v)) < 0)
/* Atomic operations are already serializing on ARM */
#define smp_mb__before_atomic_dec() barrier()
#define smp_mb__after_atomic_dec() barrier()
#define smp_mb__before_atomic_inc() barrier()
#define smp_mb__after_atomic_inc() barrier()
#endif /* __V850_ATOMIC_H__ */
/*
* include/asm-v850/bitops.h -- Bit operations
*
* Copyright (C) 2001,02 NEC Corporation
* Copyright (C) 2001,02 Miles Bader <miles@gnu.org>
* Copyright (C) 1992 Linus Torvalds.
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*/
#ifndef __V850_BITOPS_H__
#define __V850_BITOPS_H__
#include <linux/config.h>
#include <linux/compiler.h> /* unlikely */
#include <asm/byteorder.h> /* swab32 */
#include <asm/system.h> /* interrupt enable/disable */
#ifdef __KERNEL__
/*
* The __ functions are not atomic
*/
/*
* ffz = Find First Zero in word. Undefined if no zero exists,
* so code should check against ~0UL first..
*/
extern __inline__ unsigned long ffz (unsigned long word)
{
unsigned long result = 0;
while (word & 1) {
result++;
word >>= 1;
}
return result;
}
/* In the following constant-bit-op macros, a "g" constraint is used when
we really need an integer ("i" constraint). This is to avoid
warnings/errors from the compiler in the case where the associated
operand _isn't_ an integer, and shouldn't produce bogus assembly because
use of that form is protected by a guard statement that checks for
constants, and should otherwise be removed by the optimizer. This
_usually_ works -- however, __builtin_constant_p returns true for a
variable with a known constant value too, and unfortunately gcc will
happily put the variable in a register and use the register for the "g"
constraint'd asm operand. To avoid the latter problem, we add a
constant offset to the operand and subtract it back in the asm code;
forcing gcc to do arithmetic on the value is usually enough to get it
to use a real constant value. This is horrible, and ultimately
unreliable too, but it seems to work for now (hopefully gcc will offer
us more control in the future, so we can do a better job). */
#define __const_bit_op(op, nr, addr) \
({ __asm__ (op " (%0 - 0x123), %1" \
:: "g" (((nr) & 0x7) + 0x123), \
"m" (*((char *)(addr) + ((nr) >> 3))) \
: "memory"); })
#define __var_bit_op(op, nr, addr) \
({ int __nr = (nr); \
__asm__ (op " %0, [%1]" \
:: "r" (__nr & 0x7), \
"r" ((char *)(addr) + (__nr >> 3)) \
: "memory"); })
#define __bit_op(op, nr, addr) \
((__builtin_constant_p (nr) && (unsigned)(nr) <= 0x7FFFF) \
? __const_bit_op (op, nr, addr) \
: __var_bit_op (op, nr, addr))
#define __set_bit(nr, addr) __bit_op ("set1", nr, addr)
#define __clear_bit(nr, addr) __bit_op ("clr1", nr, addr)
#define __change_bit(nr, addr) __bit_op ("not1", nr, addr)
/* The bit instructions used by `non-atomic' variants are actually atomic. */
#define set_bit __set_bit
#define clear_bit __clear_bit
#define change_bit __change_bit
#define __const_tns_bit_op(op, nr, addr) \
({ int __tns_res; \
__asm__ ("tst1 (%1 - 0x123), %2; setf nz, %0; " op " (%1 - 0x123), %2" \
: "=&r" (__tns_res) \
: "g" (((nr) & 0x7) + 0x123), \
"m" (*((char *)(addr) + ((nr) >> 3))) \
: "memory"); \
__tns_res; \
})
#define __var_tns_bit_op(op, nr, addr) \
({ int __nr = (nr); \
int __tns_res; \
__asm__ ("tst1 %1, [%2]; setf nz, %0; " op " %1, [%2]" \
: "=&r" (__tns_res) \
: "r" (__nr & 0x7), \
"r" ((char *)(addr) + (__nr >> 3)) \
: "memory"); \
__tns_res; \
})
#define __tns_bit_op(op, nr, addr) \
((__builtin_constant_p (nr) && (unsigned)(nr) <= 0x7FFFF) \
? __const_tns_bit_op (op, nr, addr) \
: __var_tns_bit_op (op, nr, addr))
#define __tns_atomic_bit_op(op, nr, addr) \
({ int __tns_atomic_res, __tns_atomic_flags; \
local_irq_save (__tns_atomic_flags); \
__tns_atomic_res = __tns_bit_op (op, nr, addr); \
local_irq_restore (__tns_atomic_flags); \
__tns_atomic_res; \
})
#define __test_and_set_bit(nr, addr) __tns_bit_op ("set1", nr, addr)
#define test_and_set_bit(nr, addr) __tns_atomic_bit_op ("set1", nr, addr)
#define __test_and_clear_bit(nr, addr) __tns_bit_op ("clr1", nr, addr)
#define test_and_clear_bit(nr, addr) __tns_atomic_bit_op ("clr1", nr, addr)
#define __test_and_change_bit(nr, addr) __tns_bit_op ("not1", nr, addr)
#define test_and_change_bit(nr, addr) __tns_atomic_bit_op ("not1", nr, addr)
#define __const_test_bit(nr, addr) \
({ int __test_bit_res; \
__asm__ ("tst1 (%1 - 0x123), %2; setf nz, %0" \
: "=r" (__test_bit_res) \
: "g" (((nr) & 0x7) + 0x123), \
"m" (*((const char *)(addr) + ((nr) >> 3)))); \
__test_bit_res; \
})
extern __inline__ int __test_bit (int nr, void *addr)
{
int res;
__asm__ ("tst1 %1, [%2]; setf nz, %0"
: "=r" (res)
: "r" (nr & 0x7), "r" (addr + (nr >> 3)));
return res;
}
#define test_bit(nr,addr) \
((__builtin_constant_p (nr) && (unsigned)(nr) <= 0x7FFFF) \
? __const_test_bit ((nr), (addr)) \
: __test_bit ((nr), (addr)))
/* clear_bit doesn't provide any barrier for the compiler. */
#define smp_mb__before_clear_bit() barrier ()
#define smp_mb__after_clear_bit() barrier ()
#define find_first_zero_bit(addr, size) \
find_next_zero_bit ((addr), (size), 0)
extern __inline__ int find_next_zero_bit (void *addr, int size, int offset)
{
unsigned long *p = ((unsigned long *) addr) + (offset >> 5);
unsigned long result = offset & ~31UL;
unsigned long tmp;
if (offset >= size)
return size;
size -= result;
offset &= 31UL;
if (offset) {
tmp = * (p++);
tmp |= ~0UL >> (32-offset);
if (size < 32)
goto found_first;
if (~tmp)
goto found_middle;
size -= 32;
result += 32;
}
while (size & ~31UL) {
if (~ (tmp = * (p++)))
goto found_middle;
result += 32;
size -= 32;
}
if (!size)
return result;
tmp = *p;
found_first:
tmp |= ~0UL >> size;
found_middle:
return result + ffz (tmp);
}
#define ffs(x) generic_ffs (x)
#define fls(x) generic_fls (x)
#define __ffs(x) ffs(x)
/*
* This is just `generic_ffs' from <linux/bitops.h>, except that it assumes
* that at least one bit is set, and returns the real index of the bit
* (rather than the bit index + 1, like ffs does).
*/
static inline int sched_ffs(int x)
{
int r = 0;
if (!(x & 0xffff)) {
x >>= 16;
r += 16;
}
if (!(x & 0xff)) {
x >>= 8;
r += 8;
}
if (!(x & 0xf)) {
x >>= 4;
r += 4;
}
if (!(x & 3)) {
x >>= 2;
r += 2;
}
if (!(x & 1)) {
x >>= 1;
r += 1;
}
return r;
}
/*
* Every architecture must define this function. It's the fastest
* way of searching a 140-bit bitmap where the first 100 bits are
* unlikely to be set. It's guaranteed that at least one of the 140
* bits is set.
*/
static inline int sched_find_first_bit(unsigned long *b)
{
unsigned offs = 0;
while (! *b) {
b++;
offs += 32;
}
return sched_ffs (*b) + offs;
}
/*
* hweightN: returns the hamming weight (i.e. the number
* of bits set) of a N-bit word
*/
#define hweight32(x) generic_hweight32 (x)
#define hweight16(x) generic_hweight16 (x)
#define hweight8(x) generic_hweight8 (x)
#define ext2_set_bit test_and_set_bit
#define ext2_clear_bit test_and_clear_bit
#define ext2_test_bit test_bit
#define ext2_find_first_zero_bit find_first_zero_bit
#define ext2_find_next_zero_bit find_next_zero_bit
/* Bitmap functions for the minix filesystem. */
#define minix_test_and_set_bit test_and_set_bit
#define minix_set_bit set_bit
#define minix_test_and_clear_bit test_and_clear_bit
#define minix_test_bit test_bit
#define minix_find_first_zero_bit find_first_zero_bit
#endif /* __KERNEL__ */
#endif /* __V850_BITOPS_H__ */
/*
* include/asm-v850e/bugs.h
*
* Copyright (C) 1994 Linus Torvalds
*/
/*
* This is included by init/main.c to check for architecture-dependent bugs.
*
* Needs:
* void check_bugs(void);
*/
static void check_bugs(void)
{
}
/*
* include/asm-v850/byteorder.h -- Endian id and conversion ops
*
* Copyright (C) 2001 NEC Corporation
* Copyright (C) 2001 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#ifndef __V850_BYTEORDER_H__
#define __V850_BYTEORDER_H__
#include <asm/types.h>
#ifdef __GNUC__
static __inline__ __const__ __u32 ___arch__swab32 (__u32 word)
{
__u32 res;
__asm__ ("bsw %1, %0" : "=r" (res) : "r" (word));
return res;
}
static __inline__ __const__ __u16 ___arch__swab16 (__u16 half_word)
{
__u16 res;
__asm__ ("bsh %1, %0" : "=r" (res) : "r" (half_word));
return res;
}
#define __arch__swab32(x) ___arch__swab32(x)
#define __arch__swab16(x) ___arch__swab16(x)
#if !defined(__STRICT_ANSI__) || defined(__KERNEL__)
# define __BYTEORDER_HAS_U64__
# define __SWAB_64_THRU_32__
#endif
#endif /* __GNUC__ */
#include <linux/byteorder/little_endian.h>
#endif /* __V850_BYTEORDER_H__ */
/*
* include/asm-v850/cache.h -- Cache operations
*
* Copyright (C) 2001 NEC Corporation
* Copyright (C) 2001 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#ifndef __V850_CACHE_H__
#define __V850_CACHE_H__
/* All cache operations are machine-dependent. */
#include <asm/machdep.h>
#ifndef L1_CACHE_BYTES
/* This processor has no cache, so just choose an arbitrary value. */
#define L1_CACHE_BYTES 16
#endif
#endif /* __V850_CACHE_H__ */
/*
* include/asm-v850/cacheflush.h
*
* Copyright (C) 2001,02 NEC Corporation
* Copyright (C) 2001,02 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#ifndef __V850_CACHEFLUSH_H__
#define __V850_CACHEFLUSH_H__
/* Somebody depends on this; sigh... */
#include <linux/mm.h>
#include <asm/setup.h>
#include <asm/machdep.h>
#ifndef flush_cache_all
/* If there's no flush_cache_all macro defined by <asm/machdep.h>, then
this processor has no cache, so just define these as nops. */
#define flush_cache_all() ((void)0)
#define flush_cache_mm(mm) ((void)0)
#define flush_cache_range(vma, start, end) ((void)0)
#define flush_cache_page(vma, vmaddr) ((void)0)
#define flush_page_to_ram(page) ((void)0)
#define flush_dcache_page(page) ((void)0)
#define flush_icache() ((void)0)
#define flush_icache_range(start, end) ((void)0)
#define flush_icache_page(vma,pg) ((void)0)
#define flush_icache_user_range(vma,pg,adr,len) ((void)0)
#define flush_cache_sigtramp(vaddr) ((void)0)
#endif /* !flush_cache_all */
#endif /* __V850_CACHEFLUSH_H__ */
/*
* include/asm-v850/checksum.h -- Checksum ops
*
* Copyright (C) 2001 NEC Corporation
* Copyright (C) 2001 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#ifndef __V850_CHECKSUM_H__
#define __V850_CHECKSUM_H__
/*
* computes the checksum of a memory block at buff, length len,
* and adds in "sum" (32-bit)
*
* returns a 32-bit number suitable for feeding into itself
* or csum_tcpudp_magic
*
* this function must be called with even lengths, except
* for the last fragment, which may be odd
*
* it's best to have buff aligned on a 32-bit boundary
*/
extern unsigned int csum_partial (const unsigned char * buff, int len,
unsigned int sum);
/*
* the same as csum_partial, but copies from src while it
* checksums
*
* here even more important to align src and dst on a 32-bit (or even
* better 64-bit) boundary
*/
extern unsigned csum_partial_copy (const char *src, char *dst, int len,
unsigned sum);
/*
* the same as csum_partial_copy, but copies from user space.
*
* here even more important to align src and dst on a 32-bit (or even
* better 64-bit) boundary
*/
extern unsigned csum_partial_copy_from_user (const char *src, char *dst,
int len, unsigned sum,
int *csum_err);
#define csum_partial_copy_nocheck(src, dst, len, sum) \
csum_partial_copy ((src), (dst), (len), (sum))
unsigned short ip_fast_csum (unsigned char *iph, unsigned int ihl);
/*
* Fold a partial checksum
*/
static inline unsigned int csum_fold (unsigned long sum)
{
unsigned int result;
/*
%0 %1
hsw %1, %0 H L L H
add %1, %0 H L H+L+C H+L
*/
asm ("hsw %1, %0; add %1, %0" : "=&r" (result) : "r" (sum));
return (~result) >> 16;
}
/*
* computes the checksum of the TCP/UDP pseudo-header
* returns a 16-bit checksum, already complemented
*/
static inline unsigned int
csum_tcpudp_nofold (unsigned long saddr, unsigned long daddr,
unsigned short len,
unsigned short proto, unsigned int sum)
{
int __carry;
__asm__ ("add %2, %0;"
"setf c, %1;"
"add %1, %0;"
"add %3, %0;"
"setf c, %1;"
"add %1, %0;"
"add %4, %0;"
"setf c, %1;"
"add %1, %0"
: "=&r" (sum), "=&r" (__carry)
: "r" (daddr), "r" (saddr),
"r" (ntohs (len) + (proto << 8)),
"0" (sum));
return sum;
}
static inline unsigned short int
csum_tcpudp_magic (unsigned long saddr, unsigned long daddr,
unsigned short len,
unsigned short proto, unsigned int sum)
{
return csum_fold (csum_tcpudp_nofold (saddr, daddr, len, proto, sum));
}
/*
* this routine is used for miscellaneous IP-like checksums, mainly
* in icmp.c
*/
extern unsigned short ip_compute_csum (const unsigned char * buff, int len);
#endif /* __V850_CHECKSUM_H__ */
/*
* include/asm-v850/clinkage.h -- Macros to reflect C symbol-naming conventions
*
* Copyright (C) 2001,02 NEC Corporatione
* Copyright (C) 2001,02 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#ifndef __CLINKAGE_H__
#define __V850_CLINKAGE_H__
#include <asm/macrology.h>
#include <asm/asm.h>
#define C_SYMBOL_NAME(name) macrology_paste(_, name)
#define C_SYMBOL_STRING(name) macrology_stringify(C_SYMBOL_NAME(name))
#define C_ENTRY(name) G_ENTRY(C_SYMBOL_NAME(name))
#define C_END(name) END(C_SYMBOL_NAME(name))
#endif /* __V850_CLINKAGE_H__ */
/*
* include/asm-v850/current.h -- Current task
*
* Copyright (C) 2001,02 NEC Corporation
* Copyright (C) 2001,02 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#ifndef __V850_CURRENT_H__
#define __V850_CURRENT_H__
#include <asm/macrology.h>
#include <asm/thread_info.h>
/* Register used to hold the current task pointer while in the kernel.
Any `call clobbered' register without a special meaning should be OK,
but check asm/v850/kernel/entry.S to be sure. */
#define CURRENT_TASK_REGNUM 16
#define CURRENT_TASK macrology_paste (r, CURRENT_TASK_REGNUM)
#ifdef __ASSEMBLY__
/* Put a pointer to the current task structure into REG. */
#define GET_CURRENT_TASK(reg) \
GET_CURRENT_THREAD(reg); \
ld.w TI_TASK[reg], reg
#else /* !__ASSEMBLY__ */
/* A pointer to the current task. */
register struct task_struct *current \
__asm__ (macrology_stringify (CURRENT_TASK));
#endif /* __ASSEMBLY__ */
#endif /* _V850_CURRENT_H */
/*
* include/asm-v850/delay.h -- Delay routines, using a pre-computed
* "loops_per_second" value
*
* Copyright (C) 2001 NEC Corporation
* Copyright (C) 2001 Miles Bader <miles@gnu.org>
* Copyright (C) 1994 Hamish Macdonald
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*/
#ifndef __V850_DELAY_H__
#define __V850_DELAY_H__
#include <asm/param.h>
extern __inline__ void __delay(unsigned long loops)
{
__asm__ __volatile__ ("1: add -1, %0; bnz 1b"
: "=r" (loops) : "0" (loops));
}
/*
* Use only for very small delays ( < 1 msec). Should probably use a
* lookup table, really, as the multiplications take much too long with
* short delays. This is a "reasonable" implementation, though (and the
* first constant multiplications gets optimized away if the delay is
* a constant)
*/
extern unsigned long loops_per_jiffy;
extern __inline__ void udelay(unsigned long usecs)
{
register unsigned long full_loops, part_loops;
full_loops = ((usecs * HZ) / 1000000) * loops_per_jiffy;
usecs %= (1000000 / HZ);
part_loops = (usecs * HZ * loops_per_jiffy) / 1000000;
__delay(full_loops + part_loops);
}
#endif /* __V850_DELAY_H__ */
#ifndef __V850_DIV64_H__
#define __V850_DIV64_H__
/* We're not 64-bit, but... */
#define do_div(n,base) ({ \
int __res; \
__res = ((unsigned long) n) % (unsigned) base; \
n = ((unsigned long) n) / (unsigned) base; \
__res; })
#endif /* __V850_DIV64_H__ */
#ifndef __V850_DMA_H__
#define __V850_DMA_H__
/* What should this be? */
#define MAX_DMA_ADDRESS 0xFFFFFFFF
/* reserve a DMA channel */
extern int request_dma (unsigned int dmanr, const char * device_id);
/* release it again */
extern void free_dma (unsigned int dmanr);
#ifdef CONFIG_PCI
extern int isa_dma_bridge_buggy;
#else
#define isa_dma_bridge_buggy (0)
#endif
#endif /* __V850_DMA_H__ */
#ifndef __V850_ELF_H__
#define __V850_ELF_H__
/*
* ELF register definitions..
*/
#include <asm/ptrace.h>
#include <asm/user.h>
#include <asm/byteorder.h>
typedef unsigned long elf_greg_t;
#define ELF_NGREG (sizeof (struct pt_regs) / sizeof(elf_greg_t))
typedef elf_greg_t elf_gregset_t[ELF_NGREG];
typedef struct user_fpu_struct elf_fpregset_t;
/*
* This is used to ensure we don't load something for the wrong architecture.
*/
#define elf_check_arch(x) ( (x)->e_machine == EM_CYGNUS_V850 )
/*
* These are used to set parameters in the core dumps.
*/
#define ELF_CLASS ELFCLASS32
#ifdef __LITTLE_ENDIAN__
#define ELF_DATA ELFDATA2LSB
#else
#define ELF_DATA ELFDATA2MSB
#endif
#define ELF_ARCH EM_V850
#define USE_ELF_CORE_DUMP
#define ELF_EXEC_PAGESIZE 4096
#define ELF_CORE_COPY_REGS(_dest,_regs) \
memcpy((char *) &_dest, (char *) _regs, \
sizeof(struct pt_regs));
/* This yields a mask that user programs can use to figure out what
instruction set this CPU supports. This could be done in user space,
but it's not easy, and we've already done it here. */
#define ELF_HWCAP (0)
/* This yields a string that ld.so will use to load implementation
specific libraries for optimization. This is more specific in
intent than poking at uname or /proc/cpuinfo.
For the moment, we have only optimizations for the Intel generations,
but that could change... */
#define ELF_PLATFORM (NULL)
#define ELF_PLAT_INIT(_r) \
do { \
_r->gpr[0] = _r->gpr[1] = _r->gpr[2] = _r->gpr[3] = \
_r->gpr[4] = _r->gpr[5] = _r->gpr[6] = _r->gpr[7] = \
_r->gpr[8] = _r->gpr[9] = _r->gpr[10] = _r->gpr[11] = \
_r->gpr[12] = _r->gpr[13] = _r->gpr[14] = _r->gpr[15] = \
_r->gpr[16] = _r->gpr[17] = _r->gpr[18] = _r->gpr[19] = \
_r->gpr[20] = _r->gpr[21] = _r->gpr[22] = _r->gpr[23] = \
_r->gpr[24] = _r->gpr[25] = _r->gpr[26] = _r->gpr[27] = \
_r->gpr[28] = _r->gpr[29] = _r->gpr[30] = _r->gpr[31] = \
0; \
} while (0)
#ifdef __KERNEL__
#define SET_PERSONALITY(ex, ibcs2) set_personality(PER_LINUX_32BIT)
#endif
#endif /* __V850_ELF_H__ */
/*
* include/asm-v850/entry.h -- Definitions used by low-level trap handlers
*
* Copyright (C) 2001,02 NEC Corporation
* Copyright (C) 2001,02 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#ifndef __V850_ENTRY_H__
#define __V850_ENTRY_H__
#include <asm/ptrace.h>
#include <asm/machdep.h>
/* If true, system calls save and restore all registers (except result
registers, of course). If false, then `call clobbered' registers
will not be preserved, on the theory that system calls are basically
function calls anyway, and the caller should be able to deal with it.
This is a security risk, of course, as `internal' values may leak out
after a system call, but that certainly doesn't matter very much for
a processor with no MMU protection! For a protected-mode kernel, it
would be faster to just zero those registers before returning. */
#define TRAPS_PRESERVE_CALL_CLOBBERED_REGS 0
/* If TRAPS_PRESERVE_CALL_CLOBBERED_REGS is false, then zero `call
clobbered' registers before returning from a system call. */
#define TRAPS_ZERO_CALL_CLOBBERED_REGS 0
/* These are special variables using by the kernel trap/interrupt code
to save registers in, at a time when there are no spare registers we
can use to do so, and we can't depend on the value of the stack
pointer. This means that they must be within a signed 16-bit
displacement of 0x00000000. */
#define KERNEL_VAR_SPACE_ADDR R0_RAM_ADDR
#ifdef __ASSEMBLY__
#define KERNEL_VAR(addr) addr[r0]
#else
#define KERNEL_VAR(addr) (*(volatile unsigned long *)(addr))
#endif
/* Kernel stack pointer, 4 bytes. */
#define KSP_ADDR (KERNEL_VAR_SPACE_ADDR + 0)
#define KSP KERNEL_VAR (KSP_ADDR)
/* 1 if in kernel-mode, 0 if in user mode, 1 byte. */
#define KM_ADDR (KERNEL_VAR_SPACE_ADDR + 4)
#define KM KERNEL_VAR (KM_ADDR)
/* Temporary storage for interrupt handlers, 4 bytes. */
#define INT_SCRATCH_ADDR (KERNEL_VAR_SPACE_ADDR + 8)
#define INT_SCRATCH KERNEL_VAR (INT_SCRATCH_ADDR)
/* Where the stack-pointer is saved when jumping to various sorts of
interrupt handlers. ENTRY_SP is used by everything except NMIs,
which have their own location. Higher-priority NMIs can clobber the
value written by a lower priority NMI, since they can't be disabled,
but that's OK, because only NMI0 (the lowest-priority one) is allowed
to return. */
#define ENTRY_SP_ADDR (KERNEL_VAR_SPACE_ADDR + 12)
#define ENTRY_SP KERNEL_VAR (ENTRY_SP_ADDR)
#define NMI_ENTRY_SP_ADDR (KERNEL_VAR_SPACE_ADDR + 16)
#define NMI_ENTRY_SP KERNEL_VAR (NMI_ENTRY_SP_ADDR)
#ifdef CONFIG_RESET_GUARD
/* Used to detect unexpected resets (since the v850 has no MMU, any call
through a null pointer will jump to the reset vector). We detect
such resets by checking for a magic value, RESET_GUARD_ACTIVE, in
this location. Properly resetting the machine stores zero there, so
it shouldn't trigger the guard; the power-on value is uncertain, but
it's unlikely to be RESET_GUARD_ACTIVE. */
#define RESET_GUARD_ADDR (KERNEL_VAR_SPACE_ADDR + 28)
#define RESET_GUARD KERNEL_VAR (RESET_GUARD_ADDR)
#define RESET_GUARD_ACTIVE 0xFAB4BEEF
#endif /* CONFIG_RESET_GUARD */
#ifdef CONFIG_V850E_MA1_HIGHRES_TIMER
#define HIGHRES_TIMER_SLOW_TICKS_ADDR (KERNEL_VAR_SPACE_ADDR + 32)
#define HIGHRES_TIMER_SLOW_TICKS KERNEL_VAR (HIGHRES_TIMER_SLOW_TICKS_ADDR)
#endif /* CONFIG_V850E_MA1_HIGHRES_TIMER */
#ifndef __ASSEMBLY__
#ifdef CONFIG_RESET_GUARD
/* Turn off reset guard, so that resetting the machine works normally.
This should be called in the various machine_halt, etc., functions. */
static inline void disable_reset_guard (void)
{
RESET_GUARD = 0;
}
#endif /* CONFIG_RESET_GUARD */
#endif /* !__ASSEMBLY__ */
/* A `state save frame' is a struct pt_regs preceded by some extra space
suitable for a function call stack frame. */
/* Amount of room on the stack reserved for arguments and to satisfy the
C calling conventions, in addition to the space used by the struct
pt_regs that actually holds saved values. */
#define STATE_SAVE_ARG_SPACE (6*4) /* Up to six arguments. */
#ifdef __ASSEMBLY__
/* The size of a state save frame. */
#define STATE_SAVE_SIZE (PT_SIZE + STATE_SAVE_ARG_SPACE)
#else /* !__ASSEMBLY__ */
/* The size of a state save frame. */
#define STATE_SAVE_SIZE (sizeof (struct pt_regs) + STATE_SAVE_ARG_SPACE)
#endif /* __ASSEMBLY__ */
/* Offset of the struct pt_regs in a state save frame. */
#define STATE_SAVE_PT_OFFSET STATE_SAVE_ARG_SPACE
#endif /* __V850_ENTRY_H__ */
#ifndef __V850_ERRNO_H__
#define __V850_ERRNO_H__
#include <asm-generic/errno.h>
#endif /* __V850_ERRNO_H__ */
#ifndef __V850_FCNTL_H__
#define __V850_FCNTL_H__
/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
located on an ext2 file system */
#define O_ACCMODE 0003
#define O_RDONLY 00
#define O_WRONLY 01
#define O_RDWR 02
#define O_CREAT 0100 /* not fcntl */
#define O_EXCL 0200 /* not fcntl */
#define O_NOCTTY 0400 /* not fcntl */
#define O_TRUNC 01000 /* not fcntl */
#define O_APPEND 02000
#define O_NONBLOCK 04000
#define O_NDELAY O_NONBLOCK
#define O_SYNC 010000
#define FASYNC 020000 /* fcntl, for BSD compatibility */
#define O_DIRECTORY 040000 /* must be a directory */
#define O_NOFOLLOW 0100000 /* don't follow links */
#define O_DIRECT 0200000 /* direct disk access hint - currently ignored */
#define O_LARGEFILE 0400000
#define F_DUPFD 0 /* dup */
#define F_GETFD 1 /* get close_on_exec */
#define F_SETFD 2 /* set/clear close_on_exec */
#define F_GETFL 3 /* get file->f_flags */
#define F_SETFL 4 /* set file->f_flags */
#define F_GETLK 5
#define F_SETLK 6
#define F_SETLKW 7
#define F_SETOWN 8 /* for sockets. */
#define F_GETOWN 9 /* for sockets. */
#define F_SETSIG 10 /* for sockets. */
#define F_GETSIG 11 /* for sockets. */
#define F_GETLK64 12 /* using 'struct flock64' */
#define F_SETLK64 13
#define F_SETLKW64 14
/* for F_[GET|SET]FL */
#define FD_CLOEXEC 1 /* actually anything with low bit set goes */
/* for posix fcntl() and lockf() */
#define F_RDLCK 0
#define F_WRLCK 1
#define F_UNLCK 2
/* for old implementation of bsd flock () */
#define F_EXLCK 4 /* or 3 */
#define F_SHLCK 8 /* or 4 */
/* for leases */
#define F_INPROGRESS 16
/* operations for bsd flock(), also used by the kernel implementation */
#define LOCK_SH 1 /* shared lock */
#define LOCK_EX 2 /* exclusive lock */
#define LOCK_NB 4 /* or'd with one of the above to prevent
blocking */
#define LOCK_UN 8 /* remove lock */
#define LOCK_MAND 32 /* This is a mandatory flock */
#define LOCK_READ 64 /* ... Which allows concurrent read operations */
#define LOCK_WRITE 128 /* ... Which allows concurrent write operations */
#define LOCK_RW 192 /* ... Which allows concurrent read & write ops */
struct flock {
short l_type;
short l_whence;
off_t l_start;
off_t l_len;
pid_t l_pid;
};
struct flock64 {
short l_type;
short l_whence;
loff_t l_start;
loff_t l_len;
pid_t l_pid;
};
#define F_LINUX_SPECIFIC_BASE 1024
#endif /* __V850_FCNTL_H__ */
/*
* include/asm-v850/fpga85e2c.h -- Machine-dependent defs for
* FPGA implementation of V850E2/NA85E2C
*
* Copyright (C) 2002 NEC Corporation
* Copyright (C) 2002 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#ifndef __V850_FPGA85E2C_H__
#define __V850_FPGA85E2C_H__
#include <asm/clinkage.h>
#define CPU_ARCH "v850e2"
#define CPU_MODEL "FPGA NA85E2C/V850E2"
/* `external ram'. */
#define ERAM_ADDR 0
#define ERAM_SIZE 0x00100000 /* 1MB */
/* FPGA specific control registers. */
/* Writing a non-zero value to FLGREG(0) will signal the controlling CPU
to stop execution. */
#define FLGREG_ADDR(n) (0xFFE80100 + 2*(n))
#define FLGREG(n) (*(volatile unsigned char *)FLGREG_ADDR (n))
#define FLGREG_NUM 2
#define CSDEV_ADDR(n) (0xFFE80110 + 2*(n))
#define CSDEV(n) (*(volatile unsigned char *)CSDEV_ADDR (n))
/* The BSC register controls bus-sizing. Each memory area CSn uses a pair
of bits N*2 and N*2+1, where 00 means an 8-bit bus size, 01 16-bit, and
10 32-bit. */
#define BSC_ADDR 0xFFFFF066
#define BSC (*(volatile unsigned short *)BSC_ADDR)
#define DWC_ADDR(n) (0xFFFFF484 + 2*(n))
#define DWC(n) (*(volatile unsigned short *)DWC_ADDR (n))
#define ASC_ADDR 0xFFFFF48A
#define ASC (*(volatile unsigned short *)ASC_ADDR)
#define BTSC_ADDR 0xFFFFF070
#define BTSC (*(volatile unsigned short *)BTSC_ADDR)
#define BHC_ADDR 0xFFFFF06A
#define BHC (*(volatile unsigned short *)BHC_ADDR)
/* NB85E-style interrupt system. */
#include <asm/nb85e_intc.h>
/* Timer interrupts 0-3, interrupt at intervals from CLK/4096 to CLK/16384. */
#define IRQ_RPU(n) (60 + (n))
#define IRQ_RPU_NUM 4
/* For <asm/irq.h> */
#define NUM_CPU_IRQS 64
/* General-purpose timer. */
/* control/status register (can only be read/written via bit insns) */
#define RPU_GTMC_ADDR 0xFFFFFB00
#define RPU_GTMC (*(volatile unsigned char *)RPU_GTMC_ADDR)
#define RPU_GTMC_CE_BIT 7 /* clock enable (control) */
#define RPU_GTMC_OV_BIT 6 /* overflow (status) */
#define RPU_GTMC_CLK_BIT 1 /* 0 = .5 MHz CLK, 1 = 1 Mhz (control) */
/* 32-bit count (8 least-significant bits are always zero). */
#define RPU_GTM_ADDR 0xFFFFFB28
#define RPU_GTM (*(volatile unsigned long *)RPU_GTMC_ADDR)
/* For <asm/page.h> */
#define PAGE_OFFSET ERAM_ADDR /* minimum allocatable address */
/* For <asm/entry.h> */
/* `R0 RAM', used for a few miscellaneous variables that must be accessible
using a load instruction relative to R0. The FPGA implementation
actually has no on-chip RAM, so we use part of main ram just after the
interrupt vectors. */
#ifdef __ASSEMBLY__
#define R0_RAM_ADDR lo(C_SYMBOL_NAME(_r0_ram))
#else
extern char _r0_ram;
#define R0_RAM_ADDR ((unsigned long)&_r0_ram);
#endif
/* For <asm/param.h> */
#ifndef HZ
#define HZ 122 /* actually, 8.192ms ticks =~ 122.07 */
#endif
#endif /* __V850_FPGA85E2C_H__ */
/*
* include/asm-v850/gbus_int.h -- Midas labs GBUS interrupt support
*
* Copyright (C) 2001,02 NEC Corporation
* Copyright (C) 2001,02 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#ifndef __V850_GBUS_INT_H__
#define __V850_GBUS_INT_H__
/* The GBUS interrupt interface has 32 interrupts shared among 4
processor interrupts. The 32 GBUS interrupts are divided into two
sets of 16 each, for allocating among control registers, etc (there
are two of each control register, with bits 0-15 controlling an
interrupt each). */
/* The GBUS interrupts themselves. */
#define IRQ_GBUS_INT(n) (GBUS_INT_BASE_IRQ + (n))
#define IRQ_GBUS_INT_NUM 32
/* Control registers. */
#define GBUS_INT_STATUS_ADDR(w) (GBUS_INT_BASE_ADDR + (w)*0x40)
#define GBUS_INT_STATUS(w) (*(volatile u16 *)GBUS_INT_STATUS_ADDR(w))
#define GBUS_INT_CLEAR_ADDR(w) (GBUS_INT_BASE_ADDR + 0x10 + (w)*0x40)
#define GBUS_INT_CLEAR(w) (*(volatile u16 *)GBUS_INT_CLEAR_ADDR(w))
#define GBUS_INT_EDGE_ADDR(w) (GBUS_INT_BASE_ADDR + 0x20 + (w)*0x40)
#define GBUS_INT_EDGE(w) (*(volatile u16 *)GBUS_INT_EDGE_ADDR(w))
#define GBUS_INT_POLARITY_ADDR(w) (GBUS_INT_BASE_ADDR + 0x30 + (w)*0x40)
#define GBUS_INT_POLARITY(w) (*(volatile u16 *)GBUS_INT_POLARITY_ADDR(w))
/* This allows enabling interrupt bits in word W for interrupt GINTn. */
#define GBUS_INT_ENABLE_ADDR(w, n) \
(GBUS_INT_BASE_ADDR + 0x100 + (w)*0x10 + (n)*0x20)
#define GBUS_INT_ENABLE(w, n) (*(volatile u16 *)GBUS_INT_ENABLE_ADDR(w, n))
/* Mapping between kernel interrupt numbers and hardware control regs/bits. */
#define GBUS_INT_BITS_PER_WORD 16
#define GBUS_INT_NUM_WORDS (IRQ_GBUS_INT_NUM / GBUS_INT_BITS_PER_WORD)
#define GBUS_INT_IRQ_WORD(irq) (((irq) - GBUS_INT_BASE_IRQ) >> 4)
#define GBUS_INT_IRQ_BIT(irq) (((irq) - GBUS_INT_BASE_IRQ) & 0xF)
#define GBUS_INT_IRQ_MASK(irq) (1 << GBUS_INT_IRQ_BIT(irq))
/* Possible priorities for GBUS interrupts. */
#define GBUS_INT_PRIORITY_HIGH 2
#define GBUS_INT_PRIORITY_MEDIUM 4
#define GBUS_INT_PRIORITY_LOW 6
#ifndef __ASSEMBLY__
/* Enable interrupt handling for interrupt IRQ. */
extern void gbus_int_enable_irq (unsigned irq);
/* Disable interrupt handling for interrupt IRQ. Note that any
interrupts received while disabled will be delivered once the
interrupt is enabled again, unless they are explicitly cleared using
`gbus_int_clear_pending_irq'. */
extern void gbus_int_disable_irq (unsigned irq);
/* Return true if interrupt handling for interrupt IRQ is enabled. */
extern int gbus_int_irq_enabled (unsigned irq);
/* Disable all GBUS irqs. */
extern int gbus_int_disable_irqs (void);
/* Clear any pending interrupts for IRQ. */
extern void gbus_int_clear_pending_irq (unsigned irq);
/* Return true if interrupt IRQ is pending (but disabled). */
extern int gbus_int_irq_pending (unsigned irq);
struct gbus_int_irq_init {
const char *name; /* name of interrupt type */
/* Range of kernel irq numbers for this type:
BASE, BASE+INTERVAL, ..., BASE+INTERVAL*NUM */
unsigned base, num, interval;
unsigned priority; /* interrupt priority to assign */
};
struct hw_interrupt_type; /* fwd decl */
/* Initialize HW_IRQ_TYPES for GBUS irqs described in array
INITS (which is terminated by an entry with the name field == 0). */
extern void gbus_int_init_irq_types (struct gbus_int_irq_init *inits,
struct hw_interrupt_type *hw_irq_types);
/* Initialize GBUS interrupts. */
extern void gbus_int_init_irqs (void);
#endif /* !__ASSEMBLY__ */
#endif /* __V850_GBUS_INT_H__ */
#ifndef __V850_HARDIRQ_H__
#define __V850_HARDIRQ_H__
#include <linux/config.h>
#include <linux/threads.h>
typedef struct {
unsigned int __softirq_pending;
unsigned int __syscall_count;
struct task_struct * __ksoftirqd_task;
} ____cacheline_aligned irq_cpustat_t;
#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */
/*
* We put the hardirq and softirq counter into the preemption
* counter. The bitmask has the following meaning:
*
* - bits 0-7 are the preemption count (max preemption depth: 256)
* - bits 8-15 are the softirq count (max # of softirqs: 256)
* - bits 16-23 are the hardirq count (max # of hardirqs: 256)
*
* - ( bit 26 is the PREEMPT_ACTIVE flag. )
*
* PREEMPT_MASK: 0x000000ff
* HARDIRQ_MASK: 0x0000ff00
* SOFTIRQ_MASK: 0x00ff0000
*/
#define PREEMPT_BITS 8
#define SOFTIRQ_BITS 8
#define HARDIRQ_BITS 8
#define PREEMPT_SHIFT 0
#define SOFTIRQ_SHIFT (PREEMPT_SHIFT + PREEMPT_BITS)
#define HARDIRQ_SHIFT (SOFTIRQ_SHIFT + SOFTIRQ_BITS)
#define __MASK(x) ((1UL << (x))-1)
#define PREEMPT_MASK (__MASK(PREEMPT_BITS) << PREEMPT_SHIFT)
#define HARDIRQ_MASK (__MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT)
#define SOFTIRQ_MASK (__MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT)
#define hardirq_count() (preempt_count() & HARDIRQ_MASK)
#define softirq_count() (preempt_count() & SOFTIRQ_MASK)
#define irq_count() (preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK))
#define PREEMPT_OFFSET (1UL << PREEMPT_SHIFT)
#define SOFTIRQ_OFFSET (1UL << SOFTIRQ_SHIFT)
#define HARDIRQ_OFFSET (1UL << HARDIRQ_SHIFT)
/*
* The hardirq mask has to be large enough to have
* space for potentially all IRQ sources in the system
* nesting on a single CPU:
*/
#if (1 << HARDIRQ_BITS) < NR_IRQS
# error HARDIRQ_BITS is too low!
#endif
/*
* Are we doing bottom half or hardware interrupt processing?
* Are we in a softirq context? Interrupt context?
*/
#define in_irq() (hardirq_count())
#define in_softirq() (softirq_count())
#define in_interrupt() (irq_count())
#define hardirq_trylock() (!in_interrupt())
#define hardirq_endlock() do { } while (0)
#define irq_enter() (preempt_count() += HARDIRQ_OFFSET)
#if CONFIG_PREEMPT
# define in_atomic() (preempt_count() != kernel_locked())
# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
#else
# define in_atomic() (preempt_count() != 0)
# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
#endif
#define irq_exit() \
do { \
preempt_count() -= IRQ_EXIT_OFFSET; \
if (!in_interrupt() && softirq_pending(smp_processor_id())) \
do_softirq(); \
preempt_enable_no_resched(); \
} while (0)
#ifndef CONFIG_SMP
# define synchronize_irq(irq) barrier()
#else
# error v850nommu SMP is not available
#endif /* CONFIG_SMP */
#endif /* __V850_HARDIRQ_H__ */
/*
* include/asm-v850/highres_timer.h -- High resolution timing routines
*
* Copyright (C) 2001 NEC Corporation
* Copyright (C) 2001 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#ifndef __V850_HIGHRES_TIMER_H__
#define __V850_HIGHRES_TIMER_H__
#ifndef __ASSEMBLY__
#include <linux/time.h>
#endif
#include <asm/entry.h>
/* Frequency of the `slow ticks' (one tick each time the fast-tick
counter overflows). */
#define HIGHRES_TIMER_SLOW_TICK_RATE 25
/* Which timer in the nb85e `Timer D' we use. */
#define HIGHRES_TIMER_TIMER_D_UNIT 3
#ifndef __ASSEMBLY__
extern void highres_timer_start (void), highres_timer_stop (void);
extern void highres_timer_reset (void);
extern void highres_timer_read_ticks (u32 *slow_ticks, u32 *fast_ticks);
extern void highres_timer_ticks_to_timeval (u32 slow_ticks, u32 fast_ticks,
struct timeval *tv);
extern void highres_timer_read (struct timeval *tv);
#endif /* !__ASSEMBLY__ */
#endif /* __V850_HIGHRES_TIMER_H__ */
#ifndef __V850_HW_IRQ_H__
#define __V850_HW_IRQ_H__
extern inline void hw_resend_irq (struct hw_interrupt_type *h, unsigned int i)
{
}
#endif /* __V850_HW_IRQ_H__ */
/*
* include/asm-v850/io.h -- Misc I/O operations
*
* Copyright (C) 2001,02 NEC Corporation
* Copyright (C) 2001,02 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#ifndef __V850_IO_H__
#define __V850_IO_H__
#define IO_SPACE_LIMIT 0xFFFFFFFF
#define readb(addr) \
({ unsigned char __v = (*(volatile unsigned char *) (addr)); __v; })
#define readw(addr) \
({ unsigned short __v = (*(volatile unsigned short *) (addr)); __v; })
#define readl(addr) \
({ unsigned long __v = (*(volatile unsigned long *) (addr)); __v; })
#define writeb(b, addr) \
(void)((*(volatile unsigned char *) (addr)) = (b))
#define writew(b, addr) \
(void)((*(volatile unsigned short *) (addr)) = (b))
#define writel(b, addr) \
(void)((*(volatile unsigned int *) (addr)) = (b))
#define inb(addr) readb (addr)
#define inw(addr) readw (addr)
#define inl(addr) readl (addr)
#define outb(x, addr) ((void) writeb (x, addr))
#define outw(x, addr) ((void) writew (x, addr))
#define outl(x, addr) ((void) writel (x, addr))
#define inb_p(port) inb((port))
#define outb_p(val, port) outb((val), (port))
#define inw_p(port) inw((port))
#define outw_p(val, port) outw((val), (port))
#define inl_p(port) inl((port))
#define outl_p(val, port) outl((val), (port))
static inline void insb (unsigned long port, void *dst, unsigned long count)
{
unsigned char *p = dst;
while (count--)
*p++ = inb (port);
}
static inline void insw (unsigned long port, void *dst, unsigned long count)
{
unsigned short *p = dst;
while (count--)
*p++ = inw (port);
}
static inline void insl (unsigned long port, void *dst, unsigned long count)
{
unsigned long *p = dst;
while (count--)
*p++ = inl (port);
}
static inline void
outsb (unsigned long port, const void *src, unsigned long count)
{
const unsigned char *p = src;
while (count--)
outb (*p++, port);
}
static inline void
outsw (unsigned long port, const void *src, unsigned long count)
{
const unsigned short *p = src;
while (count--)
outw (*p++, port);
}
static inline void
outsl (unsigned long port, const void *src, unsigned long count)
{
const unsigned long *p = src;
while (count--)
outl (*p++, port);
}
#define iounmap(addr) ((void)0)
#define ioremap(physaddr, size) (physaddr)
#define ioremap_nocache(physaddr, size) (physaddr)
#define ioremap_writethrough(physaddr, size) (physaddr)
#define ioremap_fullcache(physaddr, size) (physaddr)
#define page_to_phys(page) ((page - mem_map) << PAGE_SHIFT)
#if 0
/* This is really stupid; don't define it. */
#define page_to_bus(page) page_to_phys (page)
#endif
/* Conversion between virtual and physical mappings. */
#define mm_ptov(addr) ((void *)__phys_to_virt (addr))
#define mm_vtop(addr) ((unsigned long)__virt_to_phys (addr))
#define phys_to_virt(addr) ((void *)__phys_to_virt (addr))
#define virt_to_phys(addr) ((unsigned long)__virt_to_phys (addr))
#endif /* __V850_IO_H__ */
/* $Id: ioctl.h,v 1.1 2002/09/28 14:58:41 gerg Exp $
*
* linux/ioctl.h for Linux by H.H. Bergman.
*/
#ifndef _V850_IOCTL_H
#define _V850_IOCTL_H
/* ioctl command encoding: 32 bits total, command in lower 16 bits,
* size of the parameter structure in the lower 14 bits of the
* upper 16 bits.
* Encoding the size of the parameter structure in the ioctl request
* is useful for catching programs compiled with old versions
* and to avoid overwriting user space outside the user buffer area.
* The highest 2 bits are reserved for indicating the ``access mode''.
* NOTE: This limits the max parameter size to 16kB -1 !
*/
/*
* I don't really have any idea about what this should look like, so
* for the time being, this is heavily based on the PC definitions.
*/
/*
* The following is for compatibility across the various Linux
* platforms. The i386 ioctl numbering scheme doesn't really enforce
* a type field. De facto, however, the top 8 bits of the lower 16
* bits are indeed used as a type field, so we might just as well make
* this explicit here. Please be sure to use the decoding macros
* below from now on.
*/
#define _IOC_NRBITS 8
#define _IOC_TYPEBITS 8
#define _IOC_SIZEBITS 14
#define _IOC_DIRBITS 2
#define _IOC_NRMASK ((1 << _IOC_NRBITS)-1)
#define _IOC_TYPEMASK ((1 << _IOC_TYPEBITS)-1)
#define _IOC_SIZEMASK ((1 << _IOC_SIZEBITS)-1)
#define _IOC_DIRMASK ((1 << _IOC_DIRBITS)-1)
#define _IOC_NRSHIFT 0
#define _IOC_TYPESHIFT (_IOC_NRSHIFT+_IOC_NRBITS)
#define _IOC_SIZESHIFT (_IOC_TYPESHIFT+_IOC_TYPEBITS)
#define _IOC_DIRSHIFT (_IOC_SIZESHIFT+_IOC_SIZEBITS)
/*
* Direction bits.
*/
#define _IOC_NONE 0U
#define _IOC_WRITE 1U
#define _IOC_READ 2U
#define _IOC(dir,type,nr,size) \
(((dir) << _IOC_DIRSHIFT) | \
((type) << _IOC_TYPESHIFT) | \
((nr) << _IOC_NRSHIFT) | \
((size) << _IOC_SIZESHIFT))
/* used to create numbers */
#define _IO(type,nr) _IOC(_IOC_NONE,(type),(nr),0)
#define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size))
#define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),sizeof(size))
#define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
/* used to decode ioctl numbers.. */
#define _IOC_DIR(nr) (((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
#define _IOC_TYPE(nr) (((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK)
#define _IOC_NR(nr) (((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK)
#define _IOC_SIZE(nr) (((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK)
/* ...and for the drivers/sound files... */
#define IOC_IN (_IOC_WRITE << _IOC_DIRSHIFT)
#define IOC_OUT (_IOC_READ << _IOC_DIRSHIFT)
#define IOC_INOUT ((_IOC_WRITE|_IOC_READ) << _IOC_DIRSHIFT)
#define IOCSIZE_MASK (_IOC_SIZEMASK << _IOC_SIZESHIFT)
#define IOCSIZE_SHIFT (_IOC_SIZESHIFT)
#endif /* __V850_IOCTL_H__ */
#ifndef __V850_IOCTLS_H__
#define __V850_IOCTLS_H__
#include <asm/ioctl.h>
/* 0x54 is just a magic number to make these relatively unique ('T') */
#define TCGETS 0x5401
#define TCSETS 0x5402
#define TCSETSW 0x5403
#define TCSETSF 0x5404
#define TCGETA 0x5405
#define TCSETA 0x5406
#define TCSETAW 0x5407
#define TCSETAF 0x5408
#define TCSBRK 0x5409
#define TCXONC 0x540A
#define TCFLSH 0x540B
#define TIOCEXCL 0x540C
#define TIOCNXCL 0x540D
#define TIOCSCTTY 0x540E
#define TIOCGPGRP 0x540F
#define TIOCSPGRP 0x5410
#define TIOCOUTQ 0x5411
#define TIOCSTI 0x5412
#define TIOCGWINSZ 0x5413
#define TIOCSWINSZ 0x5414
#define TIOCMGET 0x5415
#define TIOCMBIS 0x5416
#define TIOCMBIC 0x5417
#define TIOCMSET 0x5418
#define TIOCGSOFTCAR 0x5419
#define TIOCSSOFTCAR 0x541A
#define FIONREAD 0x541B
#define TIOCINQ FIONREAD
#define TIOCLINUX 0x541C
#define TIOCCONS 0x541D
#define TIOCGSERIAL 0x541E
#define TIOCSSERIAL 0x541F
#define TIOCPKT 0x5420
#define FIONBIO 0x5421
#define TIOCNOTTY 0x5422
#define TIOCSETD 0x5423
#define TIOCGETD 0x5424
#define TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */
#define TIOCTTYGSTRUCT 0x5426 /* For debugging only */
#define TIOCSBRK 0x5427 /* BSD compatibility */
#define TIOCCBRK 0x5428 /* BSD compatibility */
#define TIOCGSID 0x5429 /* Return the session ID of FD */
#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */
#define FIONCLEX 0x5450 /* these numbers need to be adjusted. */
#define FIOCLEX 0x5451
#define FIOASYNC 0x5452
#define TIOCSERCONFIG 0x5453
#define TIOCSERGWILD 0x5454
#define TIOCSERSWILD 0x5455
#define TIOCGLCKTRMIOS 0x5456
#define TIOCSLCKTRMIOS 0x5457
#define TIOCSERGSTRUCT 0x5458 /* For debugging only */
#define TIOCSERGETLSR 0x5459 /* Get line status register */
#define TIOCSERGETMULTI 0x545A /* Get multiport config */
#define TIOCSERSETMULTI 0x545B /* Set multiport config */
#define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */
#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */
#define FIOQSIZE 0x545E
/* Used for packet mode */
#define TIOCPKT_DATA 0
#define TIOCPKT_FLUSHREAD 1
#define TIOCPKT_FLUSHWRITE 2
#define TIOCPKT_STOP 4
#define TIOCPKT_START 8
#define TIOCPKT_NOSTOP 16
#define TIOCPKT_DOSTOP 32
#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */
#endif /* __V850_IOCTLS_H__ */
#ifndef __V850_IPC_H__
#define __V850_IPC_H__
/*
* These are used to wrap system calls on v850.
*
* See arch/v850/kernel/syscalls.c for ugly details..
*/
struct ipc_kludge {
struct msgbuf *msgp;
long msgtyp;
};
#define SEMOP 1
#define SEMGET 2
#define SEMCTL 3
#define MSGSND 11
#define MSGRCV 12
#define MSGGET 13
#define MSGCTL 14
#define SHMAT 21
#define SHMDT 22
#define SHMGET 23
#define SHMCTL 24
/* Used by the DIPC package, try and avoid reusing it */
#define DIPC 25
#define IPCCALL(version,op) ((version)<<16 | (op))
#endif /* __V850_IPC_H__ */
#ifndef __V850E_IPCBUF_H__
#define __V850E_IPCBUF_H__
/*
* The user_ipc_perm structure for v850e architecture.
* Note extra padding because this structure is passed back and forth
* between kernel and user space.
*
* Pad space is left for:
* - 32-bit mode_t and seq
* - 2 miscellaneous 32-bit values
*/
struct ipc64_perm
{
__kernel_key_t key;
__kernel_uid32_t uid;
__kernel_gid32_t gid;
__kernel_uid32_t cuid;
__kernel_gid32_t cgid;
__kernel_mode_t mode;
unsigned short __pad1;
unsigned short seq;
unsigned short __pad2;
unsigned long __unused1;
unsigned long __unused2;
};
#endif /* __V850E_IPCBUF_H__ */
/*
* include/asm-v850/irq.h -- Machine interrupt handling
*
* Copyright (C) 2001,02 NEC Corporation
* Copyright (C) 2001,02 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#ifndef __V850_IRQ_H__
#define __V850_IRQ_H__
#include <asm/machdep.h>
/* Default NUM_MACH_IRQS. */
#ifndef NUM_MACH_IRQS
#define NUM_MACH_IRQS NUM_CPU_IRQS
#endif
/* NMIs have IRQ numbers from FIRST_NMI to FIRST_NMI+NUM_NMIS-1. */
#define FIRST_NMI NUM_MACH_IRQS
#define IRQ_NMI(n) (FIRST_NMI + (n))
/* v850 processors have 3 non-maskable interrupts. */
#define NUM_NMIS 3
/* Includes both maskable and non-maskable irqs. */
#define NR_IRQS (NUM_MACH_IRQS + NUM_NMIS)
#ifndef __ASSEMBLY__
struct pt_regs;
struct hw_interrupt_type;
struct irqaction;
#define irq_cannonicalize(irq) (irq)
/* Initialize irq handling for IRQs.
BASE_IRQ, BASE_IRQ+INTERVAL, ..., BASE_IRQ+NUM*INTERVAL
to IRQ_TYPE. An IRQ_TYPE of 0 means to use a generic interrupt type. */
extern void
init_irq_handlers (int base_irq, int num, int interval,
struct hw_interrupt_type *irq_type);
typedef void (*irq_handler_t)(int irq, void *data, struct pt_regs *regs);
/* Handle interrupt IRQ. REGS are the registers at the time of ther
interrupt. */
extern unsigned int handle_irq (int irq, struct pt_regs *regs);
#endif /* !__ASSEMBLY__ */
#endif /* __V850_IRQ_H__ */
#ifndef __V850_KMAP_TYPES_H__
#define __V850_KMAP_TYPES_H__
enum km_type {
KM_BOUNCE_READ,
KM_SKB_SUNRPC_DATA,
KM_SKB_DATA_SOFTIRQ,
KM_USER0,
KM_USER1,
KM_BIO_SRC_IRQ,
KM_BIO_DST_IRQ,
KM_PTE0,
KM_PTE1,
KM_IRQ0,
KM_IRQ1,
KM_TYPE_NR
};
#endif /* __V850_KMAP_TYPES_H__ */
#ifndef __ASM_LINKAGE_H
#define __ASM_LINKAGE_H
/* Nothing to see here... */
#endif
/*
* include/asm-v850/ma.h -- V850E/MA series of cpu chips
*
* Copyright (C) 2001,02 NEC Corporation
* Copyright (C) 2001,02 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#ifndef __V850_MA_H__
#define __V850_MA_H__
/* The MA series uses the NB85E cpu core. */
#include <asm/nb85e.h>
/* For <asm/entry.h> */
/* We use on-chip RAM, for a few miscellaneous variables that must be
accessible using a load instruction relative to R0. The amount
varies between chip models, but there's always at least 4K, and it
should always start at FFFFC000. */
#define R0_RAM_ADDR 0xFFFFC000
/* MA series UART details. */
#define NB85E_UART_BASE_FREQ CPU_CLOCK_FREQ
/* This is a function that gets called before configuring the UART. */
#define NB85E_UART_PRE_CONFIGURE ma_uart_pre_configure
#ifndef __ASSEMBLY__
extern void ma_uart_pre_configure (unsigned chan,
unsigned cflags, unsigned baud);
#endif
/* MA series timer C details. */
#define NB85E_TIMER_C_BASE_ADDR 0xFFFFF600
/* MA series timer D details. */
#define NB85E_TIMER_D_BASE_ADDR 0xFFFFF540
#define NB85E_TIMER_D_TMD_BASE_ADDR (NB85E_TIMER_D_BASE_ADDR + 0x0)
#define NB85E_TIMER_D_CMD_BASE_ADDR (NB85E_TIMER_D_BASE_ADDR + 0x2)
#define NB85E_TIMER_D_TMCD_BASE_ADDR (NB85E_TIMER_D_BASE_ADDR + 0x4)
#define NB85E_TIMER_D_BASE_FREQ CPU_CLOCK_FREQ
/* Port 0 */
/* Direct I/O. Bits 0-7 are pins P00-P07. */
#define MA_PORT0_IO_ADDR 0xFFFFF400
#define MA_PORT0_IO (*(volatile u8 *)MA_PORT0_IO_ADDR)
/* Port mode (for direct I/O, 0 = output, 1 = input). */
#define MA_PORT0_PM_ADDR 0xFFFFF420
#define MA_PORT0_PM (*(volatile u8 *)MA_PORT0_PM_ADDR)
/* Port mode control (0 = direct I/O mode, 1 = alternative I/O mode). */
#define MA_PORT0_PMC_ADDR 0xFFFFF440
#define MA_PORT0_PMC (*(volatile u8 *)MA_PORT0_PMC_ADDR)
/* Port function control (for P04-P07, 0 = IRQ, 1 = DMARQ). */
#define MA_PORT0_PFC_ADDR 0xFFFFF460
#define MA_PORT0_PFC (*(volatile u8 *)MA_PORT0_PFC_ADDR)
/* Port 1 */
/* Direct I/O. Bits 0-3 are pins P10-P13. */
#define MA_PORT1_IO_ADDR 0xFFFFF402
#define MA_PORT1_IO (*(volatile u8 *)MA_PORT1_IO_ADDR)
/* Port mode (for direct I/O, 0 = output, 1 = input). */
#define MA_PORT1_PM_ADDR 0xFFFFF420
#define MA_PORT1_PM (*(volatile u8 *)MA_PORT1_PM_ADDR)
/* Port mode control (0 = direct I/O mode, 1 = alternative I/O mode). */
#define MA_PORT1_PMC_ADDR 0xFFFFF442
#define MA_PORT1_PMC (*(volatile u8 *)MA_PORT1_PMC_ADDR)
/* Port 4 */
/* Direct I/O. Bits 0-5 are pins P40-P45. */
#define MA_PORT4_IO_ADDR 0xFFFFF408
#define MA_PORT4_IO (*(volatile u8 *)MA_PORT4_IO_ADDR)
/* Port mode (for direct I/O, 0 = output, 1 = input). */
#define MA_PORT4_PM_ADDR 0xFFFFF428
#define MA_PORT4_PM (*(volatile u8 *)MA_PORT4_PM_ADDR)
/* Port mode control (0 = direct I/O mode, 1 = alternative I/O mode). */
#define MA_PORT4_PMC_ADDR 0xFFFFF448
#define MA_PORT4_PMC (*(volatile u8 *)MA_PORT4_PMC_ADDR)
/* Port function control (for serial interfaces, 0 = CSI, 1 = UART). */
#define MA_PORT4_PFC_ADDR 0xFFFFF468
#define MA_PORT4_PFC (*(volatile u8 *)MA_PORT4_PFC_ADDR)
#ifndef __ASSEMBLY__
/* Initialize MA chip interrupts. */
extern void ma_init_irqs (void);
#endif /* !__ASSEMBLY__ */
#endif /* __V850_MA_H__ */
/*
* include/asm-v850/ma1.h -- V850E/MA1 cpu chip
*
* Copyright (C) 2001,02 NEC Corporation
* Copyright (C) 2001,02 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#ifndef __V850_MA1_H__
#define __V850_MA1_H__
/* Inherit more generic details from MA series. */
#include <asm/ma.h>
#define CPU_MODEL "v850e/ma1"
#define CPU_MODEL_LONG "NEC V850E/MA1"
/* Hardware-specific interrupt numbers (in the kernel IRQ namespace). */
#define IRQ_INTOV(n) (n) /* 0-3 */
#define IRQ_INTOV_NUM 4
#define IRQ_INTP(n) (0x4 + (n)) /* Pnnn (pin) interrupts */
#define IRQ_INTP_NUM 24
#define IRQ_INTCMD(n) (0x1c + (n)) /* interval timer interrupts 0-3 */
#define IRQ_INTCMD_NUM 4
#define IRQ_INTDMA(n) (0x20 + (n)) /* DMA interrupts 0-3 */
#define IRQ_INTDMA_NUM 4
#define IRQ_INTCSI(n) (0x24 + (n)*4)/* CSI 0-2 transmit/receive completion */
#define IRQ_INTCSI_NUM 3
#define IRQ_INTSER(n) (0x25 + (n)*4) /* UART 0-2 reception error */
#define IRQ_INTSER_NUM 3
#define IRQ_INTSR(n) (0x26 + (n)*4) /* UART 0-2 reception completion */
#define IRQ_INTSR_NUM 3
#define IRQ_INTST(n) (0x27 + (n)*4) /* UART 0-2 transmission completion */
#define IRQ_INTST_NUM 3
/* For <asm/irq.h> */
#define NUM_CPU_IRQS 0x30
/* The MA1 has a UART with 3 channels. */
#define NB85E_UART_NUM_CHANNELS 3
#endif /* __V850_MA1_H__ */
/*
* include/asm-v850/machdep.h -- Machine-dependent definitions
*
* Copyright (C) 2001,02 NEC Corporation
* Copyright (C) 2001,02 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#ifndef __V850_MACHDEP_H__
#define __V850_MACHDEP_H__
#include <linux/config.h>
/* chips */
#ifdef CONFIG_V850E_MA1
#include <asm/ma1.h>
#endif
#ifdef CONFIG_V850E_TEG
#include <asm/teg.h>
#endif
/* Anna is both a chip _and_ a platform, so put it in the middle... */
#ifdef CONFIG_V850E2_ANNA
#include <asm/anna.h>
#endif
/* platforms */
#ifdef CONFIG_RTE_CB_MA1
#include <asm/rte_ma1_cb.h>
#endif
#ifdef CONFIG_RTE_CB_NB85E
#include <asm/rte_nb85e_cb.h>
#endif
#ifdef CONFIG_V850E_SIM
#include <asm/sim.h>
#endif
#ifdef CONFIG_V850E2_SIM85E2C
#include <asm/sim85e2c.h>
#endif
#ifdef CONFIG_V850E2_FPGA85E2C
#include <asm/fpga85e2c.h>
#endif
#endif /* __V850_MACHDEP_H__ */
/*
* include/asm-v850/macrology.h -- Various useful CPP macros
*
* Copyright (C) 2001 NEC Corporation
* Copyright (C) 2001 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#define macrology_paste(arg1, arg2) macrology_paste_1(arg1, arg2)
#define macrology_paste_1(arg1, arg2) arg1 ## arg2
#define macrology_stringify(sym) macrology_stringify_1(sym)
#define macrology_stringify_1(sym) #sym
#ifndef __V850_MMAN_H__
#define __V850_MMAN_H__
#define PROT_READ 0x1 /* page can be read */
#define PROT_WRITE 0x2 /* page can be written */
#define PROT_EXEC 0x4 /* page can be executed */
#define PROT_NONE 0x0 /* page can not be accessed */
#define MAP_SHARED 0x01 /* Share changes */
#define MAP_PRIVATE 0x02 /* Changes are private */
#define MAP_TYPE 0x0f /* Mask for type of mapping */
#define MAP_FIXED 0x10 /* Interpret addr exactly */
#define MAP_ANONYMOUS 0x20 /* don't use a file */
#define MAP_GROWSDOWN 0x0100 /* stack-like segment */
#define MAP_DENYWRITE 0x0800 /* ETXTBSY */
#define MAP_EXECUTABLE 0x1000 /* mark it as an executable */
#define MAP_LOCKED 0x2000 /* pages are locked */
#define MAP_NORESERVE 0x4000 /* don't check for reservations */
#define MS_ASYNC 1 /* sync memory asynchronously */
#define MS_INVALIDATE 2 /* invalidate the caches */
#define MS_SYNC 4 /* synchronous memory sync */
#define MCL_CURRENT 1 /* lock all current mappings */
#define MCL_FUTURE 2 /* lock all future mappings */
#define MADV_NORMAL 0x0 /* default page-in behavior */
#define MADV_RANDOM 0x1 /* page-in minimum required */
#define MADV_SEQUENTIAL 0x2 /* read-ahead aggressively */
#define MADV_WILLNEED 0x3 /* pre-fault pages */
#define MADV_DONTNEED 0x4 /* discard these pages */
/* compatibility flags */
#define MAP_ANON MAP_ANONYMOUS
#define MAP_FILE 0
#endif /* __V850_MMAN_H__ */
/* Copyright (C) 2002, David McCullough <davidm@snapgear.com> */
#ifndef __V850_MMU_H__
#define __V850_MMU_H__
struct mm_rblock_struct {
int size;
int refcount;
void *kblock;
};
struct mm_tblock_struct {
struct mm_rblock_struct *rblock;
struct mm_tblock_struct *next;
};
typedef struct {
struct mm_tblock_struct tblock;
unsigned long end_brk;
} mm_context_t;
#endif /* __V850_MMU_H__ */
#ifndef __V850_MMU_CONTEXT_H__
#define __V850_MMU_CONTEXT_H__
#include <linux/sched.h>
#define destroy_context(mm) ((void)0)
#define init_new_context(tsk,mm) 0
#define switch_mm(prev,next,tsk,cpu) ((void)0)
#define activate_mm(prev,next) ((void)0)
#define enter_lazy_tlb(mm,tsk,cpu) ((void)0)
#endif /* __V850_MMU_CONTEXT_H__ */
/*
* include/asm-v850/module.h -- Architecture-specific module hooks
*
* Copyright (C) 2001,02 NEC Corporation
* Copyright (C) 2001,02 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#ifndef __V850_MODULE_H__
#define __V850_MODULE_H__
#define arch_init_modules(x) ((void)0)
#define module_arch_init(x) (0)
#define module_map(sz) vmalloc (sz)
#define module_unmap(sz) vfree (sz)
#endif /* __V850_MODULE_H__ */
#ifndef __V850_MSGBUF_H__
#define __V850_MSGBUF_H__
/*
* The msqid64_ds structure for v850 architecture.
* Note extra padding because this structure is passed back and forth
* between kernel and user space.
*
* Pad space is left for:
* - 64-bit time_t to solve y2038 problem
* - 2 miscellaneous 32-bit values
*/
struct msqid64_ds {
struct ipc64_perm msg_perm;
__kernel_time_t msg_stime; /* last msgsnd time */
unsigned long __unused1;
__kernel_time_t msg_rtime; /* last msgrcv time */
unsigned long __unused2;
__kernel_time_t msg_ctime; /* last change time */
unsigned long __unused3;
unsigned long msg_cbytes; /* current number of bytes on queue */
unsigned long msg_qnum; /* number of messages in queue */
unsigned long msg_qbytes; /* max number of bytes on queue */
__kernel_pid_t msg_lspid; /* pid of last msgsnd */
__kernel_pid_t msg_lrpid; /* last receive pid */
unsigned long __unused4;
unsigned long __unused5;
};
#endif /* __V850_MSGBUF_H__ */
/*
* linux/include/asm-v850/namei.h
*
* Included from linux/fs/namei.c
*/
#ifndef __V850_NAMEI_H__
#define __V850_NAMEI_H__
/* This dummy routine maybe changed to something useful
* for /usr/gnemul/ emulation stuff.
* Look at asm-sparc/namei.h for details.
*/
#define __emul_prefix() NULL
#endif /* __V850_NAMEI_H__ */
/*
* include/asm-v850/nb85e.h -- NB85E cpu core
*
* Copyright (C) 2001,02 NEC Corporation
* Copyright (C) 2001,02 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#ifndef __V850_NB85E_H__
#define __V850_NB85E_H__
#include <asm/nb85e_intc.h>
#define CPU_ARCH "v850e"
#endif /* __V850_NB85E_H__ */
/*
* include/asm-v850/nb85e_cache_cache.h -- Cache control for NB85E_CACHE212 and
* NB85E_CACHE213 cache memories
*
* Copyright (C) 2001 NEC Corporation
* Copyright (C) 2001 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#ifndef __V850_NB85E_CACHE_H__
#define __V850_NB85E_CACHE_H__
/* Cache control registers. */
#define NB85E_CACHE_ICC_ADDR 0xFFFFF070
#define NB85E_CACHE_DCC_ADDR 0xFFFFF078
/* Size of a cache line in bytes. */
#define NB85E_CACHE_LINE_SIZE 16
#ifndef __ASSEMBLY__
extern inline void nb85e_cache_flush_cache (unsigned long cache_control_addr)
{
/*
From the NB85E Instruction/Data Cache manual, how to flush
the instruction cache (ICC is the `Instruction Cache Control
Register'):
mov 0x3, r2
LOP0:
ld.h ICC[r0], r1
cmp r0, r1
bnz LOP0
st.h r2, ICC[r0]
LOP1: - First TAG clear
ld.h ICC[r0], r1
cmp r0, r1
bnz LOP1
st.h r2, ICC[r0]
LOP2: - Second TAG clear
ld.h ICC[r0], r1
cmp r0, r1
bnz LOP2
*/
int cache_flush_bits, ccr_contents;
__asm__ __volatile__ (
" mov 0x3, %1;"
"1: ld.h 0[%2], %0;"
" cmp r0, %0;"
" bnz 1b;"
" st.h %1, 0[%2];"
"2: ld.h 0[%2], %0;"
" cmp r0, %0;"
" bnz 2b;"
" st.h %1, 0[%2];"
"3: ld.h 0[%2], %0;"
" cmp r0, %0;"
" bnz 3b"
: "=&r" (ccr_contents), "=&r" (cache_flush_bits)
: "r" (cache_control_addr)
: "memory");
}
extern inline void nb85e_cache_flush_icache (void)
{
nb85e_cache_flush_cache (NB85E_CACHE_ICC_ADDR);
}
extern inline void nb85e_cache_flush_dcache (void)
{
nb85e_cache_flush_cache (NB85E_CACHE_DCC_ADDR);
}
extern inline void nb85e_cache_flush (void)
{
nb85e_cache_flush_icache ();
nb85e_cache_flush_dcache ();
}
#endif /* !__ASSEMBLY__ */
/* Define standard definitions in terms of processor-specific ones. */
/* For <asm/cache.h> */
#define L1_CACHE_BYTES NB85E_CACHE_LINE_SIZE
/* For <asm/pgalloc.h> */
#define flush_cache_all() nb85e_cache_flush ()
#define flush_cache_mm(mm) nb85e_cache_flush ()
#define flush_cache_range(mm, start, end) nb85e_cache_flush ()
#define flush_cache_page(vma, vmaddr) nb85e_cache_flush ()
#define flush_page_to_ram(page) nb85e_cache_flush ()
#define flush_dcache_page(page) nb85e_cache_flush_dcache ()
#define flush_icache_range(start, end) nb85e_cache_flush_icache ()
#define flush_icache_page(vma,pg) nb85e_cache_flush_icache ()
#define flush_icache() nb85e_cache_flush_icache ()
#define flush_cache_sigtramp(vaddr) nb85e_cache_flush_icache ()
#endif /* __V850_NB85E_CACHE_H__ */
/*
* include/asm-v850/nb85e_intc.h -- NB85E cpu core interrupt controller (INTC)
*
* Copyright (C) 2001,02 NEC Corporation
* Copyright (C) 2001,02 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#ifndef __V850_NB85E_INTC_H__
#define __V850_NB85E_INTC_H__
/* There are 4 16-bit `Interrupt Mask Registers' located contiguously
starting from this base. Each interrupt uses a single bit to
indicated enabled/disabled status. */
#define NB85E_INTC_IMR_BASE_ADDR 0xFFFFF100
#define NB85E_INTC_IMR_ADDR(irq) (NB85E_INTC_IMR_BASE_ADDR + ((irq) >> 3))
#define NB85E_INTC_IMR_BIT(irq) ((irq) & 0x7)
/* Each maskable interrupt has a single-byte control register at this
address. */
#define NB85E_INTC_IC_BASE_ADDR 0xFFFFF110
#define NB85E_INTC_IC_ADDR(irq) (NB85E_INTC_IC_BASE_ADDR + ((irq) << 1))
#define NB85E_INTC_IC(irq) (*(char *)NB85E_INTC_IC_ADDR(irq))
/* Encode priority PR for storing in an interrupt control register. */
#define NB85E_INTC_IC_PR(pr) (pr)
/* Interrupt disable bit in an interrupt control register. */
#define NB85E_INTC_IC_MK_BIT 6
#define NB85E_INTC_IC_MK (1 << NB85E_INTC_IC_MK_BIT)
/* Interrupt pending flag in an interrupt control register. */
#define NB85E_INTC_IC_IF_BIT 7
#define NB85E_INTC_IC_IF (1 << NB85E_INTC_IC_IF_BIT)
#ifndef __ASSEMBLY__
/* Enable interrupt handling for interrupt IRQ. */
static inline void nb85e_intc_enable_irq (unsigned irq)
{
__asm__ __volatile__ ("clr1 %0, [%1]"
:: "r" (NB85E_INTC_IMR_BIT (irq)),
"r" (NB85E_INTC_IMR_ADDR (irq))
: "memory");
}
/* Disable interrupt handling for interrupt IRQ. Note that any
interrupts received while disabled will be delivered once the
interrupt is enabled again, unless they are explicitly cleared using
`nb85e_intc_clear_pending_irq'. */
static inline void nb85e_intc_disable_irq (unsigned irq)
{
__asm__ __volatile__ ("set1 %0, [%1]"
:: "r" (NB85E_INTC_IMR_BIT (irq)),
"r" (NB85E_INTC_IMR_ADDR (irq))
: "memory");
}
/* Return true if interrupt handling for interrupt IRQ is enabled. */
static inline int nb85e_intc_irq_enabled (unsigned irq)
{
int rval;
__asm__ __volatile__ ("tst1 %1, [%2]; setf z, %0"
: "=r" (rval)
: "r" (NB85E_INTC_IMR_BIT (irq)),
"r" (NB85E_INTC_IMR_ADDR (irq)));
return rval;
}
/* Disable irqs from 0 until LIMIT. LIMIT must be a multiple of 8. */
static inline void _nb85e_intc_disable_irqs (unsigned limit)
{
unsigned long addr;
for (addr = NB85E_INTC_IMR_BASE_ADDR; limit >= 8; addr++, limit -= 8)
*(char *)addr = 0xFF;
}
/* Disable all irqs. This is purposely a macro, because NUM_MACH_IRQS
will be only be defined later. */
#define nb85e_intc_disable_irqs() _nb85e_intc_disable_irqs (NUM_MACH_IRQS)
/* Clear any pending interrupts for IRQ. */
static inline void nb85e_intc_clear_pending_irq (unsigned irq)
{
__asm__ __volatile__ ("clr1 %0, 0[%1]"
:: "i" (NB85E_INTC_IC_IF_BIT),
"r" (NB85E_INTC_IC_ADDR (irq))
: "memory");
}
/* Return true if interrupt IRQ is pending (but disabled). */
static inline int nb85e_intc_irq_pending (unsigned irq)
{
int rval;
__asm__ __volatile__ ("tst1 %1, 0[%2]; setf nz, %0"
: "=r" (rval)
: "i" (NB85E_INTC_IC_IF_BIT),
"r" (NB85E_INTC_IC_ADDR (irq)));
return rval;
}
struct nb85e_intc_irq_init {
const char *name; /* name of interrupt type */
/* Range of kernel irq numbers for this type:
BASE, BASE+INTERVAL, ..., BASE+INTERVAL*NUM */
unsigned base, num, interval;
unsigned priority; /* interrupt priority to assign */
};
struct hw_interrupt_type; /* fwd decl */
/* Initialize HW_IRQ_TYPES for INTC-controlled irqs described in array
INITS (which is terminated by an entry with the name field == 0). */
extern void nb85e_intc_init_irq_types (struct nb85e_intc_irq_init *inits,
struct hw_interrupt_type *hw_irq_types);
#endif /* !__ASSEMBLY__ */
#endif /* __V850_NB85E_INTC_H__ */
/*
* include/asm-v850/nb85e_timer_c.h -- `Timer C' component often used
* with the NB85E cpu core
*
* Copyright (C) 2001 NEC Corporation
* Copyright (C) 2001 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
/* NOTE: this include file currently contains only enough to allow us to
use timer C as an interrupt pass-through. */
#ifndef __V850_NB85E_TIMER_C_H__
#define __V850_NB85E_TIMER_C_H__
#include <asm/types.h>
#include <asm/machdep.h> /* Pick up chip-specific defs. */
/* Timer C (16-bit interval timers). */
/* Control register 0 for timer C. */
#define NB85E_TIMER_C_TMCC0_ADDR(n) (NB85E_TIMER_C_BASE_ADDR + 0x6 + 0x10 *(n))
#define NB85E_TIMER_C_TMCC0(n) (*(volatile u8 *)NB85E_TIMER_C_TMCC0_ADDR(n))
#define NB85E_TIMER_C_TMCC0_CAE 0x01 /* clock action enable */
#define NB85E_TIMER_C_TMCC0_CE 0x02 /* count enable */
/* ... */
/* Control register 1 for timer C. */
#define NB85E_TIMER_C_TMCC1_ADDR(n) (NB85E_TIMER_C_BASE_ADDR + 0x8 + 0x10 *(n))
#define NB85E_TIMER_C_TMCC1(n) (*(volatile u8 *)NB85E_TIMER_C_TMCC1_ADDR(n))
#define NB85E_TIMER_C_TMCC1_CMS0 0x01 /* capture/compare mode select (ccc0) */
#define NB85E_TIMER_C_TMCC1_CMS1 0x02 /* capture/compare mode select (ccc1) */
/* ... */
/* Interrupt edge-sensitivity control for timer C. */
#define NB85E_TIMER_C_SESC_ADDR(n) (NB85E_TIMER_C_BASE_ADDR + 0x9 + 0x10 *(n))
#define NB85E_TIMER_C_SESC(n) (*(volatile u8 *)NB85E_TIMER_C_SESC_ADDR(n))
/* ...etc... */
#endif /* __V850_NB85E_TIMER_C_H__ */
/*
* include/asm-v850/nb85e_timer_d.h -- `Timer D' component often used
* with the NB85E cpu core
*
* Copyright (C) 2001,02 NEC Corporation
* Copyright (C) 2001,02 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#ifndef __V850_NB85E_TIMER_D_H__
#define __V850_NB85E_TIMER_D_H__
#include <asm/types.h>
#include <asm/machdep.h> /* Pick up chip-specific defs. */
/* Timer D (16-bit interval timers). */
/* Count registers for timer D. */
#define NB85E_TIMER_D_TMD_ADDR(n) (NB85E_TIMER_D_TMD_BASE_ADDR + 0x10 * (n))
#define NB85E_TIMER_D_TMD(n) (*(volatile u16 *)NB85E_TIMER_D_TMD_ADDR(n))
/* Count compare registers for timer D. */
#define NB85E_TIMER_D_CMD_ADDR(n) (NB85E_TIMER_D_CMD_BASE_ADDR + 0x10 * (n))
#define NB85E_TIMER_D_CMD(n) (*(u16 *)NB85E_TIMER_D_CMD_ADDR(n))
/* Control registers for timer D. */
#define NB85E_TIMER_D_TMCD_ADDR(n) (NB85E_TIMER_D_TMCD_BASE_ADDR + 0x10 * (n))
#define NB85E_TIMER_D_TMCD(n) (*(volatile u8 *)NB85E_TIMER_D_TMCD_ADDR(n))
/* Control bits for timer D. */
#define NB85E_TIMER_D_TMCD_CE 0x2 /* count enable */
#define NB85E_TIMER_D_TMCD_CAE 0x1 /* clock action enable */
/* Clock divider setting (log2). */
#define NB85E_TIMER_D_TMCD_CS(divlog2) (((divlog2) - NB85E_TIMER_D_TMCD_CS_MIN) << 4)
/* Minimum clock divider setting (log2). */
#ifndef NB85E_TIMER_D_TMCD_CS_MIN /* Can be overridden by mach-specific hdrs */
#define NB85E_TIMER_D_TMCD_CS_MIN 2 /* Default is correct for the v850e/ma1 */
#endif
/* Maximum clock divider setting (log2). */
#define NB85E_TIMER_D_TMCD_CS_MAX (NB85E_TIMER_D_TMCD_CS_MIN + 7)
/* Return the clock-divider (log2) of timer D unit N. */
#define NB85E_TIMER_D_DIVLOG2(n) \
(((NB85E_TIMER_D_TMCD(n) >> 4) & 0x7) + NB85E_TIMER_D_TMCD_CS_MIN)
#ifndef __ASSEMBLY__
/* Start interval timer TIMER (0-3). The timer will issue the
corresponding INTCMD interrupt RATE times per second. This function
does not enable the interrupt. */
extern void nb85e_timer_d_configure (unsigned timer, unsigned rate);
#endif /* !__ASSEMBLY__ */
#endif /* __V850_NB85E_TIMER_D_H__ */
/*
* include/asm-v850/nb85e_uart.h -- On-chip UART often used with the
* NB85E cpu core
*
* Copyright (C) 2001,02 NEC Corporation
* Copyright (C) 2001,02 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
/* There's not actually a single UART implementation used by nb85e
derivatives, but rather a series of implementations that are all
`close' to one another. This file attempts to capture some
commonality between them. */
#ifndef __V850_NB85E_UART_H__
#define __V850_NB85E_UART_H__
#include <asm/types.h>
#include <asm/machdep.h> /* Pick up chip-specific defs. */
/* The base address of the UART control registers for channel N.
The default is the address used on the V850E/MA1. */
#ifndef NB85E_UART_BASE_ADDR
#define NB85E_UART_BASE_ADDR(n) (0xFFFFFA00 + 0x10 * (n))
#endif
/* Addresses of specific UART control registers for channel N.
The defaults are the addresses used on the V850E/MA1; if a platform
wants to redefine any of these, it must redefine them all. */
#ifndef NB85E_UART_ASIM_ADDR
#define NB85E_UART_ASIM_ADDR(n) (NB85E_UART_BASE_ADDR(n) + 0x0)
#define NB85E_UART_RXB_ADDR(n) (NB85E_UART_BASE_ADDR(n) + 0x2)
#define NB85E_UART_ASIS_ADDR(n) (NB85E_UART_BASE_ADDR(n) + 0x3)
#define NB85E_UART_TXB_ADDR(n) (NB85E_UART_BASE_ADDR(n) + 0x4)
#define NB85E_UART_ASIF_ADDR(n) (NB85E_UART_BASE_ADDR(n) + 0x5)
#define NB85E_UART_CKSR_ADDR(n) (NB85E_UART_BASE_ADDR(n) + 0x6)
#define NB85E_UART_BRGC_ADDR(n) (NB85E_UART_BASE_ADDR(n) + 0x7)
#endif
/* UART config registers. */
#define NB85E_UART_ASIM(n) (*(volatile u8 *)NB85E_UART_ASIM_ADDR(n))
/* Control bits for config registers. */
#define NB85E_UART_ASIM_CAE 0x80 /* clock enable */
#define NB85E_UART_ASIM_TXE 0x40 /* transmit enable */
#define NB85E_UART_ASIM_RXE 0x20 /* receive enable */
#define NB85E_UART_ASIM_PS_MASK 0x18 /* mask covering parity-select bits */
#define NB85E_UART_ASIM_PS_NONE 0x00 /* no parity */
#define NB85E_UART_ASIM_PS_ZERO 0x08 /* zero parity */
#define NB85E_UART_ASIM_PS_ODD 0x10 /* odd parity */
#define NB85E_UART_ASIM_PS_EVEN 0x18 /* even parity */
#define NB85E_UART_ASIM_CL_8 0x04 /* char len is 8 bits (otherwise, 7) */
#define NB85E_UART_ASIM_SL_2 0x02 /* 2 stop bits (otherwise, 1) */
#define NB85E_UART_ASIM_ISRM 0x01 /* generate INTSR interrupt on errors
(otherwise, generate INTSER) */
/* UART serial interface status registers. */
#define NB85E_UART_ASIS(n) (*(volatile u8 *)NB85E_UART_ASIS_ADDR(n))
/* Control bits for status registers. */
#define NB85E_UART_ASIS_PE 0x04 /* parity error */
#define NB85E_UART_ASIS_FE 0x02 /* framing error */
#define NB85E_UART_ASIS_OVE 0x01 /* overrun error */
/* UART serial interface transmission status registers. */
#define NB85E_UART_ASIF(n) (*(volatile u8 *)NB85E_UART_ASIF_ADDR(n))
#define NB85E_UART_ASIF_TXBF 0x02 /* transmit buffer flag (data in TXB) */
#define NB85E_UART_ASIF_TXSF 0x01 /* transmit shift flag (sending data) */
/* UART receive buffer register. */
#define NB85E_UART_RXB(n) (*(volatile u8 *)NB85E_UART_RXB_ADDR(n))
/* UART transmit buffer register. */
#define NB85E_UART_TXB(n) (*(volatile u8 *)NB85E_UART_TXB_ADDR(n))
/* UART baud-rate generator control registers. */
#define NB85E_UART_CKSR(n) (*(volatile u8 *)NB85E_UART_CKSR_ADDR(n))
#define NB85E_UART_CKSR_MAX 11
#define NB85E_UART_CKSR_MAX_FREQ (25*1000*1000)
#define NB85E_UART_BRGC(n) (*(volatile u8 *)NB85E_UART_BRGC_ADDR(n))
/* This UART doesn't implement RTS/CTS by default, but some platforms
implement them externally, so check to see if <asm/machdep.h> defined
anything. */
#ifdef NB85E_UART_CTS
#define nb85e_uart_cts(n) NB85E_UART_CTS(n)
#else
#define nb85e_uart_cts(n) (1)
#endif
/* Do the same for RTS. */
#ifdef NB85E_UART_SET_RTS
#define nb85e_uart_set_rts(n,v) NB85E_UART_SET_RTS(n,v)
#else
#define nb85e_uart_set_rts(n,v) ((void)0)
#endif
/* Return true if all characters awaiting transmission on uart channel N
have been transmitted. */
#define nb85e_uart_xmit_done(n) \
(! (NB85E_UART_ASIF(n) & NB85E_UART_ASIF_TXBF))
/* Wait for this to be true. */
#define nb85e_uart_wait_for_xmit_done(n) \
do { } while (! nb85e_uart_xmit_done (n))
/* Return true if uart channel N is ready to transmit a character. */
#define nb85e_uart_xmit_ok(n) \
(nb85e_uart_xmit_done(n) && nb85e_uart_cts(n))
/* Wait for this to be true. */
#define nb85e_uart_wait_for_xmit_ok(n) \
do { } while (! nb85e_uart_xmit_ok (n))
/* Write character CH to uart channel N. */
#define nb85e_uart_putc(n, ch) (NB85E_UART_TXB(n) = (ch))
#define NB85E_UART_MINOR_BASE 64
#ifndef __ASSEMBLY__
/* Setup a console using channel 0 of the builtin uart. */
extern void nb85e_uart_cons_init (unsigned chan);
/* Configure and turn on uart channel CHAN, using the termios `control
modes' bits in CFLAGS, and a baud-rate of BAUD. */
void nb85e_uart_configure (unsigned chan, unsigned cflags, unsigned baud);
/* If the macro NB85E_UART_PRE_CONFIGURE is defined (presumably by a
<asm/machdep.h>), it is called from nb85e_uart_pre_configure before
anything else is done, with interrupts disabled. */
#endif /* !__ASSEMBLY__ */
#endif /* __V850_NB85E_UART_H__ */
/*
* include/asm-v850/nb85e_utils.h -- Utility functions associated with
* the NB85E cpu core
*
* Copyright (C) 2001 NEC Corporation
* Copyright (C) 2001 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#ifndef __V850_NB85E_UTILS_H__
#define __V850_NB85E_UTILS_H__
/* Calculate counter clock-divider and count values to attain the
desired frequency RATE from the base frequency BASE_FREQ. The
counter is expected to have a clock-divider, which can divide the
system cpu clock by a power of two value from MIN_DIVLOG2 to
MAX_DIV_LOG2, and a word-size of COUNTER_SIZE bits (the counter
counts up and resets whenever it's equal to the compare register,
generating an interrupt or whatever when it does so). The returned
values are: *DIVLOG2 -- log2 of the desired clock divider and *COUNT
-- the counter compare value to use. Returns true if it was possible
to find a reasonable value, otherwise false (and the other return
values will be set to be as good as possible). */
extern int calc_counter_params (unsigned long base_freq,
unsigned long rate,
unsigned min_divlog2, unsigned max_divlog2,
unsigned counter_size,
unsigned *divlog2, unsigned *count);
#endif /* __V850_NB85E_UTILS_H__ */
/*
* include/asm-v850/page.h -- VM ops
*
* Copyright (C) 2001, 2002 NEC Corporation
* Copyright (C) 2001, 2002 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#ifndef __V850_PAGE_H__
#define __V850_PAGE_H__
#include <asm/machdep.h>
#define PAGE_SHIFT 12
#define PAGE_SIZE (1UL << PAGE_SHIFT)
#define PAGE_MASK (~(PAGE_SIZE-1))
/*
* PAGE_OFFSET -- the first address of the first page of memory. For archs with
* no MMU this corresponds to the first free page in physical memory (aligned
* on a page boundary).
*/
#ifndef PAGE_OFFSET
#define PAGE_OFFSET 0x0000000
#endif
#ifdef __KERNEL__
#ifndef __ASSEMBLY__
#define STRICT_MM_TYPECHECKS
#define clear_page(page) memset ((void *)(page), 0, PAGE_SIZE)
#define copy_page(to, from) memcpy ((void *)(to), (void *)from, PAGE_SIZE)
#define clear_user_page(page, vaddr, pg) clear_page (page)
#define copy_user_page(to, from, vaddr,pg) copy_page (to, from)
#ifdef STRICT_MM_TYPECHECKS
/*
* These are used to make use of C type-checking..
*/
typedef struct { unsigned long pte; } pte_t;
typedef struct { unsigned long pmd; } pmd_t;
typedef struct { unsigned long pgd; } pgd_t;
typedef struct { unsigned long pgprot; } pgprot_t;
#define pte_val(x) ((x).pte)
#define pmd_val(x) ((x).pmd)
#define pgd_val(x) ((x).pgd)
#define pgprot_val(x) ((x).pgprot)
#define __pte(x) ((pte_t) { (x) } )
#define __pmd(x) ((pmd_t) { (x) } )
#define __pgd(x) ((pgd_t) { (x) } )
#define __pgprot(x) ((pgprot_t) { (x) } )
#else /* !STRICT_MM_TYPECHECKS */
/*
* .. while these make it easier on the compiler
*/
typedef unsigned long pte_t;
typedef unsigned long pmd_t;
typedef unsigned long pgd_t;
typedef unsigned long pgprot_t;
#define pte_val(x) (x)
#define pmd_val(x) (x)
#define pgd_val(x) (x)
#define pgprot_val(x) (x)
#define __pte(x) (x)
#define __pmd(x) (x)
#define __pgd(x) (x)
#define __pgprot(x) (x)
#endif /* STRICT_MM_TYPECHECKS */
#endif /* !__ASSEMBLY__ */
/* to align the pointer to the (next) page boundary */
#define PAGE_ALIGN(addr) (((addr) + PAGE_SIZE - 1) & PAGE_MASK)
#ifndef __ASSEMBLY__
extern void __bug (void) __attribute__ ((noreturn));
#define BUG() __bug()
#define PAGE_BUG(page) __bug()
/* Pure 2^n version of get_order */
extern __inline__ int get_order (unsigned long size)
{
int order;
size = (size-1) >> (PAGE_SHIFT-1);
order = -1;
do {
size >>= 1;
order++;
} while (size);
return order;
}
#endif /* !__ASSEMBLY__ */
/* No current v850 processor has virtual memory. */
#define __virt_to_phys(addr) (addr)
#define __phys_to_virt(addr) (addr)
#define virt_to_pfn(kaddr) (__virt_to_phys (kaddr) >> PAGE_SHIFT)
#define pfn_to_virt(pfn) __phys_to_virt ((pfn) << PAGE_SHIFT)
#define MAP_NR(kaddr) \
(((unsigned long)(kaddr) - PAGE_OFFSET) >> PAGE_SHIFT)
#define virt_to_page(kaddr) (mem_map + MAP_NR (kaddr))
#define page_to_virt(page) \
((((page) - mem_map) << PAGE_SHIFT) + PAGE_OFFSET)
#define pfn_to_page(pfn) virt_to_page (pfn_to_virt (pfn))
#define page_to_pfn(page) virt_to_pfn (page_to_virt (page))
#define virt_addr_valid(kaddr) \
(((void *)(kaddr) >= (void *)PAGE_OFFSET) && MAP_NR (kaddr) < max_mapnr)
#define __pa(x) __virt_to_phys ((unsigned long)(x))
#define __va(x) ((void *)__phys_to_virt ((unsigned long)(x)))
#endif /* KERNEL */
#endif /* __V850_PAGE_H__ */
/*
* include/asm-v850/param.h -- Varions kernel parameters
*
* Copyright (C) 2001,02 NEC Corporation
* Copyright (C) 2001,02 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#ifndef __V850_PARAM_H__
#define __V850_PARAM_H__
#include <asm/machdep.h> /* For HZ */
#define EXEC_PAGESIZE 4096
#ifndef NGROUPS
#define NGROUPS 32
#endif
#ifndef NOGROUP
#define NOGROUP (-1)
#endif
#define MAXHOSTNAMELEN 64 /* max length of hostname */
#ifdef __KERNEL__
# define USER_HZ 100
# define CLOCKS_PER_SEC USER_HZ
#endif
#endif /* __V850_PARAM_H__ */
/*
* include/asm-v850/pci.h -- PCI support
*
* Copyright (C) 2001,02 NEC Corporation
* Copyright (C) 2001,02 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#ifndef __V850_PCI_H__
#define __V850_PCI_H__
/* Get any platform-dependent definitions. */
#include <asm/machdep.h>
/* Generic declarations. */
struct scatterlist;
extern void pcibios_set_master (struct pci_dev *dev);
/* `Grant' to PDEV the memory block at CPU_ADDR, for doing DMA. The
32-bit PCI bus mastering address to use is returned. the device owns
this memory until either pci_unmap_single or pci_dma_sync_single is
performed. */
extern dma_addr_t
pci_map_single (struct pci_dev *pdev, void *cpu_addr, size_t size, int dir);
/* Return to the CPU the PCI DMA memory block previously `granted' to
PDEV, at DMA_ADDR. */
extern void
pci_unmap_single (struct pci_dev *pdev, dma_addr_t dma_addr, size_t size,
int dir);
/* Make physical memory consistant for a single streaming mode DMA
translation after a transfer.
If you perform a pci_map_single() but wish to interrogate the
buffer using the cpu, yet do not wish to teardown the PCI dma
mapping, you must call this function before doing so. At the next
point you give the PCI dma address back to the card, the device
again owns the buffer. */
extern void
pci_dma_sync_single (struct pci_dev *dev, dma_addr_t dma_addr, size_t size,
int dir);
/* Do multiple DMA mappings at once. */
extern int
pci_map_sg (struct pci_dev *pdev, struct scatterlist *sg, int sg_len, int dir);
/* Unmap multiple DMA mappings at once. */
extern void
pci_unmap_sg (struct pci_dev *pdev, struct scatterlist *sg, int sg_len,
int dir);
/* Allocate and map kernel buffer using consistent mode DMA for PCI
device. Returns non-NULL cpu-view pointer to the buffer if
successful and sets *DMA_ADDR to the pci side dma address as well,
else DMA_ADDR is undefined. */
extern void *
pci_alloc_consistent (struct pci_dev *pdev, size_t size, dma_addr_t *dma_addr);
/* Free and unmap a consistent DMA buffer. CPU_ADDR and DMA_ADDR must
be values that were returned from pci_alloc_consistent. SIZE must be
the same as what as passed into pci_alloc_consistent. References to
the memory and mappings assosciated with CPU_ADDR or DMA_ADDR past
this call are illegal. */
extern void
pci_free_consistent (struct pci_dev *pdev, size_t size, void *cpu_addr,
dma_addr_t dma_addr);
#endif /* __V850_PCI_H__ */
#ifndef __V850_PERCPU_H__
#define __V850_PERCPU_H__
#include <asm-generic/percpu.h>
#endif /* __V850_PERCPU_H__ */
/*
* include/asm-v850/pgalloc.h
*
* Copyright (C) 2001,02 NEC Corporation
* Copyright (C) 2001,02 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#ifndef __V850_PGALLOC_H__
#define __V850_PGALLOC_H__
#include <linux/mm.h> /* some crap code expects this */
/* ... and then, there was one. */
#define check_pgt_cache() ((void)0)
#endif /* __V850_PGALLOC_H__ */
#ifndef __V850_PGTABLE_H__
#define __V850_PGTABLE_H__
#include <linux/config.h>
#include <asm/page.h>
typedef pte_t *pte_addr_t;
#define pgd_present(pgd) (1) /* pages are always present on NO_MM */
#define pgd_none(pgd) (0)
#define pgd_bad(pgd) (0)
#define pgd_clear(pgdp) ((void)0)
#define pmd_offset(a, b) ((void *)0)
#define kern_addr_valid(addr) (1)
#define __swp_type(x) (0)
#define __swp_offset(x) (0)
#define __swp_entry(typ,off) ((swp_entry_t) { ((typ) | ((off) << 7)) })
#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) })
#define __swp_entry_to_pte(x) ((pte_t) { (x).val })
/* These mean nothing to !CONFIG_MMU. */
#define PAGE_NONE __pgprot(0)
#define PAGE_SHARED __pgprot(0)
#define PAGE_COPY __pgprot(0)
#define PAGE_READONLY __pgprot(0)
#define PAGE_KERNEL __pgprot(0)
/*
* ZERO_PAGE is a global shared page that is always zero: used
* for zero-mapped memory areas etc. When CONFIG_MMU is not defined, this
* should never actually be used, so just define it to something that's
* will hopefully cause a bus error if it is.
*/
#define ZERO_PAGE(vaddr) ((void *)0x87654321)
/* Some bogus code in procfs uses these; whatever. */
#define VMALLOC_START 0
#define VMALLOC_END (~0)
extern void paging_init (void);
#define swapper_pg_dir ((pgd_t *) 0)
#define pgtable_cache_init() ((void)0)
extern unsigned int kobjsize(const void *objp);
#endif /* __V850_PGTABLE_H__ */
#ifndef __V850_POLL_H__
#define __V850_POLL_H__
#define POLLIN 0x0001
#define POLLPRI 0x0002
#define POLLOUT 0x0004
#define POLLERR 0x0008
#define POLLHUP 0x0010
#define POLLNVAL 0x0020
#define POLLRDNORM 0x0040
#define POLLWRNORM POLLOUT
#define POLLRDBAND 0x0080
#define POLLWRBAND 0x0100
#define POLLMSG 0x0400
#define POLLREMOVE 0x1000
struct pollfd {
int fd;
short events;
short revents;
};
#endif /* __V850_POLL_H__ */
/*
* include/asm-v850/posix_types.h -- Kernel versions of standard types
*
* Copyright (C) 2001,02 NEC Corporation
* Copyright (C) 2001,02 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#ifndef __V850_POSIX_TYPES_H__
#define __V850_POSIX_TYPES_H__
typedef unsigned int __kernel_dev_t;
typedef unsigned long __kernel_ino_t;
typedef unsigned long long __kernel_ino64_t;
typedef unsigned int __kernel_mode_t;
typedef unsigned int __kernel_nlink_t;
typedef long __kernel_off_t;
typedef long long __kernel_loff_t;
typedef int __kernel_pid_t;
typedef unsigned short __kernel_ipc_pid_t;
typedef unsigned int __kernel_uid_t;
typedef unsigned int __kernel_gid_t;
typedef unsigned int __kernel_size_t;
typedef int __kernel_ssize_t;
typedef int __kernel_ptrdiff_t;
typedef long __kernel_time_t;
typedef long __kernel_suseconds_t;
typedef long __kernel_clock_t;
typedef int __kernel_daddr_t;
typedef char * __kernel_caddr_t;
typedef unsigned short __kernel_uid16_t;
typedef unsigned short __kernel_gid16_t;
typedef unsigned int __kernel_uid32_t;
typedef unsigned int __kernel_gid32_t;
/* Some bogus code depends on this; we don't care. */
typedef __kernel_uid_t __kernel_old_uid_t;
typedef struct {
#if defined(__KERNEL__) || defined(__USE_ALL)
int val[2];
#else /* !defined(__KERNEL__) && !defined(__USE_ALL) */
int __val[2];
#endif /* !defined(__KERNEL__) && !defined(__USE_ALL) */
} __kernel_fsid_t;
#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
#include <asm/bitops.h>
#undef __FD_SET
#define __FD_SET(fd, fd_set) \
__set_bit (fd, (void *)&((__kernel_fd_set *)fd_set)->fds_bits)
#undef __FD_CLR
#define __FD_CLR(fd, fd_set) \
__clear_bit (fd, (void *)&((__kernel_fd_set *)fd_set)->fds_bits)
#undef __FD_ISSET
#define __FD_ISSET(fd, fd_set) \
__test_bit (fd, (void *)&((__kernel_fd_set *)fd_set)->fds_bits)
#undef __FD_ZERO
#define __FD_ZERO(fd_set) \
memset (fd_set, 0, sizeof (*(fd_set *)fd_set))
#endif /* defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) */
#endif /* __V850_POSIX_TYPES_H__ */
/*
* include/asm-v850/processor.h
*
* Copyright (C) 2001,02 NEC Corporation
* Copyright (C) 2001,02 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#ifndef __V850_PROCESSOR_H__
#define __V850_PROCESSOR_H__
#include <linux/config.h>
#include <asm/ptrace.h>
#include <asm/thread_info.h>
#include <asm/entry.h>
/* Some code expects `segment' stuff to be defined here. */
#include <asm/segment.h>
/*
* The only places this is used seem to be horrible bletcherous kludges,
* so we just define it to be as large as possible.
*/
#define TASK_SIZE (0xFFFFFFFF)
#ifndef __ASSEMBLY__
/*
* Default implementation of macro that returns current
* instruction pointer ("program counter").
*/
#define current_text_addr() ({ __label__ _l; _l: &&_l;})
/*
* Bus types
*/
#define EISA_bus 0
#define EISA_bus__is_a_macro /* for versions in ksyms.c */
#define MCA_bus 0
#define MCA_bus__is_a_macro /* for versions in ksyms.c */
/* If you change this, you must change the associated assembly-languages
constants defined below, THREAD_*. */
struct thread_struct {
/* kernel stack pointer (must be first field in structure) */
unsigned long ksp;
};
#define INIT_THREAD { sizeof init_stack + (unsigned long)init_stack }
/* Do necessary setup to start up a newly executed thread. */
extern inline void start_thread (struct pt_regs *regs,
unsigned long pc, unsigned long usp)
{
regs->pc = pc;
regs->gpr[GPR_SP] = usp;
regs->kernel_mode = 0;
}
/* Free all resources held by a thread. */
extern inline void release_thread (struct task_struct *dead_task)
{
}
extern int kernel_thread (int (*fn)(void *), void * arg, unsigned long flags);
/* Free current thread data structures etc. */
static inline void exit_thread (void)
{
}
/* Return saved (kernel) PC of a blocked thread. */
extern inline unsigned long thread_saved_pc (struct thread_struct *t)
{
struct pt_regs *r = (struct pt_regs *)(t->ksp + STATE_SAVE_PT_OFFSET);
/* Actually, we return the LP register, because the thread is
actually blocked in switch_thread, and we're interested in
the PC it will _return_ to. */
return r->gpr[GPR_LP];
}
unsigned long get_wchan (struct task_struct *p);
/* Return some info about the user process TASK. */
#define task_tos(task) ((unsigned long)(task)->thread_info + THREAD_SIZE)
#define task_regs(task) ((struct pt_regs *)task_tos (task) - 1)
#define task_sp(task) (task_regs (task)->gpr[GPR_SP])
#define task_pc(task) (task_regs (task)->pc)
/* Grotty old names for some. */
#define KSTK_EIP(task) task_pc (task)
#define KSTK_ESP(task) task_sp (task)
#define cpu_relax() ((void)0)
#else /* __ASSEMBLY__ */
#define THREAD_KSP 0
#endif /* !__ASSEMBLY__ */
#endif /* __V850_PROCESSOR_H__ */
/*
* include/asm-v850/ptrace.h -- Access to CPU registers
*
* Copyright (C) 2001,02 NEC Corporation
* Copyright (C) 2001,02 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#ifndef __V850_PTRACE_H__
#define __V850_PTRACE_H__
/* v850 general purpose registers with special meanings. */
#define GPR_ZERO 0 /* constant zero */
#define GPR_ASM 1 /* reserved for assembler */
#define GPR_SP 3 /* stack pointer */
#define GPR_GP 4 /* global data pointer */
#define GPR_TP 5 /* `text pointer' */
#define GPR_EP 30 /* `element pointer' */
#define GPR_LP 31 /* link pointer (current return address) */
/* These aren't official names, but they make some code more descriptive. */
#define GPR_ARG0 6
#define GPR_ARG1 7
#define GPR_ARG2 8
#define GPR_ARG3 9
#define GPR_RVAL0 10
#define GPR_RVAL1 11
#define GPR_RVAL GPR_RVAL0
#define NUM_GPRS 32
/* v850 `system' registers. */
#define SR_EIPC 0
#define SR_EIPSW 1
#define SR_FEPC 2
#define SR_FEPSW 3
#define SR_ECR 4
#define SR_PSW 5
#define SR_CTPC 16
#define SR_CTPSW 17
#define SR_DBPC 18
#define SR_DBPSW 19
#define SR_CTBP 20
#define SR_DIR 21
#define SR_ASID 23
#ifndef __ASSEMBLY__
typedef unsigned long v850_reg_t;
/* How processor state is stored on the stack during a syscall/signal.
If you change this structure, change the associated assembly-language
macros below too (PT_*)! */
struct pt_regs
{
/* General purpose registers. */
v850_reg_t gpr[NUM_GPRS];
v850_reg_t pc; /* program counter */
v850_reg_t psw; /* program status word */
/* Registers used by `callt' instruction: */
v850_reg_t ctpc; /* saved program counter */
v850_reg_t ctpsw; /* saved psw */
v850_reg_t ctbp; /* base pointer for callt table */
char kernel_mode; /* 1 if in `kernel mode', 0 if user mode */
};
#define instruction_pointer(regs) ((regs)->pc)
#define user_mode(regs) (!(regs)->kernel_mode)
/* When a struct pt_regs is used to save user state for a system call in
the kernel, the system call is stored in the space for R0 (since it's
never used otherwise, R0 being a constant 0). Non-system-calls
simply store 0 there. */
#define PT_REGS_SYSCALL(regs) (regs)->gpr[0]
#define PT_REGS_SET_SYSCALL(regs, val) ((regs)->gpr[0] = (val))
#endif /* !__ASSEMBLY__ */
/* The number of bytes used to store each register. */
#define _PT_REG_SIZE 4
/* Offset of a general purpose register in a stuct pt_regs. */
#define PT_GPR(num) ((num) * _PT_REG_SIZE)
/* Offsets of various special registers & fields in a struct pt_regs. */
#define PT_PC ((NUM_GPRS + 0) * _PT_REG_SIZE)
#define PT_PSW ((NUM_GPRS + 1) * _PT_REG_SIZE)
#define PT_CTPC ((NUM_GPRS + 2) * _PT_REG_SIZE)
#define PT_CTPSW ((NUM_GPRS + 3) * _PT_REG_SIZE)
#define PT_CTBP ((NUM_GPRS + 4) * _PT_REG_SIZE)
#define PT_KERNEL_MODE ((NUM_GPRS + 5) * _PT_REG_SIZE)
#define PT_SYSCALL PT_GPR(0)
/* Size of struct pt_regs, including alignment. */
#define PT_SIZE ((NUM_GPRS + 6) * _PT_REG_SIZE)
#endif /* __V850_PTRACE_H__ */
#ifndef __V850_RESOURCE_H__
#define __V850_RESOURCE_H__
/*
* Resource limits
*/
#define RLIMIT_CPU 0 /* CPU time in ms */
#define RLIMIT_FSIZE 1 /* Maximum filesize */
#define RLIMIT_DATA 2 /* max data size */
#define RLIMIT_STACK 3 /* max stack size */
#define RLIMIT_CORE 4 /* max core file size */
#define RLIMIT_RSS 5 /* max resident set size */
#define RLIMIT_NPROC 6 /* max number of processes */
#define RLIMIT_NOFILE 7 /* max number of open files */
#define RLIMIT_MEMLOCK 8 /* max locked-in-memory address space */
#define RLIMIT_AS 9 /* address space limit */
#define RLIMIT_LOCKS 10 /* maximum file locks held */
#define RLIM_NLIMITS 11
/*
* SuS says limits have to be unsigned.
* Which makes a ton more sense anyway.
*/
#define RLIM_INFINITY (~0UL)
#ifdef __KERNEL__
#define INIT_RLIMITS \
{ \
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ _STK_LIM, RLIM_INFINITY }, \
{ 0, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ 0, 0 }, \
{ INR_OPEN, INR_OPEN }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
}
#endif /* __KERNEL__ */
#endif /* __V850_RESOURCE_H__ */
/* Do not need anything here */
/*
* include/asm-v850/rte_cb.h -- Midas labs RTE-CB series of evaluation boards
*
* Copyright (C) 2001,02 NEC Corporation
* Copyright (C) 2001,02 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#ifndef __V850_RTE_CB_H__
#define __V850_RTE_CB_H__
/* CPU addresses of GBUS memory spaces. */
#define GCS0_ADDR 0x05000000 /* GCS0 - Common SRAM (2MB) */
#define GCS0_SIZE 0x00200000 /* 2MB */
#define GCS1_ADDR 0x06000000 /* GCS1 - Flash ROM (8MB) */
#define GCS1_SIZE 0x00800000 /* 8MB */
#define GCS2_ADDR 0x07900000 /* GCS2 - I/O registers */
#define GCS2_SIZE 0x00400000 /* 4MB */
#define GCS5_ADDR 0x04000000 /* GCS5 - PCI bus space */
#define GCS5_SIZE 0x01000000 /* 16MB */
#define GCS6_ADDR 0x07980000 /* GCS6 - PCI control registers */
#define GCS6_SIZE 0x00000200 /* 512B */
/* The SRAM on the Mother-A motherboard. */
#define MB_A_SRAM_ADDR GCS0_ADDR
#define MB_A_SRAM_SIZE 0x00200000 /* 2MB */
/* GBUS interrupt support. */
#define GBUS_INT_BASE_IRQ NUM_CPU_IRQS
#define GBUS_INT_BASE_ADDR (GCS2_ADDR + 0x00006000)
#include <asm/gbus_int.h>
/* We define NUM_MACH_IRQS to include extra interrupts from the GBUS. */
#define NUM_MACH_IRQS (NUM_CPU_IRQS + IRQ_GBUS_INT_NUM)
/* Some specific interrupts. */
#define IRQ_MB_A_LAN IRQ_GBUS_INT(10)
#define IRQ_MB_A_PCI1(n) (IRQ_GBUS_INT(16) + (n))
#define IRQ_MB_A_PCI1_NUM 4
#define IRQ_MB_A_PCI2(n) (IRQ_GBUS_INT(20) + (n))
#define IRQ_MB_A_PCI2_NUM 4
#define IRQ_MB_A_EXT(n) (IRQ_GBUS_INT(24) + (n))
#define IRQ_MB_A_EXT_NUM 4
#define IRQ_MB_A_USB_OC(n) (IRQ_GBUS_INT(28) + (n))
#define IRQ_MB_A_USB_OC_NUM 2
#define IRQ_MB_A_PCMCIA_OC IRQ_GBUS_INT(30)
/* Mother-A PCI bus support. */
#include <asm/rte_mb_a_pci.h>
/* These are the base addresses used for allocating device address
space. 512K of the motherboard SRAM is in the same space, so we have
to be careful not to let it be allocated. */
#define PCIBIOS_MIN_MEM (MB_A_PCI_MEM_ADDR + 0x80000)
#define PCIBIOS_MIN_IO MB_A_PCI_IO_ADDR
/* As we don't really support PCI DMA to cpu memory, and use bounce-buffers
instead, perversely enough, this becomes always true! */
#define pci_dma_supported(dev, mask) 1
#define pci_dac_dma_supported(dev, mask) 0
#define pci_controller_num(dev) 0
#define pcibios_assign_all_busses() 1
/* For <asm/param.h> */
#ifndef HZ
#define HZ 100
#endif
#ifndef __ASSEMBLY__
extern void rte_cb_init_irqs (void);
#endif /* !__ASSEMBLY__ */
#endif /* __V850_RTE_CB_H__ */
/*
* include/asm-v850/rte_ma1_cb.h -- Midas labs RTE-V850/MA1-CB board
*
* Copyright (C) 2001,02 NEC Corporation
* Copyright (C) 2001,02 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#ifndef __V850_RTE_MA1_CB_H__
#define __V850_RTE_MA1_CB_H__
#include <asm/rte_cb.h> /* Common defs for Midas RTE-CB boards. */
/* The GBUS GINT0 - GINT4 interrupts are connected to the INTP000 - INTP011
pins on the CPU. These are shared among the GBUS interrupts. */
#define IRQ_GINT(n) IRQ_INTP(n)
#define IRQ_GINT_NUM 4
#define PLATFORM "rte-v850e/ma1-cb"
#define PLATFORM_LONG "Midas lab RTE-V850E/MA1-CB"
#define CPU_CLOCK_FREQ 50000000 /* 50MHz */
/* 1MB of onboard SRAM. Note that the monitor ROM uses parts of this
for its own purposes, so care must be taken. Some address lines are
not decoded, so the SRAM area is mirrored every 1MB from 0x400000 to
0x800000 (exclusive). */
#define SRAM_ADDR 0x00400000
#define SRAM_SIZE 0x00100000 /* 1MB */
/* 32MB of onbard SDRAM. */
#define SDRAM_ADDR 0x00800000
#define SDRAM_SIZE 0x02000000 /* 32MB */
/* For <asm/page.h> */
#define PAGE_OFFSET SRAM_ADDR
#ifdef CONFIG_ROM_KERNEL
/* Kernel is in ROM, starting at address 0. */
#define INTV_BASE 0
#else /* !CONFIG_ROM_KERNEL */
#ifdef CONFIG_RTE_CB_MULTI
/* Using RAM kernel with ROM monitor for Multi debugger. */
/* The chip's real interrupt vectors are in ROM, but they jump to a
secondary interrupt vector table in RAM. */
#define INTV_BASE 0x004F8000
/* Scratch memory used by the ROM monitor, which shouldn't be used by
linux (except for the alternate interrupt vector area, defined
above). */
#define MON_SCRATCH_ADDR 0x004F8000
#define MON_SCRATCH_SIZE 0x00008000 /* 32KB */
#else /* !CONFIG_RTE_CB_MULTI */
/* Using RAM-kernel. Assume some sort of boot-loader got us loaded at
address 0. */
#define INTV_BASE 0
#endif /* CONFIG_RTE_CB_MULTI */
#endif /* CONFIG_ROM_KERNEL */
/* Some misc. on-board devices. */
/* Seven-segment LED display (two digits). Write-only. */
#define LED_ADDR(n) (0x07802000 + (n))
#define LED(n) (*(volatile unsigned char *)LED_ADDR(n))
#define LED_NUM_DIGITS 2
/* Override the basic MA uart pre-initialization so that we can
initialize extra stuff. */
#undef NB85E_UART_PRE_CONFIGURE /* should be defined by <asm/ma.h> */
#define NB85E_UART_PRE_CONFIGURE rte_ma1_cb_uart_pre_configure
#ifndef __ASSEMBLY__
extern void rte_ma1_cb_uart_pre_configure (unsigned chan,
unsigned cflags, unsigned baud);
#endif
/* This board supports RTS/CTS for the on-chip UART, but only for channel 0. */
/* CTS for UART channel 0 is pin P43 (bit 3 of port 4). */
#define NB85E_UART_CTS(chan) ((chan) == 0 ? !(MA_PORT4_IO & 0x8) : 1)
/* RTS for UART channel 0 is pin P42 (bit 2 of port 4). */
#define NB85E_UART_SET_RTS(chan, val) \
do { \
if (chan == 0) { \
unsigned old = MA_PORT4_IO; \
if (val) \
MA_PORT4_IO = old & ~0x4; \
else \
MA_PORT4_IO = old | 0x4; \
} \
} while (0)
#endif /* __V850_RTE_MA1_CB_H__ */
/*
* include/asm-v850/mb_a_pci.h -- PCI support for Midas lab RTE-MOTHER-A board
*
* Copyright (C) 2001 NEC Corporation
* Copyright (C) 2001 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#ifndef __V850_MB_A_PCI_H__
#define __V850_MB_A_PCI_H__
#define MB_A_PCI_MEM_ADDR GCS5_ADDR
#define MB_A_PCI_MEM_SIZE (GCS5_SIZE / 2)
#define MB_A_PCI_IO_ADDR (GCS5_ADDR + MB_A_PCI_MEM_SIZE)
#define MB_A_PCI_IO_SIZE (GCS5_SIZE / 2)
#define MB_A_PCI_REG_BASE_ADDR GCS6_ADDR
#define MB_A_PCI_PCICR_ADDR (MB_A_PCI_REG_BASE_ADDR + 0x4)
#define MB_A_PCI_PCICR (*(volatile u16 *)MB_A_PCI_PCICR_ADDR)
#define MB_A_PCI_PCISR_ADDR (MB_A_PCI_REG_BASE_ADDR + 0x6)
#define MB_A_PCI_PCISR (*(volatile u16 *)MB_A_PCI_PCISR_ADDR)
#define MB_A_PCI_PCILTR_ADDR (MB_A_PCI_REG_BASE_ADDR + 0xD)
#define MB_A_PCI_PCILTR (*(volatile u8 *)MB_A_PCI_PCILTR_ADDR)
#define MB_A_PCI_PCIBAR0_ADDR (MB_A_PCI_REG_BASE_ADDR + 0x10)
#define MB_A_PCI_PCIBAR0 (*(volatile u32 *)MB_A_PCI_PCIBAR0_ADDR)
#define MB_A_PCI_PCIBAR1_ADDR (MB_A_PCI_REG_BASE_ADDR + 0x14)
#define MB_A_PCI_PCIBAR1 (*(volatile u32 *)MB_A_PCI_PCIBAR1_ADDR)
#define MB_A_PCI_PCIBAR2_ADDR (MB_A_PCI_REG_BASE_ADDR + 0x18)
#define MB_A_PCI_PCIBAR2 (*(volatile u32 *)MB_A_PCI_PCIBAR2_ADDR)
#define MB_A_PCI_VENDOR_ID_ADDR (MB_A_PCI_REG_BASE_ADDR + 0x2C)
#define MB_A_PCI_VENDOR_ID (*(volatile u16 *)MB_A_PCI_VENDOR_ID_ADDR)
#define MB_A_PCI_DEVICE_ID_ADDR (MB_A_PCI_REG_BASE_ADDR + 0x2E)
#define MB_A_PCI_DEVICE_ID (*(volatile u16 *)MB_A_PCI_DEVICE_ID_ADDR)
#define MB_A_PCI_DMRR_ADDR (MB_A_PCI_REG_BASE_ADDR + 0x9C)
#define MB_A_PCI_DMRR (*(volatile u32 *)MB_A_PCI_DMRR_ADDR)
#define MB_A_PCI_DMLBAM_ADDR (MB_A_PCI_REG_BASE_ADDR + 0xA0)
#define MB_A_PCI_DMLBAM (*(volatile u32 *)MB_A_PCI_DMLBAM_ADDR)
#define MB_A_PCI_DMLBAI_ADDR (MB_A_PCI_REG_BASE_ADDR + 0xA4)
#define MB_A_PCI_DMLBAI (*(volatile u32 *)MB_A_PCI_DMLBAI_ADDR)
#define MB_A_PCI_PCIPBAM_ADDR (MB_A_PCI_REG_BASE_ADDR + 0xA8)
#define MB_A_PCI_PCIPBAM (*(volatile u32 *)MB_A_PCI_PCIPBAM_ADDR)
/* `PCI Configuration Address Register for Direct Master to PCI IO/CFG' */
#define MB_A_PCI_DMCFGA_ADDR (MB_A_PCI_REG_BASE_ADDR + 0xAC)
#define MB_A_PCI_DMCFGA (*(volatile u32 *)MB_A_PCI_DMCFGA_ADDR)
/* `PCI Permanent Configuration ID Register' */
#define MB_A_PCI_PCIHIDR_ADDR (MB_A_PCI_REG_BASE_ADDR + 0xF0)
#define MB_A_PCI_PCIHIDR (*(volatile u32 *)MB_A_PCI_PCIHIDR_ADDR)
#endif /* __V850_MB_A_PCI_H__ */
/*
* include/asm-v850/rte_nb85e_cb.h -- Midas labs RTE-V850/NB85E-CB board
*
* Copyright (C) 2001,02 NEC Corporation
* Copyright (C) 2001,02 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#ifndef __V850_RTE_NB85E_CB_H__
#define __V850_RTE_NB85E_CB_H__
#include <asm/rte_cb.h> /* Common defs for Midas RTE-CB boards. */
#define PLATFORM "rte-v850e/nb85e-cb"
#define PLATFORM_LONG "Midas lab RTE-V850E/NB85E-CB"
#define CPU_CLOCK_FREQ 50000000 /* 50MHz */
/* 1MB of onboard SRAM. Note that the monitor ROM uses parts of this
for its own purposes, so care must be taken. */
#define SRAM_ADDR 0x03C00000
#define SRAM_SIZE 0x00100000 /* 1MB */
/* 16MB of onbard SDRAM. */
#define SDRAM_ADDR 0x01000000
#define SDRAM_SIZE 0x01000000 /* 16MB */
#ifdef CONFIG_ROM_KERNEL
/* Kernel is in ROM, starting at address 0. */
#define INTV_BASE 0
#else /* !CONFIG_ROM_KERNEL */
/* We're using the ROM monitor. */
/* The chip's real interrupt vectors are in ROM, but they jump to a
secondary interrupt vector table in RAM. */
#define INTV_BASE 0x004F8000
/* Scratch memory used by the ROM monitor, which shouldn't be used by
linux (except for the alternate interrupt vector area, defined
above). */
#define MON_SCRATCH_ADDR 0x03CE8000
#define MON_SCRATCH_SIZE 0x00008000 /* 32KB */
#endif /* CONFIG_ROM_KERNEL */
/* Some misc. on-board devices. */
/* Seven-segment LED display (two digits). Write-only. */
#define LED_ADDR(n) (0x03802000 + (n))
#define LED(n) (*(volatile unsigned char *)LED_ADDR(n))
#define LED_NUM_DIGITS 4
#endif /* __V850_RTE_NB85E_CB_H__ */
/*
* include/asm-v850/scatterlist.h
*
* Copyright (C) 2001,02 NEC Corporation
* Copyright (C) 2001,02 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#ifndef __V850_SCATTERLIST_H__
#define __V850_SCATTERLIST_H__
struct scatterlist {
struct page *page;
unsigned offset;
dma_addr_t dma_address;
unsigned length;
};
#define ISA_DMA_THRESHOLD (~0UL)
#endif /* __V850_SCATTERLIST_H__ */
#ifndef __V850_SEGMENT_H__
#define __V850_SEGMENT_H__
#ifndef __ASSEMBLY__
typedef unsigned long mm_segment_t; /* domain register */
#endif /* !__ASSEMBLY__ */
#define __KERNEL_CS 0x0
#define __KERNEL_DS 0x0
#define __USER_CS 0x1
#define __USER_DS 0x1
#define KERNEL_DS __KERNEL_DS
#define KERNEL_CS __KERNEL_CS
#define USER_DS __USER_DS
#define USER_CS __USER_CS
#define segment_eq(a,b) ((a) == (b))
#define get_ds() (KERNEL_DS)
#define get_fs() (USER_DS)
#define set_fs(seg) ((void)(seg))
#define copy_segments(task, mm) ((void)((void)(task), (mm)))
#define release_segments(mm) ((void)(mm))
#define forget_segments() ((void)0)
#endif /* __V850_SEGMENT_H__ */
#ifndef __V850_SEMAPHORE_H__
#define __V850_SEMAPHORE_H__
#include <linux/linkage.h>
#include <linux/spinlock.h>
#include <linux/wait.h>
#include <linux/rwsem.h>
#include <asm/atomic.h>
struct semaphore {
atomic_t count;
int sleepers;
wait_queue_head_t wait;
};
#define __SEMAPHORE_INITIALIZER(name,count) \
{ ATOMIC_INIT (count), 0, \
__WAIT_QUEUE_HEAD_INITIALIZER ((name).wait) }
#define __MUTEX_INITIALIZER(name) \
__SEMAPHORE_INITIALIZER (name,1)
#define __DECLARE_SEMAPHORE_GENERIC(name,count) \
struct semaphore name = __SEMAPHORE_INITIALIZER (name,count)
#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC (name,1)
#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC (name,0)
extern inline void sema_init (struct semaphore *sem, int val)
{
*sem = (struct semaphore)__SEMAPHORE_INITIALIZER((*sem),val);
}
static inline void init_MUTEX (struct semaphore *sem)
{
sema_init (sem, 1);
}
static inline void init_MUTEX_LOCKED (struct semaphore *sem)
{
sema_init (sem, 0);
}
/*
* special register calling convention
*/
asmlinkage void __down_failed (void);
asmlinkage int __down_interruptible_failed (void);
asmlinkage int __down_trylock_failed (void);
asmlinkage void __up_wakeup (void);
extern void __down (struct semaphore * sem);
extern int __down_interruptible (struct semaphore * sem);
extern int __down_trylock (struct semaphore * sem);
extern void __up (struct semaphore * sem);
extern inline void down (struct semaphore * sem)
{
if (atomic_dec_return (&sem->count) < 0)
__down (sem);
}
extern inline int down_interruptible (struct semaphore * sem)
{
int ret = 0;
if (atomic_dec_return (&sem->count) < 0)
ret = __down_interruptible (sem);
return ret;
}
extern inline int down_trylock (struct semaphore *sem)
{
int ret = 0;
if (atomic_dec_return (&sem->count) < 0)
ret = __down_trylock (sem);
return ret;
}
extern inline void up (struct semaphore * sem)
{
if (atomic_inc_return (&sem->count) <= 0)
__up (sem);
}
#endif /* __V850_SEMAPHORE_H__ */
#ifndef __V850_SEMBUF_H__
#define __V850_SEMBUF_H__
/*
* The semid64_ds structure for v850 architecture.
* Note extra padding because this structure is passed back and forth
* between kernel and user space.
*
* Pad space is left for:
* - 64-bit time_t to solve y2038 problem
* - 2 miscellaneous 32-bit values
*/
struct semid64_ds {
struct ipc64_perm sem_perm; /* permissions .. see ipc.h */
__kernel_time_t sem_otime; /* last semop time */
unsigned long __unused1;
__kernel_time_t sem_ctime; /* last change time */
unsigned long __unused2;
unsigned long sem_nsems; /* no. of semaphores in array */
unsigned long __unused3;
unsigned long __unused4;
};
#endif /* __V850_SEMBUF_H__ */
/*
* include/asm-v850/setup.h
*
* Copyright (C) 2001 NEC Corporation
* Copyright (C) 2001 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#ifndef __V850_SETUP_H__
#define __V850_SETUP_H__
/* Linux/v850 platforms. This corresponds roughly to what the outside
the CPU looks like. */
#define MACH_SIM 1 /* GDB architectural simulator */
/* v850 cpu architectures. This is what a user-program would be
concerned with. */
#define CPU_ARCH_V850E 1
#define CPU_ARCH_V850E2 2
/* v850 cpu `cores'. These are system-level extensions to the basic CPU,
defining such things as interrupt-handling. */
#define CPU_CORE_NB85E 1
#define CPU_CORE_NB85ET 2
#define CPU_CORE_NU85E 3
#define CPU_CORE_NU85ET 4
/* Specific v850 cpu chips. These each incorporate a `core', and add
varions peripheral services. */
#define CPU_CHIP_MA1 1
#endif /* __V850_SETUP_H__ */
#ifndef __V850_SHMBUF_H__
#define __V850_SHMBUF_H__
/*
* The shmid64_ds structure for v850 architecture.
* Note extra padding because this structure is passed back and forth
* between kernel and user space.
*
* Pad space is left for:
* - 64-bit time_t to solve y2038 problem
* - 2 miscellaneous 32-bit values
*/
struct shmid64_ds {
struct ipc64_perm shm_perm; /* operation perms */
size_t shm_segsz; /* size of segment (bytes) */
__kernel_time_t shm_atime; /* last attach time */
unsigned long __unused1;
__kernel_time_t shm_dtime; /* last detach time */
unsigned long __unused2;
__kernel_time_t shm_ctime; /* last change time */
unsigned long __unused3;
__kernel_pid_t shm_cpid; /* pid of creator */
__kernel_pid_t shm_lpid; /* pid of last operator */
unsigned long shm_nattch; /* no. of current attaches */
unsigned long __unused4;
unsigned long __unused5;
};
struct shminfo64 {
unsigned long shmmax;
unsigned long shmmin;
unsigned long shmmni;
unsigned long shmseg;
unsigned long shmall;
unsigned long __unused1;
unsigned long __unused2;
unsigned long __unused3;
unsigned long __unused4;
};
#endif /* __V850_SHMBUF_H__ */
#ifndef __V850_SHMPARAM_H__
#define __V850_SHMPARAM_H__
#define SHMLBA PAGE_SIZE /* attach addr a multiple of this */
#endif /* __V850_SHMPARAM_H__ */
/*
* include/asm-v850/sigcontext.h -- Signal contexts
*
* Copyright (C) 2001 NEC Corporation
* Copyright (C) 2001 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#ifndef __V850_SIGCONTEXT_H__
#define __V850_SIGCONTEXT_H__
#include <asm/ptrace.h>
struct sigcontext
{
struct pt_regs regs;
unsigned long oldmask;
};
#endif /* __V850_SIGCONTEXT_H__ */
#ifndef __V850_SIGINFO_H__
#define __V850_SIGINFO_H__
#include <asm-generic/siginfo.h>
#endif /* __V850_SIGINFO_H__ */
#ifndef __V850_SIGNAL_H__
#define __V850_SIGNAL_H__
#include <linux/types.h>
/* Avoid too many header ordering problems. */
struct siginfo;
#ifdef __KERNEL__
/* Most things should be clean enough to redefine this at will, if care
is taken to make libc match. */
#define _NSIG 64
#define _NSIG_BPW 32
#define _NSIG_WORDS (_NSIG / _NSIG_BPW)
typedef unsigned long old_sigset_t; /* at least 32 bits */
typedef struct {
unsigned long sig[_NSIG_WORDS];
} sigset_t;
#else /* !__KERNEL__ */
/* Here we must cater to libcs that poke about in kernel headers. */
#define NSIG 32
typedef unsigned long sigset_t;
#endif /* __KERNEL__ */
#define SIGHUP 1
#define SIGINT 2
#define SIGQUIT 3
#define SIGILL 4
#define SIGTRAP 5
#define SIGABRT 6
#define SIGIOT 6
#define SIGBUS 7
#define SIGFPE 8
#define SIGKILL 9
#define SIGUSR1 10
#define SIGSEGV 11
#define SIGUSR2 12
#define SIGPIPE 13
#define SIGALRM 14
#define SIGTERM 15
#define SIGSTKFLT 16
#define SIGCHLD 17
#define SIGCONT 18
#define SIGSTOP 19
#define SIGTSTP 20
#define SIGTTIN 21
#define SIGTTOU 22
#define SIGURG 23
#define SIGXCPU 24
#define SIGXFSZ 25
#define SIGVTALRM 26
#define SIGPROF 27
#define SIGWINCH 28
#define SIGIO 29
#define SIGPOLL SIGIO
/*
#define SIGLOST 29
*/
#define SIGPWR 30
#define SIGSYS 31
#define SIGUNUSED 31
/* These should not be considered constants from userland. */
#define SIGRTMIN 32
#define SIGRTMAX (_NSIG-1)
/*
* SA_FLAGS values:
*
* SA_ONSTACK indicates that a registered stack_t will be used.
* SA_INTERRUPT is a no-op, but left due to historical reasons. Use the
* SA_RESTART flag to get restarting signals (which were the default long ago)
* SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
* SA_RESETHAND clears the handler when the signal is delivered.
* SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
* SA_NODEFER prevents the current signal from being masked in the handler.
*
* SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
* Unix names RESETHAND and NODEFER respectively.
*/
#define SA_NOCLDSTOP 0x00000001
#define SA_NOCLDWAIT 0x00000002 /* not supported yet */
#define SA_SIGINFO 0x00000004
#define SA_ONSTACK 0x08000000
#define SA_RESTART 0x10000000
#define SA_NODEFER 0x40000000
#define SA_RESETHAND 0x80000000
#define SA_NOMASK SA_NODEFER
#define SA_ONESHOT SA_RESETHAND
#define SA_INTERRUPT 0x20000000 /* dummy -- ignored */
#define SA_RESTORER 0x04000000
/*
* sigaltstack controls
*/
#define SS_ONSTACK 1
#define SS_DISABLE 2
#define MINSIGSTKSZ 2048
#define SIGSTKSZ 8192
#ifdef __KERNEL__
/*
* These values of sa_flags are used only by the kernel as part of the
* irq handling routines.
*
* SA_INTERRUPT is also used by the irq handling routines.
* SA_SHIRQ is for shared interrupt support on PCI and EISA.
*/
#define SA_PROBE SA_ONESHOT
#define SA_SAMPLE_RANDOM SA_RESTART
#define SA_SHIRQ 0x04000000
#endif /* __KERNEL__ */
#define SIG_BLOCK 0 /* for blocking signals */
#define SIG_UNBLOCK 1 /* for unblocking signals */
#define SIG_SETMASK 2 /* for setting the signal mask */
/* Type of a signal handler. */
typedef void (*__sighandler_t)(int);
#define SIG_DFL ((__sighandler_t)0) /* default signal handling */
#define SIG_IGN ((__sighandler_t)1) /* ignore signal */
#define SIG_ERR ((__sighandler_t)-1) /* error return from signal */
#ifdef __KERNEL__
struct old_sigaction {
__sighandler_t sa_handler;
old_sigset_t sa_mask;
unsigned long sa_flags;
void (*sa_restorer)(void);
};
struct sigaction {
__sighandler_t sa_handler;
unsigned long sa_flags;
void (*sa_restorer)(void);
sigset_t sa_mask; /* mask last for extensibility */
};
struct k_sigaction {
struct sigaction sa;
};
#else /* !__KERNEL__ */
/* Here we must cater to libcs that poke about in kernel headers. */
struct sigaction {
union {
__sighandler_t _sa_handler;
void (*_sa_sigaction)(int, struct siginfo *, void *);
} _u;
sigset_t sa_mask;
unsigned long sa_flags;
void (*sa_restorer)(void);
};
#define sa_handler _u._sa_handler
#define sa_sigaction _u._sa_sigaction
#endif /* __KERNEL__ */
typedef struct sigaltstack {
void *ss_sp;
int ss_flags;
size_t ss_size;
} stack_t;
#ifdef __KERNEL__
#include <asm/sigcontext.h>
#undef __HAVE_ARCH_SIG_BITOPS
#endif /* __KERNEL__ */
#endif /* __V850_SIGNAL_H__ */
/*
* include/asm-v850/sim.h -- Machine-dependent defs for GDB v850e simulator
*
* Copyright (C) 2001,02 NEC Corporation
* Copyright (C) 2001,02 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#ifndef __V850_SIM_H__
#define __V850_SIM_H__
#define CPU_ARCH "v850e"
#define CPU_MODEL "GDB/v850e simulator"
/* We use a wierd value for RAM, not just 0, for testing purposes.
These must match the values used in the linker script. */
#define RAM_ADDR 0x8F000000
#define RAM_SIZE 0x01000000
/* For <asm/page.h> */
#define PAGE_OFFSET RAM_ADDR
/* For <asm/entry.h> */
/* `R0 RAM', used for a few miscellaneous variables that must be
accessible using a load instruction relative to R0. On real
processors, this usually is on-chip RAM, but here we just
choose an arbitrary address that meets the above constraint. */
#define R0_RAM_ADDR 0xFFFFF000
/* For <asm/param.h> */
#ifndef HZ
#define HZ 24 /* Minimum supported frequency. */
#endif
/* For <asm/irq.h> */
#define NUM_CPU_IRQS 6
#endif /* __V850_SIM_H__ */
/*
* include/asm-v850/sim85e2c.h -- Machine-dependent defs for
* V850E2 RTL simulator
*
* Copyright (C) 2002 NEC Corporation
* Copyright (C) 2002 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#ifndef __V850_SIM85E2C_H__
#define __V850_SIM85E2C_H__
#define CPU_ARCH "v850e2"
#define CPU_MODEL "sim85e2c simulator"
/* Various memory areas supported by the simulator.
These should match the corresponding definitions in the linker script. */
/* `instruction RAM'; instruction fetches are much faster from IRAM than
from DRAM. */
#define IRAM_ADDR 0
#define IRAM_SIZE 0x00100000 /* 1MB */
/* `data RAM', below and contiguous with the I/O space.
Data fetches are much faster from DRAM than from IRAM. */
#define DRAM_ADDR 0xfff00000
#define DRAM_SIZE 0x000ff000 /* 1020KB */
/* `external ram'. Unlike the above RAM areas, this memory is cached,
so both instruction and data fetches should be (mostly) fast --
however, currently only write-through caching is supported, so writes
to ERAM will be slow. */
#define ERAM_ADDR 0x00100000
#define ERAM_SIZE 0x07f00000 /* 127MB (max) */
/* CPU core control registers; these should be expanded and moved into
separate header files when we support some other processors based on
the same E2 core. */
/* Bus Transaction Control Register */
#define NA85E2C_CACHE_BTSC_ADDR 0xfffff070
#define NA85E2C_CACHE_BTSC (*(volatile unsigned short *)NA85E2C_CACHE_BTSC_ADDR)
#define NA85E2C_CACHE_BTSC_ICM 0x1 /* icache enable */
#define NA85E2C_CACHE_BTSC_DCM0 0x4 /* dcache enable, bit 0 */
#define NA85E2C_CACHE_BTSC_DCM1 0x8 /* dcache enable, bit 1 */
/* Cache Configuration Register */
#define NA85E2C_BUSM_BHC_ADDR 0xfffff06a
#define NA85E2C_BUSM_BHC (*(volatile unsigned short *)NA85E2C_BUSM_BHC_ADDR)
/* Simulator specific control registers. */
/* NOTHAL controls whether the simulator will stop at a `halt' insn. */
#define NOTHAL_ADDR 0xffffff22
#define NOTHAL (*(volatile unsigned char *)NOTHAL_ADDR)
/* The simulator will stop N cycles after N is written to SIMFIN. */
#define SIMFIN_ADDR 0xffffff24
#define SIMFIN (*(volatile unsigned short *)SIMFIN_ADDR)
/* The simulator has an nb85e-style interrupt system. */
#include <asm/nb85e_intc.h>
/* For <asm/irq.h> */
#define NUM_CPU_IRQS 64
/* For <asm/page.h> */
#define PAGE_OFFSET DRAM_ADDR
/* For <asm/entry.h> */
/* `R0 RAM', used for a few miscellaneous variables that must be accessible
using a load instruction relative to R0. The sim85e2c simulator
actually puts 1020K of RAM from FFF00000 to FFFFF000, so we arbitarily
choose a small portion at the end of that. */
#define R0_RAM_ADDR 0xFFFFE000
/* For <asm/param.h> */
#ifndef HZ
#define HZ 24 /* Minimum supported frequency. */
#endif
#endif /* __V850_SIM85E2C_H__ */
/*
* include/asm-v850/simsyscall.h -- `System calls' under the v850e emulator
*
* Copyright (C) 2001 NEC Corporation
* Copyright (C) 2001 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#ifndef __V850_SIMSYSCALL_H__
#define __V850_SIMSYSCALL_H__
#define V850_SIM_SYS_exit(a...) V850_SIM_SYSCALL_1 (1 , ##a)
#define V850_SIM_SYS_fork(a...) V850_SIM_SYSCALL_0 (2 , ##a)
#define V850_SIM_SYS_read(a...) V850_SIM_SYSCALL_3 (3 , ##a)
#define V850_SIM_SYS_write(a...) V850_SIM_SYSCALL_3 (4 , ##a)
#define V850_SIM_SYS_open(a...) V850_SIM_SYSCALL_2 (5 , ##a)
#define V850_SIM_SYS_close(a...) V850_SIM_SYSCALL_1 (6 , ##a)
#define V850_SIM_SYS_wait4(a...) V850_SIM_SYSCALL_4 (7 , ##a)
/* #define V850_SIM_SYS_creat(a...) V850_SIM_SYSCALL_1 (8 , ##a) */
/* #define V850_SIM_SYS_link(a...) V850_SIM_SYSCALL_1 (9 , ##a) */
/* #define V850_SIM_SYS_unlink(a...) V850_SIM_SYSCALL_1 (10 , ##a) */
#define V850_SIM_SYS_execv(a...) V850_SIM_SYSCALL_2 (11 , ##a)
/* #define V850_SIM_SYS_chdir(a...) V850_SIM_SYSCALL_1 (12 , ##a) */
/* #define V850_SIM_SYS_mknod(a...) V850_SIM_SYSCALL_1 (14 , ##a) */
#define V850_SIM_SYS_chmod(a...) V850_SIM_SYSCALL_2 (15 , ##a)
#define V850_SIM_SYS_chown(a...) V850_SIM_SYSCALL_2 (16 , ##a)
#define V850_SIM_SYS_lseek(a...) V850_SIM_SYSCALL_3 (19 , ##a)
/* #define V850_SIM_SYS_getpid(a...) V850_SIM_SYSCALL_1 (20 , ##a) */
/* #define V850_SIM_SYS_isatty(a...) V850_SIM_SYSCALL_1 (21 , ##a) */
/* #define V850_SIM_SYS_fstat(a...) V850_SIM_SYSCALL_1 (22 , ##a) */
#define V850_SIM_SYS_time(a...) V850_SIM_SYSCALL_1 (23 , ##a)
#define V850_SIM_SYS_poll(a...) V850_SIM_SYSCALL_3 (24 , ##a)
#define V850_SIM_SYS_stat(a...) V850_SIM_SYSCALL_2 (38 , ##a)
#define V850_SIM_SYS_pipe(a...) V850_SIM_SYSCALL_1 (42 , ##a)
#define V850_SIM_SYS_times(a...) V850_SIM_SYSCALL_1 (43 , ##a)
#define V850_SIM_SYS_execve(a...) V850_SIM_SYSCALL_3 (59 , ##a)
#define V850_SIM_SYS_gettimeofday(a...) V850_SIM_SYSCALL_2 (116 , ##a)
/* #define V850_SIM_SYS_utime(a...) V850_SIM_SYSCALL_2 (201 , ##a) */
/* #define V850_SIM_SYS_wait(a...) V850_SIM_SYSCALL_1 (202 , ##a) */
#define V850_SIM_SYS_make_raw(a...) V850_SIM_SYSCALL_1 (1024 , ##a)
#define V850_SIM_SYSCALL_0(_call) \
({ \
register int call __asm__ ("r6") = _call; \
register int rval __asm__ ("r10"); \
__asm__ __volatile__ ("trap 31" \
: "=r" (rval) \
: "r" (call) \
: "r11", "memory"); \
rval; \
})
#define V850_SIM_SYSCALL_1(_call, _arg0) \
({ \
register int call __asm__ ("r6") = _call; \
register long arg0 __asm__ ("r7") = (long)_arg0; \
register int rval __asm__ ("r10"); \
__asm__ __volatile__ ("trap 31" \
: "=r" (rval) \
: "r" (call), "r" (arg0) \
: "r11", "memory"); \
rval; \
})
#define V850_SIM_SYSCALL_2(_call, _arg0, _arg1) \
({ \
register int call __asm__ ("r6") = _call; \
register long arg0 __asm__ ("r7") = (long)_arg0; \
register long arg1 __asm__ ("r8") = (long)_arg1; \
register int rval __asm__ ("r10"); \
__asm__ __volatile__ ("trap 31" \
: "=r" (rval) \
: "r" (call), "r" (arg0), "r" (arg1) \
: "r11", "memory"); \
rval; \
})
#define V850_SIM_SYSCALL_3(_call, _arg0, _arg1, _arg2) \
({ \
register int call __asm__ ("r6") = _call; \
register long arg0 __asm__ ("r7") = (long)_arg0; \
register long arg1 __asm__ ("r8") = (long)_arg1; \
register long arg2 __asm__ ("r9") = (long)_arg2; \
register int rval __asm__ ("r10"); \
__asm__ __volatile__ ("trap 31" \
: "=r" (rval) \
: "r" (call), "r" (arg0), "r" (arg1), "r" (arg2)\
: "r11", "memory"); \
rval; \
})
#define V850_SIM_SYSCALL(call, args...) \
V850_SIM_SYS_##call (args)
#endif /* __V850_SIMSYSCALL_H__ */
#ifndef __V850_SOCKET_H__
#define __V850_SOCKET_H__
#include <asm/sockios.h>
/* For setsockoptions(2) */
#define SOL_SOCKET 1
#define SO_DEBUG 1
#define SO_REUSEADDR 2
#define SO_TYPE 3
#define SO_ERROR 4
#define SO_DONTROUTE 5
#define SO_BROADCAST 6
#define SO_SNDBUF 7
#define SO_RCVBUF 8
#define SO_KEEPALIVE 9
#define SO_OOBINLINE 10
#define SO_NO_CHECK 11
#define SO_PRIORITY 12
#define SO_LINGER 13
#define SO_BSDCOMPAT 14
/* To add :#define SO_REUSEPORT 15 */
#define SO_PASSCRED 16
#define SO_PEERCRED 17
#define SO_RCVLOWAT 18
#define SO_SNDLOWAT 19
#define SO_RCVTIMEO 20
#define SO_SNDTIMEO 21
/* Security levels - as per NRL IPv6 - don't actually do anything */
#define SO_SECURITY_AUTHENTICATION 22
#define SO_SECURITY_ENCRYPTION_TRANSPORT 23
#define SO_SECURITY_ENCRYPTION_NETWORK 24
#define SO_BINDTODEVICE 25
/* Socket filtering */
#define SO_ATTACH_FILTER 26
#define SO_DETACH_FILTER 27
#define SO_PEERNAME 28
#define SO_TIMESTAMP 29
#define SCM_TIMESTAMP SO_TIMESTAMP
#define SO_ACCEPTCONN 30
/* Nast libc5 fixup - bletch */
#if defined(__KERNEL__)
/* Socket types. */
#define SOCK_STREAM 1 /* stream (connection) socket */
#define SOCK_DGRAM 2 /* datagram (conn.less) socket */
#define SOCK_RAW 3 /* raw socket */
#define SOCK_RDM 4 /* reliably-delivered message */
#define SOCK_SEQPACKET 5 /* sequential packet socket */
#define SOCK_PACKET 10 /* linux specific way of */
/* getting packets at the dev */
/* level. For writing rarp and */
/* other similar things on the */
/* user level. */
#define SOCK_MAX (SOCK_PACKET+1)
#endif
#endif /* __V850_SOCKET_H__ */
#ifndef __V850_SOCKIOS_H__
#define __V850_SOCKIOS_H__
/* Socket-level I/O control calls. */
#define FIOSETOWN 0x8901
#define SIOCSPGRP 0x8902
#define FIOGETOWN 0x8903
#define SIOCGPGRP 0x8904
#define SIOCATMARK 0x8905
#define SIOCGSTAMP 0x8906 /* Get stamp */
#endif /* __V850_SOCKIOS_H__ */
#ifndef __V850_SOFTIRQ_H__
#define __V850_SOFTIRQ_H__
#include <linux/preempt.h>
#include <asm/hardirq.h>
#define local_bh_disable() \
do { preempt_count() += SOFTIRQ_OFFSET; barrier(); } while (0)
#define __local_bh_enable() \
do { barrier(); preempt_count() -= SOFTIRQ_OFFSET; } while (0)
#define local_bh_enable() \
do { \
__local_bh_enable(); \
if (unlikely(!in_interrupt() && softirq_pending(smp_processor_id()))) \
do_softirq(); \
preempt_check_resched(); \
} while (0)
#endif /* __V850_SOFTIRQ_H__ */
#ifndef __V850_STAT_H__
#define __V850_STAT_H__
struct stat {
__kernel_dev_t st_dev;
__kernel_ino_t st_ino;
__kernel_mode_t st_mode;
__kernel_nlink_t st_nlink;
__kernel_uid_t st_uid;
__kernel_gid_t st_gid;
__kernel_dev_t st_rdev;
__kernel_off_t st_size;
unsigned long st_blksize;
unsigned long st_blocks;
unsigned long st_atime;
unsigned long __unused1;
unsigned long st_mtime;
unsigned long __unused2;
unsigned long st_ctime;
unsigned long __unused3;
unsigned long __unused4;
unsigned long __unused5;
};
struct stat64 {
__kernel_dev_t st_dev;
unsigned long __unused0;
unsigned long __unused1;
__kernel_ino64_t st_ino;
__kernel_mode_t st_mode;
__kernel_nlink_t st_nlink;
__kernel_uid_t st_uid;
__kernel_gid_t st_gid;
__kernel_dev_t st_rdev;
unsigned long __unused2;
unsigned long __unused3;
__kernel_loff_t st_size;
unsigned long st_blksize;
unsigned long st_blocks; /* No. of 512-byte blocks allocated */
unsigned long __unused4; /* future possible st_blocks high bits */
unsigned long st_atime;
unsigned long __unused5;
unsigned long st_mtime;
unsigned long __unused6;
unsigned long st_ctime;
unsigned long __unused7; /* high 32 bits of ctime someday */
unsigned long __unused8;
};
#endif /* __V850_STAT_H__ */
#ifndef __V850_STATFS_H__
#define __V850_STATFS_H__
#ifndef __KERNEL_STRICT_NAMES
#include <linux/types.h>
typedef __kernel_fsid_t fsid_t;
#endif
struct statfs {
long f_type;
long f_bsize;
long f_blocks;
long f_bfree;
long f_bavail;
long f_files;
long f_ffree;
__kernel_fsid_t f_fsid;
long f_namelen;
long f_spare[6];
};
#endif /* __V850_STATFS_H__ */
/*
* include/asm-v850/string.h -- Architecture specific string routines
*
* Copyright (C) 2001,02 NEC Corporation
* Copyright (C) 2001,02 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#ifndef __V850_STRING_H__
#define __V850_STRING_H__
#define __HAVE_ARCH_BCOPY
#define __HAVE_ARCH_MEMCPY
#define __HAVE_ARCH_MEMSET
#define __HAVE_ARCH_MEMMOVE
extern void *memcpy (void *, const void *, __kernel_size_t);
extern void bcopy (const char *, char *, int);
extern void *memset (void *, int, __kernel_size_t);
extern void *memmove (void *, const void *, __kernel_size_t);
#endif /* __V850_STRING_H__ */
/*
* include/asm-v850/system.h -- Low-level interrupt/thread ops
*
* Copyright (C) 2001,02 NEC Corporation
* Copyright (C) 2001,02 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#ifndef __V850_SYSTEM_H__
#define __V850_SYSTEM_H__
#include <linux/linkage.h>
#include <asm/ptrace.h>
#define prepare_to_switch() do { } while (0)
/*
* switch_to(n) should switch tasks to task ptr, first checking that
* ptr isn't the current task, in which case it does nothing.
*/
struct thread_struct;
extern void *switch_thread (struct thread_struct *last,
struct thread_struct *next);
#define switch_to(prev,next,last) \
do { \
if (prev != next) { \
(last) = switch_thread (&prev->thread, &next->thread); \
} \
} while (0)
/* Enable/disable interrupts. */
#define local_irq_enable() __asm__ __volatile__ ("ei")
#define local_irq_disable() __asm__ __volatile__ ("di")
#define local_save_flags(flags) \
__asm__ __volatile__ ("stsr %1, %0" : "=r" (flags) : "i" (SR_PSW))
#define local_restore_flags(flags) \
__asm__ __volatile__ ("ldsr %0, %1" :: "r" (flags), "i" (SR_PSW))
/* For spinlocks etc */
#define local_irq_save(flags) \
do { local_save_flags (flags); local_irq_disable (); } while (0)
#define local_irq_restore(flags) \
local_restore_flags (flags);
static inline int irqs_disabled (void)
{
unsigned flags;
local_save_flags (flags);
return !!(flags & 0x20);
}
/*
* Force strict CPU ordering.
* Not really required on v850...
*/
#define nop() __asm__ __volatile__ ("nop")
#define mb() __asm__ __volatile__ ("" ::: "memory")
#define rmb() mb ()
#define wmb() mb ()
#define set_rmb(var, value) do { xchg (&var, value); } while (0)
#define set_mb(var, value) set_rmb (var, value)
#define set_wmb(var, value) do { var = value; wmb (); } while (0)
#ifdef CONFIG_SMP
#define smp_mb() mb ()
#define smp_rmb() rmb ()
#define smp_wmb() wmb ()
#else
#define smp_mb() barrier ()
#define smp_rmb() barrier ()
#define smp_wmb() barrier ()
#endif
#define xchg(ptr, with) \
((__typeof__ (*(ptr)))__xchg ((unsigned long)(with), (ptr), sizeof (*(ptr))))
#define tas(ptr) (xchg ((ptr), 1))
extern inline unsigned long __xchg (unsigned long with,
__volatile__ void *ptr, int size)
{
unsigned long tmp, flags;
local_irq_save (flags);
switch (size) {
case 1:
tmp = *(unsigned char *)ptr;
*(unsigned char *)ptr = with;
break;
case 2:
tmp = *(unsigned short *)ptr;
*(unsigned short *)ptr = with;
break;
case 4:
tmp = *(unsigned long *)ptr;
*(unsigned long *)ptr = with;
break;
}
local_irq_restore (flags);
return tmp;
}
#endif /* __V850_SYSTEM_H__ */
/*
* include/asm-v850/nb85e_teg.h -- NB85E-TEG cpu chip
*
* Copyright (C) 2001,02 NEC Corporation
* Copyright (C) 2001,02 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#ifndef __V850_NB85E_TEG_H__
#define __V850_NB85E_TEG_H__
/* The NB85E_TEG uses the NB85E cpu core. */
#include <asm/nb85e.h>
#define CHIP "v850e/nb85e-teg"
#define CHIP_LONG "NEC V850E/NB85E TEG"
/* Hardware-specific interrupt numbers (in the kernel IRQ namespace). */
#define IRQ_INTOV(n) (n) /* 0-3 */
#define IRQ_INTOV_NUM 4
#define IRQ_INTCMD(n) (0x1c + (n)) /* interval timer interrupts 0-3 */
#define IRQ_INTCMD_NUM 4
#define IRQ_INTDMA(n) (0x20 + (n)) /* DMA interrupts 0-3 */
#define IRQ_INTDMA_NUM 4
#define IRQ_INTCSI(n) (0x24 + (n)) /* CSI 0-2 transmit/receive completion */
#define IRQ_INTCSI_NUM 3
#define IRQ_INTSER(n) (0x25 + (n)) /* UART 0-2 reception error */
#define IRQ_INTSER_NUM 3
#define IRQ_INTSR(n) (0x26 + (n)) /* UART 0-2 reception completion */
#define IRQ_INTSR_NUM 3
#define IRQ_INTST(n) (0x27 + (n)) /* UART 0-2 transmission completion */
#define IRQ_INTST_NUM 3
/* For <asm/irq.h> */
#define NUM_MACH_IRQS 0x30
/* TEG UART details. */
#define NB85E_UART_BASE_ADDR(n) (0xFFFFF600 + 0x10 * (n))
#define NB85E_UART_ASIM_ADDR(n) (NB85E_UART_BASE_ADDR(n) + 0x0)
#define NB85E_UART_ASIS_ADDR(n) (NB85E_UART_BASE_ADDR(n) + 0x2)
#define NB85E_UART_ASIF_ADDR(n) (NB85E_UART_BASE_ADDR(n) + 0x4)
#define NB85E_UART_CKSR_ADDR(n) (NB85E_UART_BASE_ADDR(n) + 0x6)
#define NB85E_UART_BRGC_ADDR(n) (NB85E_UART_BASE_ADDR(n) + 0x8)
#define NB85E_UART_TXB_ADDR(n) (NB85E_UART_BASE_ADDR(n) + 0xA)
#define NB85E_UART_RXB_ADDR(n) (NB85E_UART_BASE_ADDR(n) + 0xC)
#define NB85E_UART_NUM_CHANNELS 1
#define NB85E_UART_BASE_FREQ CPU_CLOCK_FREQ
/* The TEG RTPU. */
#define NB85E_RTPU_BASE_ADDR 0xFFFFF210
#endif /* __V850_NB85E_TEG_H__ */
#ifndef __V850_TERMBITS_H__
#define __V850_TERMBITS_H__
#include <linux/posix_types.h>
typedef unsigned char cc_t;
typedef unsigned int speed_t;
typedef unsigned int tcflag_t;
#define NCCS 19
struct termios {
tcflag_t c_iflag; /* input mode flags */
tcflag_t c_oflag; /* output mode flags */
tcflag_t c_cflag; /* control mode flags */
tcflag_t c_lflag; /* local mode flags */
cc_t c_line; /* line discipline */
cc_t c_cc[NCCS]; /* control characters */
};
/* c_cc characters */
#define VINTR 0
#define VQUIT 1
#define VERASE 2
#define VKILL 3
#define VEOF 4
#define VTIME 5
#define VMIN 6
#define VSWTC 7
#define VSTART 8
#define VSTOP 9
#define VSUSP 10
#define VEOL 11
#define VREPRINT 12
#define VDISCARD 13
#define VWERASE 14
#define VLNEXT 15
#define VEOL2 16
/* c_iflag bits */
#define IGNBRK 0000001
#define BRKINT 0000002
#define IGNPAR 0000004
#define PARMRK 0000010
#define INPCK 0000020
#define ISTRIP 0000040
#define INLCR 0000100
#define IGNCR 0000200
#define ICRNL 0000400
#define IUCLC 0001000
#define IXON 0002000
#define IXANY 0004000
#define IXOFF 0010000
#define IMAXBEL 0020000
/* c_oflag bits */
#define OPOST 0000001
#define OLCUC 0000002
#define ONLCR 0000004
#define OCRNL 0000010
#define ONOCR 0000020
#define ONLRET 0000040
#define OFILL 0000100
#define OFDEL 0000200
#define NLDLY 0000400
#define NL0 0000000
#define NL1 0000400
#define CRDLY 0003000
#define CR0 0000000
#define CR1 0001000
#define CR2 0002000
#define CR3 0003000
#define TABDLY 0014000
#define TAB0 0000000
#define TAB1 0004000
#define TAB2 0010000
#define TAB3 0014000
#define XTABS 0014000
#define BSDLY 0020000
#define BS0 0000000
#define BS1 0020000
#define VTDLY 0040000
#define VT0 0000000
#define VT1 0040000
#define FFDLY 0100000
#define FF0 0000000
#define FF1 0100000
/* c_cflag bit meaning */
#define CBAUD 0010017
#define B0 0000000 /* hang up */
#define B50 0000001
#define B75 0000002
#define B110 0000003
#define B134 0000004
#define B150 0000005
#define B200 0000006
#define B300 0000007
#define B600 0000010
#define B1200 0000011
#define B1800 0000012
#define B2400 0000013
#define B4800 0000014
#define B9600 0000015
#define B19200 0000016
#define B38400 0000017
#define EXTA B19200
#define EXTB B38400
#define CSIZE 0000060
#define CS5 0000000
#define CS6 0000020
#define CS7 0000040
#define CS8 0000060
#define CSTOPB 0000100
#define CREAD 0000200
#define PARENB 0000400
#define PARODD 0001000
#define HUPCL 0002000
#define CLOCAL 0004000
#define CBAUDEX 0010000
#define B57600 0010001
#define B115200 0010002
#define B230400 0010003
#define B460800 0010004
#define B500000 0010005
#define B576000 0010006
#define B921600 0010007
#define B1000000 0010010
#define B1152000 0010011
#define B1500000 0010012
#define B2000000 0010013
#define B2500000 0010014
#define B3000000 0010015
#define B3500000 0010016
#define B4000000 0010017
#define CIBAUD 002003600000 /* input baud rate (not used) */
#define CMSPAR 010000000000 /* mark or space (stick) parity */
#define CRTSCTS 020000000000 /* flow control */
/* c_lflag bits */
#define ISIG 0000001
#define ICANON 0000002
#define XCASE 0000004
#define ECHO 0000010
#define ECHOE 0000020
#define ECHOK 0000040
#define ECHONL 0000100
#define NOFLSH 0000200
#define TOSTOP 0000400
#define ECHOCTL 0001000
#define ECHOPRT 0002000
#define ECHOKE 0004000
#define FLUSHO 0010000
#define PENDIN 0040000
#define IEXTEN 0100000
/* tcflow() and TCXONC use these */
#define TCOOFF 0
#define TCOON 1
#define TCIOFF 2
#define TCION 3
/* tcflush() and TCFLSH use these */
#define TCIFLUSH 0
#define TCOFLUSH 1
#define TCIOFLUSH 2
/* tcsetattr uses these */
#define TCSANOW 0
#define TCSADRAIN 1
#define TCSAFLUSH 2
#endif /* __V850_TERMBITS_H__ */
#ifndef __V850_TERMIOS_H__
#define __V850_TERMIOS_H__
#include <asm/termbits.h>
#include <asm/ioctls.h>
struct winsize {
unsigned short ws_row;
unsigned short ws_col;
unsigned short ws_xpixel;
unsigned short ws_ypixel;
};
#define NCC 8
struct termio {
unsigned short c_iflag; /* input mode flags */
unsigned short c_oflag; /* output mode flags */
unsigned short c_cflag; /* control mode flags */
unsigned short c_lflag; /* local mode flags */
unsigned char c_line; /* line discipline */
unsigned char c_cc[NCC]; /* control characters */
};
/* modem lines */
#define TIOCM_LE 0x001
#define TIOCM_DTR 0x002
#define TIOCM_RTS 0x004
#define TIOCM_ST 0x008
#define TIOCM_SR 0x010
#define TIOCM_CTS 0x020
#define TIOCM_CAR 0x040
#define TIOCM_RNG 0x080
#define TIOCM_DSR 0x100
#define TIOCM_CD TIOCM_CAR
#define TIOCM_RI TIOCM_RNG
#define TIOCM_OUT1 0x2000
#define TIOCM_OUT2 0x4000
#define TIOCM_LOOP 0x8000
/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
/* line disciplines */
#define N_TTY 0
#define N_SLIP 1
#define N_MOUSE 2
#define N_PPP 3
#define N_STRIP 4
#define N_AX25 5
#define N_X25 6 /* X.25 async */
#define N_6PACK 7
#define N_MASC 8 /* Reserved for Mobitex module <kaz@cafe.net> */
#define N_R3964 9 /* Reserved for Simatic R3964 module */
#define N_PROFIBUS_FDL 10 /* Reserved for Profibus <Dave@mvhi.com> */
#define N_IRDA 11 /* Linux IR - http://irda.sourceforge.net/ */
#define N_SMSBLOCK 12 /* SMS block mode - for talking to GSM data cards about SMS messages */
#define N_HDLC 13 /* synchronous HDLC */
#define N_SYNC_PPP 14 /* synchronous PPP */
#define N_HCI 15 /* Bluetooth HCI UART */
#ifdef __KERNEL__
/* intr=^C quit=^\ erase=del kill=^U
eof=^D vtime=\0 vmin=\1 sxtc=\0
start=^Q stop=^S susp=^Z eol=\0
reprint=^R discard=^U werase=^W lnext=^V
eol2=\0
*/
#define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0"
/*
* Translate a "termio" structure into a "termios". Ugh.
*/
#define SET_LOW_TERMIOS_BITS(termios, termio, x) { \
unsigned short __tmp; \
get_user(__tmp,&(termio)->x); \
*(unsigned short *) &(termios)->x = __tmp; \
}
#define user_termio_to_kernel_termios(termios, termio) \
({ \
SET_LOW_TERMIOS_BITS(termios, termio, c_iflag); \
SET_LOW_TERMIOS_BITS(termios, termio, c_oflag); \
SET_LOW_TERMIOS_BITS(termios, termio, c_cflag); \
SET_LOW_TERMIOS_BITS(termios, termio, c_lflag); \
copy_from_user((termios)->c_cc, (termio)->c_cc, NCC); \
})
/*
* Translate a "termios" structure into a "termio". Ugh.
*/
#define kernel_termios_to_user_termio(termio, termios) \
({ \
put_user((termios)->c_iflag, &(termio)->c_iflag); \
put_user((termios)->c_oflag, &(termio)->c_oflag); \
put_user((termios)->c_cflag, &(termio)->c_cflag); \
put_user((termios)->c_lflag, &(termio)->c_lflag); \
put_user((termios)->c_line, &(termio)->c_line); \
copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \
})
#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios))
#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios))
#endif /* __KERNEL__ */
#endif /* __V850_TERMIOS_H__ */
/*
* include/asm-v850/thread_info.h -- v850 low-level thread information
*
* Copyright (C) 2002 NEC Corporation
* Copyright (C) 2002 Miles Bader <miles@gnu.org>
* Copyright (C) 2002 David Howells (dhowells@redhat.com)
* - Incorporating suggestions made by Linus Torvalds and Dave Miller
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* This file was derived from the PPC version, include/asm-ppc/thread_info.h
* which was adapted from the i386 version by Paul Mackerras
*/
#ifndef __V850_THREAD_INFO_H__
#define __V850_THREAD_INFO_H__
#ifdef __KERNEL__
#ifndef __ASSEMBLY__
/*
* low level task data.
* If you change this, change the TI_* offsets below to match.
*/
struct thread_info {
struct task_struct *task; /* main task structure */
struct exec_domain *exec_domain; /* execution domain */
unsigned long flags; /* low level flags */
int cpu; /* cpu we're on */
int preempt_count;
};
#define INIT_THREAD_INFO(tsk) \
{ \
.task = &tsk, \
.exec_domain = &default_exec_domain, \
.flags = 0, \
.cpu = 0, \
.preempt_count = 1 \
}
#define init_thread_info (init_thread_union.thread_info)
#define init_stack (init_thread_union.stack)
/*
* macros/functions for gaining access to the thread information structure
*/
/* thread information allocation */
#define alloc_thread_info() ((struct thread_info *) \
__get_free_pages(GFP_KERNEL, 1))
#define free_thread_info(ti) free_pages((unsigned long) (ti), 1)
#define get_thread_info(ti) get_task_struct((ti)->task)
#define put_thread_info(ti) put_task_struct((ti)->task)
#endif /* __ASSEMBLY__ */
/*
* Offsets in thread_info structure, used in assembly code
*/
#define TI_TASK 0
#define TI_EXECDOMAIN 4
#define TI_FLAGS 8
#define TI_CPU 12
#define TI_PREEMPT 16
#define TI_SOFTIRQ 20
#define TI_HARDIRQ 24
#define PREEMPT_ACTIVE 0x4000000
/*
* thread information flag bit numbers
*/
#define TIF_SYSCALL_TRACE 0 /* syscall trace active */
#define TIF_NOTIFY_RESUME 1 /* resumption notification requested */
#define TIF_SIGPENDING 2 /* signal pending */
#define TIF_NEED_RESCHED 3 /* rescheduling necessary */
#define TIF_POLLING_NRFLAG 4 /* true if poll_idle() is polling
TIF_NEED_RESCHED */
/* as above, but as bit values */
#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME)
#define _TIF_SIGPENDING (1<<TIF_SIGPENDING)
#define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED)
#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
/* Size of kernel stack for each process. */
#define THREAD_SIZE 0x2000
/* The alignment of kernel threads, with thread_info structures at their
base. Thus, a pointer for a task's task structure can be derived from
its kernel stack pointer. */
#define THREAD_ALIGNMENT THREAD_SIZE
#define THREAD_MASK (-THREAD_ALIGNMENT)
#ifdef __ASSEMBLY__
/* Put a pointer to the current thread_info structure into REG. Note that
this definition requires THREAD_MASK to be representable as a signed
16-bit value. */
#define GET_CURRENT_THREAD(reg) \
/* Use `addi' and then `and' instead of just `andi', because \
`addi' sign-extends the immediate value, whereas `andi' \
zero-extends it. */ \
addi THREAD_MASK, r0, reg; \
and sp, reg
#else
/* Return a pointer to the current thread_info structure. */
static inline struct thread_info *current_thread_info (void)
{
register unsigned long sp __asm__ ("sp");
return (struct thread_info *)(sp & THREAD_MASK);
}
#endif /* __ASSEMBLY__ */
#endif /* __KERNEL__ */
#endif /* __V850_THREAD_INFO_H__ */
/*
* linux/include/asm-v850/timex.h
*
* v850 architecture timex specifications
*/
#ifndef __V850_TIMEX_H__
#define __V850_TIMEX_H__
#define CLOCK_TICK_RATE 1193180 /* Underlying HZ */
#define CLOCK_TICK_FACTOR 20 /* Factor of both 1000000 and CLOCK_TICK_RATE */
#define FINETUNE ((((((long)LATCH * HZ - CLOCK_TICK_RATE) << SHIFT_HZ) * \
(1000000/CLOCK_TICK_FACTOR) / (CLOCK_TICK_RATE/CLOCK_TICK_FACTOR)) \
<< (SHIFT_SCALE-SHIFT_HZ)) / HZ)
typedef unsigned long cycles_t;
static inline cycles_t get_cycles(void)
{
return 0;
}
#endif /* __V850_TIMEX_H__ */
/*
* include/asm-v850/tlb.h
*
* Copyright (C) 2002 NEC Corporation
* Copyright (C) 2002 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#ifndef __V850_TLB_H__
#define __V850_TLB_H__
#define tlb_flush(tlb) ((void)0)
#include <asm-generic/tlb.h>
#endif /* __V850_TLB_H__ */
/*
* include/asm-v850/tlbflush.h
*
* Copyright (C) 2001,02 NEC Corporation
* Copyright (C) 2001,02 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#ifndef __V850_TLBFLUSH_H__
#define __V850_TLBFLUSH_H__
#include <asm/setup.h>
#include <asm/machdep.h>
/*
* flush all user-space atc entries.
*/
static inline void __flush_tlb(void)
{
BUG ();
}
static inline void __flush_tlb_one(unsigned long addr)
{
BUG ();
}
#define flush_tlb() __flush_tlb()
/*
* flush all atc entries (both kernel and user-space entries).
*/
static inline void flush_tlb_all(void)
{
BUG ();
}
static inline void flush_tlb_mm(struct mm_struct *mm)
{
BUG ();
}
static inline void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr)
{
BUG ();
}
static inline void flush_tlb_range(struct vm_area_struct *vma,
unsigned long start, unsigned long end)
{
BUG ();
}
extern inline void flush_tlb_kernel_page(unsigned long addr)
{
BUG ();
}
extern inline void flush_tlb_pgtables(struct mm_struct *mm,
unsigned long start, unsigned long end)
{
BUG ();
}
#endif /* __V850_TLBFLUSH_H__ */
#ifndef __V850_TOPOLOGY_H__
#define __V850_TOPOLOGY_H__
#include <asm-generic/topology.h>
#endif /* __V850_TOPOLOGY_H__ */
#ifndef __V850_TYPES_H__
#define __V850_TYPES_H__
#ifndef __ASSEMBLY__
/*
* This file is never included by application software unless
* explicitly requested (e.g., via linux/types.h) in which case the
* application is Linux specific so (user-) name space pollution is
* not a major issue. However, for interoperability, libraries still
* need to be careful to avoid a name clashes.
*/
typedef unsigned short umode_t;
/*
* __xx is ok: it doesn't pollute the POSIX namespace. Use these in the
* header files exported to user space
*/
typedef __signed__ char __s8;
typedef unsigned char __u8;
typedef __signed__ short __s16;
typedef unsigned short __u16;
typedef __signed__ int __s32;
typedef unsigned int __u32;
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
typedef __signed__ long long __s64;
typedef unsigned long long __u64;
#endif
/*
* These aren't exported outside the kernel to avoid name space clashes
*/
#ifdef __KERNEL__
typedef signed char s8;
typedef unsigned char u8;
typedef signed short s16;
typedef unsigned short u16;
typedef signed int s32;
typedef unsigned int u32;
typedef signed long long s64;
typedef unsigned long long u64;
#define BITS_PER_LONG 32
/* Dma addresses are 32-bits wide. */
typedef u32 dma_addr_t;
#endif /* __KERNEL__ */
#endif /* !__ASSEMBLY__ */
#endif /* __V850_TYPES_H__ */
#ifndef __V850_UACCESS_H__
#define __V850_UACCESS_H__
/*
* User space memory access functions
*/
#include <linux/sched.h>
#include <asm/segment.h>
#include <asm/machdep.h>
#define VERIFY_READ 0
#define VERIFY_WRITE 1
extern inline int access_ok (int type, const void *addr, unsigned long size)
{
/* XXX I guess we should check against real ram bounds at least, and
possibly make sure ADDR is not within the kernel.
For now we just check to make sure it's not a small positive
or negative value, as that will at least catch some kinds of
error. In particular, we make sure that ADDR's not within the
interrupt vector area, which we know starts at zero, or within the
peripheral-I/O area, which is located just _before_ zero. */
unsigned long val = (unsigned long)addr;
return val >= (0x80 + NUM_CPU_IRQS*16) && val < 0xFFFFF000;
}
extern inline int verify_area (int type, const void *addr, unsigned long size)
{
return access_ok (type, addr, size) ? 0 : -EFAULT;
}
/*
* The exception table consists of pairs of addresses: the first is the
* address of an instruction that is allowed to fault, and the second is
* the address at which the program should continue. No registers are
* modified, so it is entirely up to the continuation code to figure out
* what to do.
*
* All the routines below use bits of fixup code that are out of line
* with the main instruction path. This means when everything is well,
* we don't even have to jump over them. Further, they do not intrude
* on our cache or tlb entries.
*/
struct exception_table_entry
{
unsigned long insn, fixup;
};
/* Returns 0 if exception not found and fixup otherwise. */
extern unsigned long search_exception_table (unsigned long);
/*
* These are the main single-value transfer routines. They automatically
* use the right size if we just have the right pointer type.
*/
extern int bad_user_access_length (void);
#define __get_user(var, ptr) \
({ \
int __gu_err = 0; \
typeof(*(ptr)) __gu_val = 0; \
switch (sizeof (*(ptr))) { \
case 1: \
case 2: \
case 4: \
__gu_val = *(ptr); \
break; \
case 8: \
memcpy(&__gu_val, ptr, sizeof(__gu_val)); \
break; \
default: \
__gu_val = 0; \
__gu_err = __get_user_bad (); \
break; \
} \
(var) = __gu_val; \
__gu_err; \
})
#define __get_user_bad() (bad_user_access_length (), (-EFAULT))
#define __put_user(var, ptr) \
({ \
int __pu_err = 0; \
switch (sizeof (*(ptr))) { \
case 1: \
case 2: \
case 4: \
*(ptr) = (var); \
break; \
case 8: { \
typeof(*(ptr)) __pu_val = 0; \
memcpy(ptr, &__pu_val, sizeof(__pu_val)); \
} \
break; \
default: \
__pu_err = __put_user_bad (); \
break; \
} \
__pu_err; \
})
#define __put_user_bad() (bad_user_access_length (), (-EFAULT))
#define put_user(x, ptr) __put_user(x, ptr)
#define get_user(x, ptr) __get_user(x, ptr)
#define __copy_from_user(to, from, n) (memcpy (to, from, n), 0)
#define __copy_to_user(to, from, n) (memcpy(to, from, n), 0)
#define copy_from_user(to, from, n) __copy_from_user (to, from, n)
#define copy_to_user(to, from, n) __copy_to_user(to, from, n)
#define copy_to_user_ret(to,from,n,retval) \
({ if (copy_to_user (to,from,n)) return retval; })
#define copy_from_user_ret(to,from,n,retval) \
({ if (copy_from_user (to,from,n)) return retval; })
/*
* Copy a null terminated string from userspace.
*/
static inline long
strncpy_from_user (char *dst, const char *src, long count)
{
char *tmp;
strncpy (dst, src, count);
for (tmp = dst; *tmp && count > 0; tmp++, count--)
;
return tmp - dst;
}
/*
* Return the size of a string (including the ending 0)
*
* Return 0 on exception, a value greater than N if too long
*/
static inline long strnlen_user (const char *src, long n)
{
return strlen (src) + 1;
}
#define strlen_user(str) strnlen_user (str, 32767)
/*
* Zero Userspace
*/
static inline unsigned long
clear_user (void *to, unsigned long n)
{
memset (to, 0, n);
return 0;
}
#endif /* __V850_UACCESS_H__ */
#ifndef __V850_UCONTEXT_H__
#define __V850_UCONTEXT_H__
#include <asm/sigcontext.h>
struct ucontext {
unsigned long uc_flags;
struct ucontext *uc_link;
stack_t uc_stack;
struct sigcontext uc_mcontext;
sigset_t uc_sigmask; /* mask last for extensibility */
};
#endif /* __V850_UCONTEXT_H__ */
/*
* include/asm-v850/unaligned.h -- Unaligned memory access
*
* Copyright (C) 2001 NEC Corporation
* Copyright (C) 2001 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* This file is a copy of the arm version, include/asm-arm/unaligned.h
*
* Note that some v850 chips support unaligned access, but it seems too
* annoying to use.
*/
#ifndef __V850_UNALIGNED_H__
#define __V850_UNALIGNED_H__
#include <asm/types.h>
extern int __bug_unaligned_x(void *ptr);
/*
* What is the most efficient way of loading/storing an unaligned value?
*
* That is the subject of this file. Efficiency here is defined as
* minimum code size with minimum register usage for the common cases.
* It is currently not believed that long longs are common, so we
* trade efficiency for the chars, shorts and longs against the long
* longs.
*
* Current stats with gcc 2.7.2.2 for these functions:
*
* ptrsize get: code regs put: code regs
* 1 1 1 1 2
* 2 3 2 3 2
* 4 7 3 7 3
* 8 20 6 16 6
*
* gcc 2.95.1 seems to code differently:
*
* ptrsize get: code regs put: code regs
* 1 1 1 1 2
* 2 3 2 3 2
* 4 7 4 7 4
* 8 19 8 15 6
*
* which may or may not be more efficient (depending upon whether
* you can afford the extra registers). Hopefully the gcc 2.95
* is inteligent enough to decide if it is better to use the
* extra register, but evidence so far seems to suggest otherwise.
*
* Unfortunately, gcc is not able to optimise the high word
* out of long long >> 32, or the low word from long long << 32
*/
#define __get_unaligned_2(__p) \
(__p[0] | __p[1] << 8)
#define __get_unaligned_4(__p) \
(__p[0] | __p[1] << 8 | __p[2] << 16 | __p[3] << 24)
#define get_unaligned(ptr) \
({ \
__typeof__(*(ptr)) __v; \
__u8 *__p = (__u8 *)(ptr); \
switch (sizeof(*(ptr))) { \
case 1: __v = *(ptr); break; \
case 2: __v = __get_unaligned_2(__p); break; \
case 4: __v = __get_unaligned_4(__p); break; \
case 8: { \
unsigned int __v1, __v2; \
__v2 = __get_unaligned_4((__p+4)); \
__v1 = __get_unaligned_4(__p); \
__v = ((unsigned long long)__v2 << 32 | __v1); \
} \
break; \
default: __v = __bug_unaligned_x(__p); break; \
} \
__v; \
})
extern inline void __put_unaligned_2(__u32 __v, register __u8 *__p)
{
*__p++ = __v;
*__p++ = __v >> 8;
}
extern inline void __put_unaligned_4(__u32 __v, register __u8 *__p)
{
__put_unaligned_2(__v >> 16, __p + 2);
__put_unaligned_2(__v, __p);
}
extern inline void __put_unaligned_8(const unsigned long long __v, register __u8 *__p)
{
/*
* tradeoff: 8 bytes of stack for all unaligned puts (2
* instructions), or an extra register in the long long
* case - go for the extra register.
*/
__put_unaligned_4(__v >> 32, __p+4);
__put_unaligned_4(__v, __p);
}
/*
* Try to store an unaligned value as efficiently as possible.
*/
#define put_unaligned(val,ptr) \
({ \
switch (sizeof(*(ptr))) { \
case 1: \
*(ptr) = (val); \
break; \
case 2: __put_unaligned_2((val),(__u8 *)(ptr)); \
break; \
case 4: __put_unaligned_4((val),(__u8 *)(ptr)); \
break; \
case 8: __put_unaligned_8((val),(__u8 *)(ptr)); \
break; \
default: __bug_unaligned_x(ptr); \
break; \
} \
(void) 0; \
})
#endif /* __V850_UNALIGNED_H__ */
/*
* include/asm-v850/unistd.h -- System call numbers and invocation mechanism
*
* Copyright (C) 2001,02 NEC Corporation
* Copyright (C) 2001,02 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#ifndef __V850_UNISTD_H__
#define __V850_UNISTD_H__
#include <asm/clinkage.h>
#define __NR_exit 1
#define __NR_fork 2
#define __NR_read 3
#define __NR_write 4
#define __NR_open 5
#define __NR_close 6
#define __NR_waitpid 7
#define __NR_creat 8
#define __NR_link 9
#define __NR_unlink 10
#define __NR_execve 11
#define __NR_chdir 12
#define __NR_time 13
#define __NR_mknod 14
#define __NR_chmod 15
#define __NR_chown 16
#define __NR_break 17
#define __NR_lseek 19
#define __NR_getpid 20
#define __NR_mount 21
#define __NR_umount 22
#define __NR_setuid 23
#define __NR_getuid 24
#define __NR_stime 25
#define __NR_ptrace 26
#define __NR_alarm 27
#define __NR_pause 29
#define __NR_utime 30
#define __NR_stty 31
#define __NR_gtty 32
#define __NR_access 33
#define __NR_nice 34
#define __NR_ftime 35
#define __NR_sync 36
#define __NR_kill 37
#define __NR_rename 38
#define __NR_mkdir 39
#define __NR_rmdir 40
#define __NR_dup 41
#define __NR_pipe 42
#define __NR_times 43
#define __NR_prof 44
#define __NR_brk 45
#define __NR_setgid 46
#define __NR_getgid 47
#define __NR_signal 48
#define __NR_geteuid 49
#define __NR_getegid 50
#define __NR_acct 51
#define __NR_umount2 52
#define __NR_lock 53
#define __NR_ioctl 54
#define __NR_fcntl 55
#define __NR_setpgid 57
#define __NR_umask 60
#define __NR_chroot 61
#define __NR_ustat 62
#define __NR_dup2 63
#define __NR_getppid 64
#define __NR_getpgrp 65
#define __NR_setsid 66
#define __NR_sigaction 67
#define __NR_sgetmask 68
#define __NR_ssetmask 69
#define __NR_setreuid 70
#define __NR_setregid 71
#define __NR_sigsuspend 72
#define __NR_sigpending 73
#define __NR_sethostname 74
#define __NR_setrlimit 75
#define __NR_ugetrlimit 76
#define __NR_getrusage 77
#define __NR_gettimeofday 78
#define __NR_settimeofday 79
#define __NR_getgroups 80
#define __NR_setgroups 81
#define __NR_select 82
#define __NR_symlink 83
#define __NR_readlink 85
#define __NR_uselib 86
#define __NR_swapon 87
#define __NR_reboot 88
#define __NR_readdir 89
#define __NR_mmap 90
#define __NR_munmap 91
#define __NR_truncate 92
#define __NR_ftruncate 93
#define __NR_fchmod 94
#define __NR_fchown 95
#define __NR_getpriority 96
#define __NR_setpriority 97
#define __NR_profil 98
#define __NR_statfs 99
#define __NR_fstatfs 100
#define __NR_socketcall 102
#define __NR_syslog 103
#define __NR_setitimer 104
#define __NR_getitimer 105
#define __NR_stat 106
#define __NR_lstat 107
#define __NR_fstat 108
#define __NR_vhangup 111
#define __NR_wait4 114
#define __NR_swapoff 115
#define __NR_sysinfo 116
#define __NR_ipc 117
#define __NR_fsync 118
#define __NR_sigreturn 119
#define __NR_clone 120
#define __NR_setdomainname 121
#define __NR_uname 122
#define __NR_cacheflush 123
#define __NR_adjtimex 124
#define __NR_mprotect 125
#define __NR_sigprocmask 126
#define __NR_create_module 127
#define __NR_init_module 128
#define __NR_delete_module 129
#define __NR_get_kernel_syms 130
#define __NR_quotactl 131
#define __NR_getpgid 132
#define __NR_fchdir 133
#define __NR_bdflush 134
#define __NR_sysfs 135
#define __NR_personality 136
#define __NR_afs_syscall 137 /* Syscall for Andrew File System */
#define __NR_setfsuid 138
#define __NR_setfsgid 139
#define __NR__llseek 140
#define __NR_getdents 141
#define __NR_flock 143
#define __NR_msync 144
#define __NR_readv 145
#define __NR_writev 146
#define __NR_getsid 147
#define __NR_fdatasync 148
#define __NR__sysctl 149
#define __NR_mlock 150
#define __NR_munlock 151
#define __NR_mlockall 152
#define __NR_munlockall 153
#define __NR_sched_setparam 154
#define __NR_sched_getparam 155
#define __NR_sched_setscheduler 156
#define __NR_sched_getscheduler 157
#define __NR_sched_yield 158
#define __NR_sched_get_priority_max 159
#define __NR_sched_get_priority_min 160
#define __NR_sched_rr_get_interval 161
#define __NR_nanosleep 162
#define __NR_mremap 163
#define __NR_setresuid 164
#define __NR_getresuid 165
#define __NR_query_module 167
#define __NR_poll 168
#define __NR_nfsservctl 169
#define __NR_setresgid 170
#define __NR_getresgid 171
#define __NR_prctl 172
#define __NR_rt_sigreturn 173
#define __NR_rt_sigaction 174
#define __NR_rt_sigprocmask 175
#define __NR_rt_sigpending 176
#define __NR_rt_sigtimedwait 177
#define __NR_rt_sigqueueinfo 178
#define __NR_rt_sigsuspend 179
#define __NR_pread 180
#define __NR_pwrite 181
#define __NR_lchown 182
#define __NR_getcwd 183
#define __NR_capget 184
#define __NR_capset 185
#define __NR_sigaltstack 186
#define __NR_sendfile 187
#define __NR_getpmsg 188 /* some people actually want streams */
#define __NR_putpmsg 189 /* some people actually want streams */
#define __NR_vfork 190
#define __NR_mmap2 192
#define __NR_truncate64 193
#define __NR_ftruncate64 194
#define __NR_stat64 195
#define __NR_lstat64 196
#define __NR_fstat64 197
#define __NR_fcntl64 198
#define __NR_getdents64 199
#define __NR_pivot_root 200
#define __NR_gettid 201
#define __NR_tkill 202
/* #define __NR_mincore 203 */
/* #define __NR_madvise 204 */
/* Syscall protocol:
Syscall number in r12, args in r6-r9, r13-r14
Return value in r10
Trap 0 for `short' syscalls, where all the args can fit in function
call argument registers, and trap 1 when there are additional args in
r13-r14. */
#define SYSCALL_NUM "r12"
#define SYSCALL_ARG0 "r6"
#define SYSCALL_ARG1 "r7"
#define SYSCALL_ARG2 "r8"
#define SYSCALL_ARG3 "r9"
#define SYSCALL_ARG4 "r13"
#define SYSCALL_ARG5 "r14"
#define SYSCALL_RET "r10"
#define SYSCALL_SHORT_TRAP "0"
#define SYSCALL_LONG_TRAP "1"
/* Registers clobbered by any syscall. This _doesn't_ include the syscall
number (r12) or the `extended arg' registers (r13, r14), even though
they are actually clobbered too (this is because gcc's `asm' statement
doesn't allow a clobber to be used as an input or output). */
#define SYSCALL_CLOBBERS "r1", "r5", "r11", "r15", "r16", \
"r17", "r18", "r19"
/* Registers clobbered by a `short' syscall. This includes all clobbers
except the syscall number (r12). */
#define SYSCALL_SHORT_CLOBBERS SYSCALL_CLOBBERS, "r13", "r14"
#define __syscall_return(type, res) \
do { \
/* user-visible error numbers are in the range -1 - -124: \
see <asm-v850/errno.h> */ \
if ((unsigned long)(res) >= (unsigned long)(-125)) { \
errno = -(res); \
res = -1; \
} \
return (type) (res); \
} while (0)
#define _syscall0(type, name) \
type name (void) \
{ \
register unsigned long __syscall __asm__ (SYSCALL_NUM) = __NR_##name; \
register unsigned long __ret __asm__ (SYSCALL_RET); \
__asm__ __volatile__ ("trap " SYSCALL_SHORT_TRAP \
: "=r" (__ret), "=r" (__syscall) \
: "1" (__syscall) \
: SYSCALL_SHORT_CLOBBERS); \
__syscall_return (type, __ret); \
}
#define _syscall1(type, name, atype, a) \
type name (atype a) \
{ \
register atype __a __asm__ (SYSCALL_ARG0) = a; \
register unsigned long __syscall __asm__ (SYSCALL_NUM) = __NR_##name; \
register unsigned long __ret __asm__ (SYSCALL_RET); \
__asm__ __volatile__ ("trap " SYSCALL_SHORT_TRAP \
: "=r" (__ret), "=r" (__syscall) \
: "1" (__syscall), "r" (__a) \
: SYSCALL_SHORT_CLOBBERS); \
__syscall_return (type, __ret); \
}
#define _syscall2(type, name, atype, a, btype, b) \
type name (atype a, btype b) \
{ \
register atype __a __asm__ (SYSCALL_ARG0) = a; \
register btype __b __asm__ (SYSCALL_ARG1) = b; \
register unsigned long __syscall __asm__ (SYSCALL_NUM) = __NR_##name; \
register unsigned long __ret __asm__ (SYSCALL_RET); \
__asm__ __volatile__ ("trap " SYSCALL_SHORT_TRAP \
: "=r" (__ret), "=r" (__syscall) \
: "1" (__syscall), "r" (__a), "r" (__b) \
: SYSCALL_SHORT_CLOBBERS); \
__syscall_return (type, __ret); \
}
#define _syscall3(type, name, atype, a, btype, b, ctype, c) \
type name (atype a, btype b, ctype c) \
{ \
register atype __a __asm__ (SYSCALL_ARG0) = a; \
register btype __b __asm__ (SYSCALL_ARG1) = b; \
register ctype __c __asm__ (SYSCALL_ARG2) = c; \
register unsigned long __syscall __asm__ (SYSCALL_NUM) = __NR_##name; \
register unsigned long __ret __asm__ (SYSCALL_RET); \
__asm__ __volatile__ ("trap " SYSCALL_SHORT_TRAP \
: "=r" (__ret), "=r" (__syscall) \
: "1" (__syscall), "r" (__a), "r" (__b), "r" (__c) \
: SYSCALL_SHORT_CLOBBERS); \
__syscall_return (type, __ret); \
}
#define _syscall4(type, name, atype, a, btype, b, ctype, c, dtype, d) \
type name (atype a, btype b, ctype c, dtype d) \
{ \
register atype __a __asm__ (SYSCALL_ARG0) = a; \
register btype __b __asm__ (SYSCALL_ARG1) = b; \
register ctype __c __asm__ (SYSCALL_ARG2) = c; \
register dtype __d __asm__ (SYSCALL_ARG3) = d; \
register unsigned long __syscall __asm__ (SYSCALL_NUM) = __NR_##name; \
register unsigned long __ret __asm__ (SYSCALL_RET); \
__asm__ __volatile__ ("trap " SYSCALL_SHORT_TRAP \
: "=r" (__ret), "=r" (__syscall) \
: "1" (__syscall), \
"r" (__a), "r" (__b), "r" (__c), "r" (__d) \
: SYSCALL_SHORT_CLOBBERS); \
__syscall_return (type, __ret); \
}
#define _syscall5(type, name, atype, a, btype, b, ctype, c, dtype, d, etype,e)\
type name (atype a, btype b, ctype c, dtype d, etype e) \
{ \
register atype __a __asm__ (SYSCALL_ARG0) = a; \
register btype __b __asm__ (SYSCALL_ARG1) = b; \
register ctype __c __asm__ (SYSCALL_ARG2) = c; \
register dtype __d __asm__ (SYSCALL_ARG3) = d; \
register etype __e __asm__ (SYSCALL_ARG4) = e; \
register unsigned long __syscall __asm__ (SYSCALL_NUM) = __NR_##name; \
register unsigned long __ret __asm__ (SYSCALL_RET); \
__asm__ __volatile__ ("trap " SYSCALL_LONG_TRAP \
: "=r" (__ret), "=r" (__syscall), "=r" (__e) \
: "1" (__syscall), \
"r" (__a), "r" (__b), "r" (__c), "r" (__d), "2" (__e) \
: SYSCALL_CLOBBERS); \
__syscall_return (type, __ret); \
}
#define _syscall6(type, name, atype, a, btype, b, ctype, c, dtype, d, etype, e, ftype, f) \
type name (atype a, btype b, ctype c, dtype d, etype e, ftype f) \
{ \
register atype __a __asm__ (SYSCALL_ARG0) = a; \
register btype __b __asm__ (SYSCALL_ARG1) = b; \
register ctype __c __asm__ (SYSCALL_ARG2) = c; \
register dtype __d __asm__ (SYSCALL_ARG3) = d; \
register etype __e __asm__ (SYSCALL_ARG4) = e; \
register etype __f __asm__ (SYSCALL_ARG5) = f; \
register unsigned long __syscall __asm__ (SYSCALL_NUM) = __NR_##name; \
register unsigned long __ret __asm__ (SYSCALL_RET); \
__asm__ __volatile__ ("trap " SYSCALL_LONG_TRAP \
: "=r" (__ret), "=r" (__syscall), \
"=r" (__e), "=r" (__f) \
: "1" (__syscall), \
"r" (__a), "r" (__b), "r" (__c), "r" (__d), \
"2" (__e), "3" (__f) \
: SYSCALL_CLOBBERS); \
__syscall_return (type, __ret); \
}
#ifdef __KERNEL_SYSCALLS__
/*
* we need this inline - forking from kernel space will result
* in NO COPY ON WRITE (!!!), until an execve is executed. This
* is no problem, but for the stack. This is handled by not letting
* main() use the stack at all after fork(). Thus, no function
* calls - which means inline code for fork too, as otherwise we
* would use the stack upon exit from 'fork()'.
*
* Actually only pause and fork are needed inline, so that there
* won't be any messing with the stack from main(), but we define
* some others too.
*/
#define __NR__exit __NR_exit
extern inline _syscall0(pid_t,setsid)
extern inline _syscall3(int,write,int,fd,const char *,buf,off_t,count)
extern inline _syscall3(int,read,int,fd,char *,buf,off_t,count)
extern inline _syscall3(off_t,lseek,int,fd,off_t,offset,int,count)
extern inline _syscall1(int,dup,int,fd)
extern inline _syscall3(int,execve,const char *,file,char **,argv,char **,envp)
extern inline _syscall3(int,open,const char *,file,int,flag,int,mode)
extern inline _syscall1(int,close,int,fd)
extern inline _syscall1(int,_exit,int,exitcode)
extern inline _syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options)
extern inline pid_t wait(int * wait_stat)
{
return waitpid (-1, wait_stat, 0);
}
#endif
/*
* "Conditional" syscalls
*/
#define cond_syscall(name) \
asm (".weak\t" C_SYMBOL_STRING(name) ";" \
".set\t" C_SYMBOL_STRING(name) "," C_SYMBOL_STRING(sys_ni_syscall));
#if 0
/* This doesn't work if there's a function prototype for NAME visible,
because the argument types probably won't match. */
#define cond_syscall(name) \
void name (void) __attribute__ ((weak, alias ("sys_ni_syscall")));
#endif
#endif /* __V850_UNISTD_H__ */
#ifndef __V850_USER_H__
#define __V850_USER_H__
/* Adapted from <asm-ppc/user.h>. */
#ifdef __KERNEL__
#include <linux/ptrace.h>
#include <asm/page.h>
/*
* Core file format: The core file is written in such a way that gdb
* can understand it and provide useful information to the user (under
* linux we use the `trad-core' bfd, NOT the osf-core). The file contents
* are as follows:
*
* upage: 1 page consisting of a user struct that tells gdb
* what is present in the file. Directly after this is a
* copy of the task_struct, which is currently not used by gdb,
* but it may come in handy at some point. All of the registers
* are stored as part of the upage. The upage should always be
* only one page long.
* data: The data segment follows next. We use current->end_text to
* current->brk to pick up all of the user variables, plus any memory
* that may have been sbrk'ed. No attempt is made to determine if a
* page is demand-zero or if a page is totally unused, we just cover
* the entire range. All of the addresses are rounded in such a way
* that an integral number of pages is written.
* stack: We need the stack information in order to get a meaningful
* backtrace. We need to write the data from usp to
* current->start_stack, so we round each of these in order to be able
* to write an integer number of pages.
*/
struct user {
struct pt_regs regs; /* entire machine state */
size_t u_tsize; /* text size (pages) */
size_t u_dsize; /* data size (pages) */
size_t u_ssize; /* stack size (pages) */
unsigned long start_code; /* text starting address */
unsigned long start_data; /* data starting address */
unsigned long start_stack; /* stack starting address */
long int signal; /* signal causing core dump */
struct regs * u_ar0; /* help gdb find registers */
unsigned long magic; /* identifies a core file */
char u_comm[32]; /* user command name */
};
#define NBPG PAGE_SIZE
#define UPAGES 1
#define HOST_TEXT_START_ADDR (u.start_code)
#define HOST_DATA_START_ADDR (u.start_data)
#define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG)
#endif /* __KERNEL__ */
#endif /* __V850_USER_H__ */
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