This is a large patch from Eric Valette <valette@crf.canon.fr> that was

described in the message following this paragraph.  This patch also includes
a mcp750 BSP.

From valette@crf.canon.fr Mon Jun 14 10:03:08 1999
Date: Tue, 18 May 1999 01:30:14 +0200 (CEST)
From: VALETTE Eric <valette@crf.canon.fr>
To: joel@oarcorp.com
Cc: raguet@crf.canon.fr, rtems-snapshots@oarcorp.com, valette@crf.canon.fr
Subject: Questions/Suggestion regarding RTEMS PowerPC code (long)


Dear knowledgeable RTEMS powerpc users,

As some of you may know, I'm currently finalizing a port
of RTEMS on a MCP750 Motorola board. I have done most
of it but have some questions to ask before submitting
the port.

In order to understand some of the changes I have made
or would like to make, maybe it is worth describing the
MCP750 Motorola board.

the MCP750 is a COMPACT PCI powerpc board with :

	1) a MPC750 233 MHz processor,
	2) a raven bus bridge/PCI controller that
	implement an OPENPIC compliant interrupt controller,
	3) a VIA 82C586 PCI/ISA bridge that offers a PC
	compliant IO for keyboard, serial line, IDE, and
	the well known PC 8259 cascaded PIC interrupt
	architecture model,
	4) a DEC 21140 Ethernet controller,
	5) the PPCBUG Motorola firmware in flash,
	6) A DEC PCI bridge,

This architecture is common to most Motorola 60x/7xx
board except that :
	1) on VME board, the DEC PCI bridge is replaced by
	a VME chipset,
	2) the VIA 82C586 PCI/ISA bridge is replaced by
	another bridge that is almost fully compatible
	with the via bridge...

So the port should be a rather close basis for many
60x/7xx motorola board...

On this board, I already have ported Linux 2.2.3 and
use it both as a development and target board.

Now the questions/suggestions I have :

1)  EXCEPTION CODE
-------------------

As far as I know exceptions on PPC are handled like
interrupts. I dislike this very much as :

	a) Except for the decrementer exception (and
	maybe some other on mpc8xx), exceptions are
	not recoverable and the handler just need to print
	the full context and go to the firmware or debugger...
	b) The interrupt switch is only necessary for the
	decrementer and external interrupt (at least on
	6xx,7xx).
	c) The full context for exception is never saved and
	thus cannot be used by debugger... I do understand
	the most important for interrupts low level code
	is to save the minimal context enabling	to call C
	code for performance reasons. On non recoverable
	exception on the other hand, the most important is
	to save the maximum information concerning proc status
	in order to analyze the reason of the fault. At
	least we will need this in order to implement the
	port of RGDB on PPC

==> I wrote an API for connecting raw exceptions (and thus
raw interrupts) for mpc750. It should be valid for most
powerpc processors... I hope to find a way to make this coexist
with actual code layout. The code is actually located
in lib/libcpu/powerpc/mpc750 and is thus optional
(provided I write my own version of exec/score/cpu/powerpc/cpu.c ...)

See remark about files/directory layout organization in 4)

2) Current Implementation of ISR low level code
-----------------------------------------------

I do not understand why the MSR EE flags is cleared
again in exec/score/cpu/powerpc/irq_stubs.S

#if (PPC_USE_SPRG)
	mfmsr	r5
	mfspr   r6, sprg2
#else
        lwz	r6,msr_initial(r11)
	lis     r5,~PPC_MSR_DISABLE_MASK@ha
        ori     r5,r5,~PPC_MSR_DISABLE_MASK@l
	and	r6,r6,r5
	mfmsr	r5
#endif

Reading the doc, when a decrementer interrupt or an
external interrupt is active, the MSR EE flag is already
cleared. BTW if exception/interrupt could occur, it would
trash SRR0 and SRR1. In fact the code may be useful to set
MSR[RI] that re-enables exception processing. BTW I will need
to set other value in MSR to handle interrupts :

	a) I want the MSR[IR] and MSR[DR] to be set for
	performance reasons and also because I need DBAT
	support to have access to PCI memory space as the
	interrupt controller is in the PCI space.

Reading the code, I see others have the same kind of request :

/* SCE 980217
 *
 * We need address translation ON when we call our ISR routine

	mtmsr	r5

 */

This is just another prof that even the lowest level
IRQ code is fundamentally board dependent and
not simply processor dependent especially when
the processor use external interrupt controller
because it has a single interrupt request line...

Note that if you look at the PPC code high level interrupt
handling code, as the "set_vector" routine that really connects
the interrupt is in the BSP/startup/genpvec.c,
the fact that IRQ handling is BSP specific is DE-FACTO
acknowledged.

I know I have already expressed this and understand that this
would require some heavy change in the code but believe
me you will reach a point where you will not be able
to find a compatible while optimum implementation for low level
interrupt handling code...) In my case this is already true...

So please consider removing low level IRQ handling from
exec/score/cpu/* and only let there exception handling code...
Exceptions are usually only processor dependent and do
not depend on external hardware mechanism to be masked or
acknowledged or re-enabled (there are probably exception but ...)

I have already done this for pc386 bsp but need to make it again.
This time I will even propose an API.

3) R2/R13 manipulation for EABI implementation
----------------------------------------------

I do not understand the handling of r2 and r13 in the
EABI case. The specification for r2 says pointer to sdata2,
sbss2 section => constant. However I do not see -ffixed-r2
passed to any compilation system in make/custom/*
(for info linux does this on PPC).

So either this is a default compiler option when choosing
powerpc-rtems and thus we do not need to do anything with
this register as all the code is compiled with this compiler
and linked together OR this register may be used by rtems code
and then we do not need any special initialization or
handling.

The specification for r13 says pointer to the small data
area. r13 argumentation is the same except that as far
as I know the usage of the small data area requires
specific compiler support so that access to variables is
compiled via loading the LSB in a register and then
using r13 to get full address... It is like a small
memory model and it was present in IBM C compilers.

=> I propose to suppress any specific code for r2 and
r13 in the EABI case.

4) Code layout organization (yes again :-))
-------------------------------------------

I think there are a number of design flaws in the way
the code is for ppc organized and I will try to point them out.
I have been beaten by this again on this new port, and
was beaten last year while modifying code for pc386.

a) exec/score/cpu/* vs lib/libcpu/cpu/*.

I think that too many things are put in exec/score/cpu that
have nothing to do with RTEMS internals but are rather
related to CPU feature.

This include at least :

	a) registers access routine (e.g GET_MSR_Value),
	b) interrupt masking/unmasking routines,
	c) cache_mngt_routine,
	d) mmu_mngt_routine,
	e) Routines to connect the raw_exception, raw_interrupt
	handler,

b) lib/libcpu/cpu/powerpc/*

With a processor family as exuberant as the powerpc family,
and their well known subtle differences (604 vs 750) or
unfortunately majors (8xx vs 60x)  the directory structure
is fine (except maybe the names that are not homogeneous)

	powerpc

ppc421 mpc821 ...

I only needed to add mpc750. But the fact that libcpu.a was not
produced was a pain and the fact that this organization may
duplicates code is also problematic.

So, except if the support of automake provides a better solution
I would like to propose something like this :

		powerpc

mpc421 	mpc821	...	mpc750	shared wrapup

with the following rules :

	a) "shared" would act as a source container for sources that may
	be shared among processors. Needed files would be compiled inside
	the processor specific directory using the vpath Makefile
	mechanism. "shared" may also contain compilation code
	for routine that are really shared and not worth to inline...
	(did not found many things so far as registers access routine
	ARE WORTH INLINING)... In the case something is compiled there,
	it should create libcpushared.a

	b) layout under processor specific directory is free provided
	that
		1)the result of the compilation process exports :

		libcpu/powerpc/"PROC"/*.h in $(PROJECT_INCLUDE)/libcpu

		2) each processor specific directory creates
		a library called libcpuspecific.a
	Note that this organization enables to have a file that
	is nearly the same than in shared but that must differ
	because of processor differences...

	c) "wrapup" should create libcpu.a using libcpushared.a
	libcpuspecific.a and export it $(PROJECT_INCLUDE)/libcpu

The only thing I have no ideal solution is the way to put shared
definitions in "shared" and only processor specific definition
in "proc". To give a concrete example, most MSR bit definition
are shared among PPC processors and only some differs. if we create
a single msr.h in shared it will have ifdef. If in msr.h we
include libcpu/msr_c.h we will need to have it in each prowerpc
specific directory (even empty). Opinions are welcomed ...

Note that a similar mechanism exist in libbsp/i386 that also
contains a shared directory that is used by several bsp
like pc386 and i386ex and a similar wrapup mechanism...

NB: I have done this for mpc750 and other processors could just use
similar Makefiles...

c) The exec/score/cpu/powerpc directory layout.

I think the directory layout should be the same than the
libcpu/powerpc. As it is not, there are a lot of ifdefs
inside the code... And of course low level interrupt handling
code should be removed...

Besides that I do not understand why

	1) things are compiled in the wrap directory,
	2) some includes are moved to rtems/score,

I think the "preinstall" mechanism enables to put
everything in the current directory (or better in a per processor
directory),


5) Interrupt handling API
-------------------------

Again :-). But I think that using all the features the PIC
offers is a MUST for RT system. I already explained in the
prologue of this (long and probably boring) mail that the MCP750
boards offers an OPENPIC compliant architecture and that
the VIA 82586 PCI/ISA bridge offers a PC compatible IO and
PIC mapping. Here is a logical view of the RAVEN/VIA 82586
interrupt mapping :


---------    0  ------
| OPEN	| <-----|8259|
| PIC	|	|    |    2  ------
|(RAVEN)|	|    | <-----|8259|
|	|	|    |	     |    |   11
|	|	|    |	     |    | <----
|	|	|    |	     |    |
|	|	|    |	     |    |
---------       ------	     |    |
    ^			     ------
    |		VIA PCI/ISA bridge
    |  x
    -------- PCI interrupts

OPENPIC offers interrupt priorities among PCI interrupts
and interrupt selective masking. The 8259 offers the same kind
of feature. With actual powerpc interrupt code :

	1) there is no way to specify priorities among
	interrupts handler. This is REALLY a bad thing.
	For me it is as importnat as having priorities
	for threads...
	2) for my implementation, each ISR should
	contain the code that acknowledge the RAVEN
	and 8259 cascade, modify interrupt mask on both
	chips, and reenable interrupt at processor level,
	..., restore then on interrupt return,.... This code
	is actually similar to code located in some
	genpvec.c powerpc files,
	3) I must update _ISR_Nesting_level because
	irq.inl use it...
	4) the libchip code connects the ISR via set_vector
	but the libchip handler code does not contain any code to
	manipulate external interrupt controller hardware
	in order to acknoledge the interrupt or re-enable
	them (except for the target hardware of course)
	So this code is broken unless set_vector adds an
	additionnal prologue/epilogue before calling/returning
	from in order to acknoledge/mask the raven and the
	8259 PICS... => Anyway already EACH BSP MUST REWRITE
	PART OF INTERRUPT HANDLING CODE TO CORRECTLY IMPLEMENT
	SET_VECTOR.

I would rather offer an API similar to the one provided
in libbsp/i386/shared/irq/irq.h so that :

	1) Once the driver supplied methods is called the
	only things the ISR has to do is to worry about the
	external hardware that triggered the interrupt.
	Everything on openpic/VIA/processor would have been
	done by the low levels (same things as set-vector)
	2) The caller will need to supply the on/off/isOn
	routine that are fundamental to correctly implements
	debuggers/performance monitoring is a portable way
	3) A globally configurable interrupt priorities
	mechanism...

I have nothing against providing a compatible
set_vector just to make libchip happy but
as I have already explained in  other
mails (months ago), I really think that the ISR
connection should be handled by the BSP and that no
code containing irq connection should exist the
rtems generic layers... Thus I really dislike
libchip on this aspect because in a long term
it will force to adopt the less reach API
for interrupt handling that exists (set_vector).

Additional note : I think the _ISR_Is_in_progress()
inline routine should be :

	1) Put in a processor specific section,
	2) Should not rely on a global variable,

As :
	a) on symmetric MP, there is one interrupt level
	per CPU,
	b) On processor that have an ISP (e,g 68040),
	this variable is useless (MSR bit testing could
	be used)
	c) On PPC, instead of using the address of the
	variable via __CPU_IRQ_info.Nest_level a dedicated
	SPR could be used.

NOTE:	most of this is also true for _Thread_Dispatch_disable_level


END NOTE
--------

Please do not take what I said in the mail as a criticism for
anyone who submitted ppc code. Any code present helped me
a lot understanding PPC behavior. I just wanted by this
mail to :
	1) try to better understand the actual code,
	2) propose concrete ways of enhancing current code
	by providing an alternative implementation for MCP750. I
	will make my best effort to try to brake nothing but this
	is actually hard due to the file layout organisation.
	3) make understandable some changes I will probably make
	if joel let me do them :-)

Any comments/objections are welcomed as usual.



--
   __
  /  `                   	Eric Valette
 /--   __  o _.          	Canon CRF
(___, / (_(_(__         	Rue de la touche lambert
				35517 Cesson-Sevigne  Cedex
				FRANCE
Tel: +33 (0)2 99 87 68 91	Fax: +33 (0)2 99 84 11 30
E-mail: valette@crf.canon.fr
This commit is contained in:
Joel Sherrill
1999-06-14 16:51:13 +00:00
parent 255b2931b6
commit ba46ffa616
162 changed files with 50702 additions and 2806 deletions
+12 -4
View File
@@ -1,4 +1,7 @@
#
# $Id$
#
#
# $Id$
#
@@ -18,8 +21,13 @@ VPATH = @srcdir@
include $(RTEMS_ROOT)/make/custom/${RTEMS_BSP}.cfg
include $(RTEMS_ROOT)/make/directory.cfg
SUB_DIRS = rtems wrap
SHARED_LIB=shared
ifeq ($(RTEMS_CPU_MODEL),mpc750)
CPUDIR=mpc750
else
CPUDIR=other_cpu
endif
SUB_DIRS=$(CPUDIR) $(SHARED_LIB)
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
cd $(top_builddir) \
&& CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+275
View File
@@ -0,0 +1,275 @@
/* asm.h
*
* This include file attempts to address the problems
* caused by incompatible flavors of assemblers and
* toolsets. It primarily addresses variations in the
* use of leading underscores on symbols and the requirement
* that register names be preceded by a %.
*
*
* NOTE: The spacing in the use of these macros
* is critical to them working as advertised.
*
* COPYRIGHT:
*
* This file is based on similar code found in newlib available
* from ftp.cygnus.com. The file which was used had no copyright
* notice. This file is freely distributable as long as the source
* of the file is noted. This file is:
*
* COPYRIGHT (c) 1995.
* i-cubed ltd.
*
* COPYRIGHT (c) 1994.
* On-Line Applications Research Corporation (OAR).
*
* $Id$
*/
#ifndef __PPC_ASM_h
#define __PPC_ASM_h
/*
* Indicate we are in an assembly file and get the basic CPU definitions.
*/
#ifndef ASM
#define ASM
#endif
#include <rtems/score/targopts.h>
#include <rtems/score/ppc.h>
/*
* Recent versions of GNU cpp define variables which indicate the
* need for underscores and percents. If not using GNU cpp or
* the version does not support this, then you will obviously
* have to define these as appropriate.
*/
#ifndef __USER_LABEL_PREFIX__
#define __USER_LABEL_PREFIX__
#endif
#ifndef __REGISTER_PREFIX__
#define __REGISTER_PREFIX__
#endif
#ifndef __FLOAT_REGISTER_PREFIX__
#define __FLOAT_REGISTER_PREFIX__ __REGISTER_PREFIX__
#endif
#if (PPC_ABI == PPC_ABI_POWEROPEN)
#ifndef __PROC_LABEL_PREFIX__
#define __PROC_LABEL_PREFIX__ .
#endif
#endif
#ifndef __PROC_LABEL_PREFIX__
#define __PROC_LABEL_PREFIX__ __USER_LABEL_PREFIX__
#endif
/* ANSI concatenation macros. */
#define CONCAT1(a, b) CONCAT2(a, b)
#define CONCAT2(a, b) a ## b
/* Use the right prefix for global labels. */
#define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
/* Use the right prefix for procedure labels. */
#define PROC(x) CONCAT1 (__PROC_LABEL_PREFIX__, x)
/* Use the right prefix for registers. */
#define REG(x) CONCAT1 (__REGISTER_PREFIX__, x)
/* Use the right prefix for floating point registers. */
#define FREG(x) CONCAT1 (__FLOAT_REGISTER_PREFIX__, x)
/*
* define macros for all of the registers on this CPU
*
* EXAMPLE: #define d0 REG (d0)
*/
#define r0 REG(0)
#define r1 REG(1)
#define r2 REG(2)
#define r3 REG(3)
#define r4 REG(4)
#define r5 REG(5)
#define r6 REG(6)
#define r7 REG(7)
#define r8 REG(8)
#define r9 REG(9)
#define r10 REG(10)
#define r11 REG(11)
#define r12 REG(12)
#define r13 REG(13)
#define r14 REG(14)
#define r15 REG(15)
#define r16 REG(16)
#define r17 REG(17)
#define r18 REG(18)
#define r19 REG(19)
#define r20 REG(20)
#define r21 REG(21)
#define r22 REG(22)
#define r23 REG(23)
#define r24 REG(24)
#define r25 REG(25)
#define r26 REG(26)
#define r27 REG(27)
#define r28 REG(28)
#define r29 REG(29)
#define r30 REG(30)
#define r31 REG(31)
#define f0 FREG(0)
#define f1 FREG(1)
#define f2 FREG(2)
#define f3 FREG(3)
#define f4 FREG(4)
#define f5 FREG(5)
#define f6 FREG(6)
#define f7 FREG(7)
#define f8 FREG(8)
#define f9 FREG(9)
#define f10 FREG(10)
#define f11 FREG(11)
#define f12 FREG(12)
#define f13 FREG(13)
#define f14 FREG(14)
#define f15 FREG(15)
#define f16 FREG(16)
#define f17 FREG(17)
#define f18 FREG(18)
#define f19 FREG(19)
#define f20 FREG(20)
#define f21 FREG(21)
#define f22 FREG(22)
#define f23 FREG(23)
#define f24 FREG(24)
#define f25 FREG(25)
#define f26 FREG(26)
#define f27 FREG(27)
#define f28 FREG(28)
#define f29 FREG(29)
#define f30 FREG(30)
#define f31 FREG(31)
/*
* Some special purpose registers (SPRs).
*/
#define srr0 0x01a
#define srr1 0x01b
#define srr2 0x3de /* IBM 400 series only */
#define srr3 0x3df /* IBM 400 series only */
#define sprg0 0x110
#define sprg1 0x111
#define sprg2 0x112
#define sprg3 0x113
/* the following SPR/DCR registers exist only in IBM 400 series */
#define dear 0x3d5
#define evpr 0x3d6 /* SPR: exception vector prefix register */
#define iccr 0x3fb /* SPR: instruction cache control reg. */
#define dccr 0x3fa /* SPR: data cache control reg. */
#define exisr 0x040 /* DCR: external interrupt status register */
#define exier 0x042 /* DCR: external interrupt enable register */
#define br0 0x080 /* DCR: memory bank register 0 */
#define br1 0x081 /* DCR: memory bank register 1 */
#define br2 0x082 /* DCR: memory bank register 2 */
#define br3 0x083 /* DCR: memory bank register 3 */
#define br4 0x084 /* DCR: memory bank register 4 */
#define br5 0x085 /* DCR: memory bank register 5 */
#define br6 0x086 /* DCR: memory bank register 6 */
#define br7 0x087 /* DCR: memory bank register 7 */
/* end of IBM400 series register definitions */
/* The following registers are for the MPC8x0 */
#define der 0x095 /* Debug Enable Register */
/* end of MPC8x0 registers */
/*
* Following must be tailor for a particular flavor of the C compiler.
* They may need to put underscores in front of the symbols.
*/
#define PUBLIC_VAR(sym) .globl SYM (sym)
#define EXTERN_VAR(sym) .extern SYM (sym)
#define PUBLIC_PROC(sym) .globl PROC (sym)
#define EXTERN_PROC(sym) .extern PROC (sym)
/* Other potentially assembler specific operations */
#if PPC_ASM == PPC_ASM_ELF
#define ALIGN(n,p) .align p
#define DESCRIPTOR(x) \
.section .descriptors,"aw"; \
PUBLIC_VAR (x); \
SYM (x):; \
.long PROC (x); \
.long s.got; \
.long 0
#define EXT_SYM_REF(x) .long x
#define EXT_PROC_REF(x) .long x
/*
* Define macros to handle section beginning and ends.
*/
#define BEGIN_CODE_DCL .text
#define END_CODE_DCL
#define BEGIN_DATA_DCL .data
#define END_DATA_DCL
#define BEGIN_CODE .text
#define END_CODE
#define BEGIN_DATA .data
#define END_DATA
#define BEGIN_BSS .bss
#define END_BSS
#define END
#elif PPC_ASM == PPC_ASM_XCOFF
#define ALIGN(n,p) .align p
#define DESCRIPTOR(x) \
.csect x[DS]; \
.globl x[DS]; \
.long PROC (x)[PR]; \
.long TOC[tc0]
#define EXT_SYM_REF(x) .long x[RW]
#define EXT_PROC_REF(x) .long x[DS]
/*
* Define macros to handle section beginning and ends.
*/
#define BEGIN_CODE_DCL .csect .text[PR]
#define END_CODE_DCL
#define BEGIN_DATA_DCL .csect .data[RW]
#define END_DATA_DCL
#define BEGIN_CODE .csect .text[PR]
#define END_CODE
#define BEGIN_DATA .csect .data[RW]
#define END_DATA
#define BEGIN_BSS .bss
#define END_BSS
#define END
#else
#error "PPC_ASM_TYPE is not properly defined"
#endif
#ifndef PPC_ASM
#error "PPC_ASM_TYPE is not properly defined"
#endif
#endif
/* end of include file */
@@ -0,0 +1,83 @@
#
# $Id$
#
@SET_MAKE@
srcdir = @srcdir@
top_srcdir = @top_srcdir@
top_builddir = ../../../../../../..
subdir = c/src/exec/score/cpu/powerpc/wrap
INSTALL = @INSTALL@
RTEMS_ROOT = $(top_srcdir)/@RTEMS_TOPdir@
PROJECT_ROOT = @PROJECT_ROOT@
VPATH = @srcdir@
RELS=../$(ARCH)/rtems-cpu.rel
# C source names, if any, go here -- minus the .c
C_PIECES = cpu
C_FILES=$(C_PIECES:%=%.c)
C_O_FILES=$(C_PIECES:%=${ARCH}/%.o)
ROOT_H_PIECES =
ROOT_H_FILES=$(ROOT_H_PIECES:%=$(srcdir)/%)
RTEMS_SCORE_H_PIECES=cpu.h
RTEMS_SCORE_H_FILES=$(RTEMS_SCORE_H_PIECES:%=$(srcdir)/%)
H_PIECES=$(ROOT_H_PIECES) $(RTEMS_SCORE_H_PIECES)
H_FILES=$(H_PIECES%=$(srcdir)/%)
I_PIECES= c_isr
I_FILES=$(I_PIECES:%=$(srcdir)/%.inl)
# Assembly source names, if any, go here -- minus the .S
S_PIECES = cpu_asm
S_FILES=$(S_PIECES:%=%.S)
S_O_FILES=$(S_FILES:%.S=${ARCH}/%.o)
SRCS=$(C_FILES) $(CC_FILES) $(H_FILES) $(S_FILES) $(EXTERNAL_H_FILES) $(I_FILES)
OBJS=$(C_O_FILES) $(CC_O_FILES) $(S_O_FILES)
include $(RTEMS_ROOT)/make/custom/${RTEMS_BSP}.cfg
include $(RTEMS_ROOT)/make/leaf.cfg
#
# (OPTIONAL) Add local stuff here using +=
#
DEFINES +=
CPPFLAGS +=
CFLAGS += $(CFLAGS_OS_V)
LD_PATHS +=
LD_LIBS +=
LDFLAGS +=
#
# Add your list of files to delete here. The config files
# already know how to delete some stuff, so you may want
# to just run 'make clean' first to see what gets missed.
# 'make clobber' already includes 'make clean'
#
CLEAN_ADDITIONS +=
CLOBBER_ADDITIONS +=
../$(ARCH)/rtems-cpu.rel: $(OBJS)
test -d ../$(ARCH) || mkdir ../$(ARCH)
$(make-rel)
all: ${ARCH} $(SRCS) preinstall $(OBJS) $(RELS)
# Install the program(s), appending _g or _p as appropriate.
# for include files, just use $(INSTALL_CHANGE)
install: all
preinstall: ${ARCH}
$(INSTALL_CHANGE) -m 444 ${RTEMS_SCORE_H_FILES} ${I_FILES} $(PROJECT_INCLUDE)/rtems/score
$(INSTALL_CHANGE) -m 444 ${ROOT_H_FILES} $(PROJECT_INCLUDE)
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
cd $(top_builddir) \
&& CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
@@ -0,0 +1,9 @@
RTEMS_INLINE_ROUTINE boolean _ISR_Is_in_progress( void )
{
register unsigned int isr_nesting_level;
/*
* Move from special purpose register 0 (mfspr SPRG0, r3)
*/
asm volatile ("mfspr %0, 272" : "=r" (isr_nesting_level));
return isr_nesting_level;
}
+118
View File
@@ -0,0 +1,118 @@
/*
* PowerPC CPU Dependent Source
*
* Author: Andrew Bray <andy@i-cubed.co.uk>
*
* COPYRIGHT (c) 1995 by i-cubed ltd.
*
* To anyone who acknowledges that this file is provided "AS IS"
* without any express or implied warranty:
* permission to use, copy, modify, and distribute this file
* for any purpose is hereby granted without fee, provided that
* the above copyright notice and this notice appears in all
* copies, and that the name of i-cubed limited not be used in
* advertising or publicity pertaining to distribution of the
* software without specific, written prior permission.
* i-cubed limited makes no representations about the suitability
* of this software for any purpose.
*
* Derived from c/src/exec/cpu/no_cpu/cpu.c:
*
* COPYRIGHT (c) 1989-1997.
* On-Line Applications Research Corporation (OAR).
* Copyright assigned to U.S. Government, 1994.
*
* The license and distribution terms for this file may be found in
* the file LICENSE in this distribution or at
* http://www.OARcorp.com/rtems/license.html.
*
* $Id$
*/
#include <rtems/system.h>
#include <rtems/score/isr.h>
#include <rtems/score/context.h>
#include <rtems/score/thread.h>
#include <rtems/score/interr.h>
/* _CPU_Initialize
*
* This routine performs processor dependent initialization.
*
* INPUT PARAMETERS:
* cpu_table - CPU table to initialize
* thread_dispatch - address of disptaching routine
*/
void _CPU_Initialize(
rtems_cpu_table *cpu_table,
void (*thread_dispatch) /* ignored on this CPU */
)
{
_CPU_Table = *cpu_table;
}
/*PAGE
*
* _CPU_Context_Initialize
*/
#define CPU_MINIMUM_STACK_FRAME_SIZE 8
void _CPU_Context_Initialize(
Context_Control *the_context,
unsigned32 *stack_base,
unsigned32 size,
unsigned32 new_level,
void *entry_point,
boolean is_fp
)
{
unsigned32 msr_value;
unsigned32 sp;
sp = (unsigned32)stack_base + size - CPU_MINIMUM_STACK_FRAME_SIZE;
*((unsigned32 *)sp) = 0;
the_context->gpr1 = sp;
_CPU_MSR_GET( msr_value );
if (!(new_level & CPU_MODES_INTERRUPT_MASK)) {
msr_value |= MSR_EE;
}
else {
msr_value &= ~MSR_EE;
}
the_context->msr = msr_value;
/*
* The FP bit of the MSR should only be enabled if this is a floating
* point task. Unfortunately, the vfprintf_r routine in newlib
* ends up pushing a floating point register regardless of whether or
* not a floating point number is being printed. Serious restructuring
* of vfprintf.c will be required to avoid this behavior. At this
* time (7 July 1997), this restructuring is not being done.
*/
/*if ( is_fp ) */
the_context->msr |= PPC_MSR_FP;
the_context->pc = (unsigned32)entry_point;
}
/*PAGE
*
* _CPU_Install_interrupt_stack
*/
void _CPU_Install_interrupt_stack( void )
{
}
@@ -24,7 +24,7 @@
* On-Line Applications Research Corporation (OAR).
* Copyright assigned to U.S. Government, 1994.
*
* The license and distribution terms for this file may in
* The license and distribution terms for this file may be found in
* the file LICENSE in this distribution or at
* http://www.OARcorp.com/rtems/license.html.
*
@@ -39,9 +39,9 @@ extern "C" {
#endif
#include <rtems/score/ppc.h> /* pick up machine definitions */
#include <libcpu/cpu.h>
#ifndef ASM
struct CPU_Interrupt_frame;
#include <rtems/score/ppctypes.h>
#endif
@@ -110,7 +110,7 @@ struct CPU_Interrupt_frame;
* procedure on that CPU.
*/
#define CPU_HAS_SOFTWARE_INTERRUPT_STACK FALSE
#define CPU_HAS_SOFTWARE_INTERRUPT_STACK TRUE
/*
* Does this CPU have hardware support for a dedicated interrupt stack?
@@ -127,12 +127,7 @@ struct CPU_Interrupt_frame;
* procedure on that CPU.
*/
/*
* ACB: This is a lie, but it gets us a handle on a call to set up
* a variable derived from the top of the interrupt stack.
*/
#define CPU_HAS_HARDWARE_INTERRUPT_STACK TRUE
#define CPU_HAS_HARDWARE_INTERRUPT_STACK FALSE
/*
* Does RTEMS allocate a dedicated interrupt stack in the Interrupt Manager?
@@ -144,7 +139,7 @@ struct CPU_Interrupt_frame;
* or CPU_INSTALL_HARDWARE_INTERRUPT_STACK is TRUE.
*/
#define CPU_ALLOCATE_INTERRUPT_STACK TRUE
#define CPU_ALLOCATE_INTERRUPT_STACK FALSE
/*
* Does the RTEMS invoke the user's ISR with the vector number and
@@ -152,7 +147,7 @@ struct CPU_Interrupt_frame;
* number (0)?
*/
#define CPU_ISR_PASSES_FRAME_POINTER 1
#define CPU_ISR_PASSES_FRAME_POINTER 0
/*
* Does the CPU have hardware floating point?
@@ -304,31 +299,6 @@ struct CPU_Interrupt_frame;
#define CPU_BIG_ENDIAN TRUE
#define CPU_LITTLE_ENDIAN FALSE
/*
* The following defines the number of bits actually used in the
* interrupt field of the task mode. How those bits map to the
* CPU interrupt levels is defined by the routine _CPU_ISR_Set_level().
*
* The interrupt level is bit mapped for the PowerPC family. The
* bits are set to 0 to indicate that a particular exception source
* enabled and 1 if it is disabled. This keeps with RTEMS convention
* that interrupt level 0 means all sources are enabled.
*
* The bits are assigned to correspond to enable bits in the MSR.
*/
#define PPC_INTERRUPT_LEVEL_ME 0x01
#define PPC_INTERRUPT_LEVEL_EE 0x02
#define PPC_INTERRUPT_LEVEL_CE 0x04
/* XXX should these be maskable? */
#if 0
#define PPC_INTERRUPT_LEVEL_DE 0x08
#define PPC_INTERRUPT_LEVEL_BE 0x10
#define PPC_INTERRUPT_LEVEL_SE 0x20
#endif
#define CPU_MODES_INTERRUPT_MASK 0x00000007
/*
* Processor defined structures
@@ -419,12 +389,8 @@ typedef struct {
typedef struct CPU_Interrupt_frame {
unsigned32 stacklink; /* Ensure this is a real frame (also reg1 save) */
#if (PPC_ABI == PPC_ABI_POWEROPEN || PPC_ABI == PPC_ABI_GCC27)
unsigned32 dummy[13]; /* Used by callees: PowerOpen ABI */
#else
unsigned32 dummy[1]; /* Used by callees: SVR4/EABI */
#endif
/* This is what is left out of the primary contexts */
unsigned32 calleeLr; /* link register used by callees: SVR4/EABI */
/* This is what is left out of the primary contexts */
unsigned32 gpr0;
unsigned32 gpr2; /* play safe */
unsigned32 gpr3;
@@ -450,8 +416,7 @@ typedef struct CPU_Interrupt_frame {
unsigned32 msr;
unsigned32 pad[3];
} CPU_Interrupt_frame;
/*
* The following table contains the information required to configure
* the PowerPC processor specific parameters.
@@ -471,41 +436,10 @@ typedef struct {
/* end of fields required on all CPUs */
unsigned32 clicks_per_usec; /* Timer clicks per microsecond */
void (*spurious_handler)(unsigned32 vector, CPU_Interrupt_frame *);
boolean exceptions_in_RAM; /* TRUE if in RAM */
#if (defined(ppc403) || defined(mpc860) || defined(mpc821))
unsigned32 serial_per_sec; /* Serial clocks per second */
boolean serial_external_clock;
boolean serial_xon_xoff;
boolean serial_cts_rts;
unsigned32 serial_rate;
unsigned32 timer_average_overhead; /* Average overhead of timer in ticks */
unsigned32 timer_least_valid; /* Least valid number from timer */
boolean timer_internal_clock; /* TRUE, when timer runs with CPU clk */
#endif
#if (defined(mpc860) || defined(mpc821))
unsigned32 clock_speed; /* Speed of CPU in Hz */
#endif
} rtems_cpu_table;
/*
* The following type defines an entry in the PPC's trap table.
*
* NOTE: The instructions chosen are RTEMS dependent although one is
* obligated to use two of the four instructions to perform a
* long jump. The other instructions load one register with the
* trap type (a.k.a. vector) and another with the psr.
*/
typedef struct {
unsigned32 stwu_r1; /* stwu %r1, -(??+IP_END)(%1)*/
unsigned32 stw_r0; /* stw %r0, IP_0(%r1) */
unsigned32 li_r0_IRQ; /* li %r0, _IRQ */
unsigned32 b_Handler; /* b PROC (_ISR_Handler) */
} CPU_Trap_table_entry;
/*
* This variable is optional. It is used on CPUs on which it is difficult
* to generate an "uninitialized" FP context. It is filled in by
@@ -531,6 +465,14 @@ typedef struct {
SCORE_EXTERN void *_CPU_Interrupt_stack_low;
SCORE_EXTERN void *_CPU_Interrupt_stack_high;
/*
* This defines the number of levels and the mask used to pick those
* bits out of a thread mode.
*/
#define CPU_MODES_INTERRUPT_LEVEL 0x00000001 /* interrupt level in mode */
#define CPU_MODES_INTERRUPT_MASK 0x00000001 /* interrupt level in mode */
/*
* With some compilation systems, it is difficult if not impossible to
* call a high-level language routine from assembly language. This
@@ -549,22 +491,11 @@ SCORE_EXTERN void *_CPU_Interrupt_stack_high;
SCORE_EXTERN struct {
unsigned32 *Nest_level;
unsigned32 *Disable_level;
void *Vector_table;
void *Stack;
#if (PPC_ABI == PPC_ABI_POWEROPEN)
unsigned32 Dispatch_r2;
#else
unsigned32 Default_r2;
#if (PPC_ABI != PPC_ABI_GCC27)
unsigned32 Default_r13;
#endif
#endif
volatile boolean *Switch_necessary;
boolean *Signal;
unsigned32 msr_initial;
} _CPU_IRQ_info CPU_STRUCTURE_ALIGNMENT;
/*
@@ -662,148 +593,29 @@ SCORE_EXTERN struct {
#define loc_string(a,b) a " (" #b ")\n"
#define _CPU_MSR_Value( _msr_value ) \
do { \
_msr_value = 0; \
asm volatile ("mfmsr %0" : "=&r" ((_msr_value)) : "0" ((_msr_value))); \
} while (0)
#define _CPU_MSR_SET( _msr_value ) \
{ asm volatile ("mtmsr %0" : "=&r" ((_msr_value)) : "0" ((_msr_value))); }
#if 0
#define _CPU_ISR_Disable( _isr_cookie ) \
{ register unsigned int _disable_mask = PPC_MSR_DISABLE_MASK; \
_isr_cookie = 0; \
asm volatile (
"mfmsr %0" : \
"=r" ((_isr_cookie)) : \
"0" ((_isr_cookie)) \
); \
asm volatile (
"andc %1,%0,%1" : \
"=r" ((_isr_cookie)), "=&r" ((_disable_mask)) : \
"0" ((_isr_cookie)), "1" ((_disable_mask)) \
); \
asm volatile (
"mtmsr %1" : \
"=r" ((_disable_mask)) : \
"0" ((_disable_mask)) \
); \
}
#endif
#define _CPU_ISR_Disable( _isr_cookie ) \
{ register unsigned int _disable_mask = PPC_MSR_DISABLE_MASK; \
_isr_cookie = 0; \
asm volatile ( \
"mfmsr %0; andc %1,%0,%1; mtmsr %1" : \
"=&r" ((_isr_cookie)), "=&r" ((_disable_mask)) : \
"0" ((_isr_cookie)), "1" ((_disable_mask)) \
); \
}
#define _CPU_Data_Cache_Block_Flush( _address ) \
do { register void *__address = (_address); \
register unsigned32 _zero = 0; \
asm volatile ( "dcbf %0,%1" : \
"=r" (_zero), "=r" (__address) : \
"0" (_zero), "1" (__address) \
); \
} while (0)
/*
* Enable interrupts to the previous level (returned by _CPU_ISR_Disable).
* This indicates the end of an RTEMS critical section. The parameter
* _isr_cookie is not modified.
*/
#define _CPU_ISR_Enable( _isr_cookie ) \
{ \
asm volatile ( "mtmsr %0" : \
"=r" ((_isr_cookie)) : \
"0" ((_isr_cookie))); \
}
/*
* This temporarily restores the interrupt to _isr_cookie before immediately
* disabling them again. This is used to divide long RTEMS critical
* sections into two or more parts. The parameter _isr_cookie is not
* modified.
*
* NOTE: The version being used is not very optimized but it does
* not trip a problem in gcc where the disable mask does not
* get loaded. Check this for future (post 10/97 gcc versions.
*/
#define _CPU_ISR_Flash( _isr_cookie ) \
{ register unsigned int _disable_mask = PPC_MSR_DISABLE_MASK; \
asm volatile ( \
"mtmsr %0; andc %1,%0,%1; mtmsr %1" : \
"=r" ((_isr_cookie)), "=r" ((_disable_mask)) : \
"0" ((_isr_cookie)), "1" ((_disable_mask)) \
); \
}
/*
* Map interrupt level in task mode onto the hardware that the CPU
* actually provides. Currently, interrupt levels which do not
* map onto the CPU in a generic fashion are undefined. Someday,
* it would be nice if these were "mapped" by the application
* via a callout. For example, m68k has 8 levels 0 - 7, levels
* 8 - 255 would be available for bsp/application specific meaning.
* This could be used to manage a programmable interrupt controller
* via the rtems_task_mode directive.
*/
unsigned32 _CPU_ISR_Calculate_level(
unsigned32 new_level
);
void _CPU_ISR_Set_level(
unsigned32 new_level
);
unsigned32 _CPU_ISR_Get_level( void );
void _CPU_ISR_install_raw_handler(
unsigned32 vector,
proc_ptr new_handler,
proc_ptr *old_handler
);
/* end of ISR handler macros */
/*
* Simple spin delay in microsecond units for device drivers.
* This is very dependent on the clock speed of the target.
*/
#define CPU_Get_timebase_low( _value ) \
asm volatile( "mftb %0" : "=r" (_value) )
#define delay( _microseconds ) \
do { \
unsigned32 start, ticks, now; \
CPU_Get_timebase_low( start ) ; \
ticks = (_microseconds) * Cpu_table.clicks_per_usec; \
do \
CPU_Get_timebase_low( now ) ; \
while (now - start < ticks); \
} while (0)
#define delay_in_bus_cycles( _cycles ) \
do { \
unsigned32 start, now; \
CPU_Get_timebase_low( start ); \
do \
CPU_Get_timebase_low( now ); \
while (now - start < (_cycles)); \
} while (0)
static inline unsigned32 _CPU_ISR_Get_level( void )
{
register unsigned int msr;
_CPU_MSR_GET(msr);
if (msr & MSR_EE) return 0;
else return 1;
}
static inline void _CPU_ISR_Set_level( unsigned32 level )
{
register unsigned int msr;
_CPU_MSR_GET(msr);
if (!(level & CPU_MODES_INTERRUPT_MASK)) {
msr |= MSR_EE;
}
else {
msr &= ~MSR_EE;
}
_CPU_MSR_SET(msr);
}
#define _CPU_ISR_install_vector(irq, new, old) {BSP_panic("_CPU_ISR_install_vector called\n");}
/* Context handler macros */
@@ -892,7 +704,7 @@ void _CPU_Context_Initialize(
*/
#define _CPU_Fatal_halt( _error ) \
_CPU_Fatal_error(_error)
_BSP_Fatal_error(_error)
/* end of Fatal Error manager macros */
@@ -999,17 +811,6 @@ void _CPU_Initialize(
void (*thread_dispatch)
);
/*
* _CPU_ISR_install_vector
*
* This routine installs an interrupt vector.
*/
void _CPU_ISR_install_vector(
unsigned32 vector,
proc_ptr new_handler,
proc_ptr *old_handler
);
/*
* _CPU_Install_interrupt_stack
@@ -0,0 +1,396 @@
/* cpu_asm.s 1.1 - 95/12/04
*
* This file contains the assembly code for the PowerPC implementation
* of RTEMS.
*
* Author: Andrew Bray <andy@i-cubed.co.uk>
*
* COPYRIGHT (c) 1995 by i-cubed ltd.
*
* To anyone who acknowledges that this file is provided "AS IS"
* without any express or implied warranty:
* permission to use, copy, modify, and distribute this file
* for any purpose is hereby granted without fee, provided that
* the above copyright notice and this notice appears in all
* copies, and that the name of i-cubed limited not be used in
* advertising or publicity pertaining to distribution of the
* software without specific, written prior permission.
* i-cubed limited makes no representations about the suitability
* of this software for any purpose.
*
* Derived from c/src/exec/cpu/no_cpu/cpu_asm.c:
*
* COPYRIGHT (c) 1989-1997.
* On-Line Applications Research Corporation (OAR).
* Copyright assigned to U.S. Government, 1994.
*
* The license and distribution terms for this file may in
* the file LICENSE in this distribution or at
* http://www.OARcorp.com/rtems/license.html.
*
* $Id$
*/
#include <asm.h>
/*
* Offsets for various Contexts
*/
.set GP_1, 0
.set GP_2, (GP_1 + 4)
.set GP_13, (GP_2 + 4)
.set GP_14, (GP_13 + 4)
.set GP_15, (GP_14 + 4)
.set GP_16, (GP_15 + 4)
.set GP_17, (GP_16 + 4)
.set GP_18, (GP_17 + 4)
.set GP_19, (GP_18 + 4)
.set GP_20, (GP_19 + 4)
.set GP_21, (GP_20 + 4)
.set GP_22, (GP_21 + 4)
.set GP_23, (GP_22 + 4)
.set GP_24, (GP_23 + 4)
.set GP_25, (GP_24 + 4)
.set GP_26, (GP_25 + 4)
.set GP_27, (GP_26 + 4)
.set GP_28, (GP_27 + 4)
.set GP_29, (GP_28 + 4)
.set GP_30, (GP_29 + 4)
.set GP_31, (GP_30 + 4)
.set GP_CR, (GP_31 + 4)
.set GP_PC, (GP_CR + 4)
.set GP_MSR, (GP_PC + 4)
.set FP_0, 0
.set FP_1, (FP_0 + 4)
.set FP_2, (FP_1 + 4)
.set FP_3, (FP_2 + 4)
.set FP_4, (FP_3 + 4)
.set FP_5, (FP_4 + 4)
.set FP_6, (FP_5 + 4)
.set FP_7, (FP_6 + 4)
.set FP_8, (FP_7 + 4)
.set FP_9, (FP_8 + 4)
.set FP_10, (FP_9 + 4)
.set FP_11, (FP_10 + 4)
.set FP_12, (FP_11 + 4)
.set FP_13, (FP_12 + 4)
.set FP_14, (FP_13 + 4)
.set FP_15, (FP_14 + 4)
.set FP_16, (FP_15 + 4)
.set FP_17, (FP_16 + 4)
.set FP_18, (FP_17 + 4)
.set FP_19, (FP_18 + 4)
.set FP_20, (FP_19 + 4)
.set FP_21, (FP_20 + 4)
.set FP_22, (FP_21 + 4)
.set FP_23, (FP_22 + 4)
.set FP_24, (FP_23 + 4)
.set FP_25, (FP_24 + 4)
.set FP_26, (FP_25 + 4)
.set FP_27, (FP_26 + 4)
.set FP_28, (FP_27 + 4)
.set FP_29, (FP_28 + 4)
.set FP_30, (FP_29 + 4)
.set FP_31, (FP_30 + 4)
.set FP_FPSCR, (FP_31 + 4)
.set IP_LINK, 0
.set IP_0, (IP_LINK + 8)
.set IP_2, (IP_0 + 4)
.set IP_3, (IP_2 + 4)
.set IP_4, (IP_3 + 4)
.set IP_5, (IP_4 + 4)
.set IP_6, (IP_5 + 4)
.set IP_7, (IP_6 + 4)
.set IP_8, (IP_7 + 4)
.set IP_9, (IP_8 + 4)
.set IP_10, (IP_9 + 4)
.set IP_11, (IP_10 + 4)
.set IP_12, (IP_11 + 4)
.set IP_13, (IP_12 + 4)
.set IP_28, (IP_13 + 4)
.set IP_29, (IP_28 + 4)
.set IP_30, (IP_29 + 4)
.set IP_31, (IP_30 + 4)
.set IP_CR, (IP_31 + 4)
.set IP_CTR, (IP_CR + 4)
.set IP_XER, (IP_CTR + 4)
.set IP_LR, (IP_XER + 4)
.set IP_PC, (IP_LR + 4)
.set IP_MSR, (IP_PC + 4)
.set IP_END, (IP_MSR + 16)
BEGIN_CODE
/*
* _CPU_Context_save_fp_context
*
* This routine is responsible for saving the FP context
* at *fp_context_ptr. If the point to load the FP context
* from is changed then the pointer is modified by this routine.
*
* Sometimes a macro implementation of this is in cpu.h which dereferences
* the ** and a similarly named routine in this file is passed something
* like a (Context_Control_fp *). The general rule on making this decision
* is to avoid writing assembly language.
*/
ALIGN (PPC_CACHE_ALIGNMENT, PPC_CACHE_ALIGN_POWER)
PUBLIC_PROC (_CPU_Context_save_fp)
PROC (_CPU_Context_save_fp):
#if (PPC_HAS_FPU == 1)
lwz r3, 0(r3)
stfs f0, FP_0(r3)
stfs f1, FP_1(r3)
stfs f2, FP_2(r3)
stfs f3, FP_3(r3)
stfs f4, FP_4(r3)
stfs f5, FP_5(r3)
stfs f6, FP_6(r3)
stfs f7, FP_7(r3)
stfs f8, FP_8(r3)
stfs f9, FP_9(r3)
stfs f10, FP_10(r3)
stfs f11, FP_11(r3)
stfs f12, FP_12(r3)
stfs f13, FP_13(r3)
stfs f14, FP_14(r3)
stfs f15, FP_15(r3)
stfs f16, FP_16(r3)
stfs f17, FP_17(r3)
stfs f18, FP_18(r3)
stfs f19, FP_19(r3)
stfs f20, FP_20(r3)
stfs f21, FP_21(r3)
stfs f22, FP_22(r3)
stfs f23, FP_23(r3)
stfs f24, FP_24(r3)
stfs f25, FP_25(r3)
stfs f26, FP_26(r3)
stfs f27, FP_27(r3)
stfs f28, FP_28(r3)
stfs f29, FP_29(r3)
stfs f30, FP_30(r3)
stfs f31, FP_31(r3)
mffs f2
stfs f2, FP_FPSCR(r3)
#endif
blr
/*
* _CPU_Context_restore_fp_context
*
* This routine is responsible for restoring the FP context
* at *fp_context_ptr. If the point to load the FP context
* from is changed then the pointer is modified by this routine.
*
* Sometimes a macro implementation of this is in cpu.h which dereferences
* the ** and a similarly named routine in this file is passed something
* like a (Context_Control_fp *). The general rule on making this decision
* is to avoid writing assembly language.
*/
ALIGN (PPC_CACHE_ALIGNMENT, PPC_CACHE_ALIGN_POWER)
PUBLIC_PROC (_CPU_Context_restore_fp)
PROC (_CPU_Context_restore_fp):
#if (PPC_HAS_FPU == 1)
lwz r3, 0(r3)
lfs f2, FP_FPSCR(r3)
mtfsf 255, f2
lfs f0, FP_0(r3)
lfs f1, FP_1(r3)
lfs f2, FP_2(r3)
lfs f3, FP_3(r3)
lfs f4, FP_4(r3)
lfs f5, FP_5(r3)
lfs f6, FP_6(r3)
lfs f7, FP_7(r3)
lfs f8, FP_8(r3)
lfs f9, FP_9(r3)
lfs f10, FP_10(r3)
lfs f11, FP_11(r3)
lfs f12, FP_12(r3)
lfs f13, FP_13(r3)
lfs f14, FP_14(r3)
lfs f15, FP_15(r3)
lfs f16, FP_16(r3)
lfs f17, FP_17(r3)
lfs f18, FP_18(r3)
lfs f19, FP_19(r3)
lfs f20, FP_20(r3)
lfs f21, FP_21(r3)
lfs f22, FP_22(r3)
lfs f23, FP_23(r3)
lfs f24, FP_24(r3)
lfs f25, FP_25(r3)
lfs f26, FP_26(r3)
lfs f27, FP_27(r3)
lfs f28, FP_28(r3)
lfs f29, FP_29(r3)
lfs f30, FP_30(r3)
lfs f31, FP_31(r3)
#endif
blr
/* _CPU_Context_switch
*
* This routine performs a normal non-FP context switch.
*/
ALIGN (PPC_CACHE_ALIGNMENT, PPC_CACHE_ALIGN_POWER)
PUBLIC_PROC (_CPU_Context_switch)
PROC (_CPU_Context_switch):
sync
isync
/* This assumes that all the registers are in the given order */
li r5, 32
addi r3,r3,-4
#if ( PPC_USE_DATA_CACHE )
dcbz r5, r3
#endif
stw r1, GP_1+4(r3)
stw r2, GP_2+4(r3)
#if (PPC_USE_MULTIPLE == 1)
addi r3, r3, GP_18+4
#if ( PPC_USE_DATA_CACHE )
dcbz r5, r3
#endif
stmw r13, GP_13-GP_18(r3)
#else
stw r13, GP_13+4(r3)
stw r14, GP_14+4(r3)
stw r15, GP_15+4(r3)
stw r16, GP_16+4(r3)
stw r17, GP_17+4(r3)
stwu r18, GP_18+4(r3)
#if ( PPC_USE_DATA_CACHE )
dcbz r5, r3
#endif
stw r19, GP_19-GP_18(r3)
stw r20, GP_20-GP_18(r3)
stw r21, GP_21-GP_18(r3)
stw r22, GP_22-GP_18(r3)
stw r23, GP_23-GP_18(r3)
stw r24, GP_24-GP_18(r3)
stw r25, GP_25-GP_18(r3)
stw r26, GP_26-GP_18(r3)
stw r27, GP_27-GP_18(r3)
stw r28, GP_28-GP_18(r3)
stw r29, GP_29-GP_18(r3)
stw r30, GP_30-GP_18(r3)
stw r31, GP_31-GP_18(r3)
#endif
#if ( PPC_USE_DATA_CACHE )
dcbt r0, r4
#endif
mfcr r6
stw r6, GP_CR-GP_18(r3)
mflr r7
stw r7, GP_PC-GP_18(r3)
mfmsr r8
stw r8, GP_MSR-GP_18(r3)
#if ( PPC_USE_DATA_CACHE )
dcbt r5, r4
#endif
lwz r1, GP_1(r4)
lwz r2, GP_2(r4)
#if (PPC_USE_MULTIPLE == 1)
addi r4, r4, GP_19
#if ( PPC_USE_DATA_CACHE )
dcbt r5, r4
#endif
lmw r13, GP_13-GP_19(r4)
#else
lwz r13, GP_13(r4)
lwz r14, GP_14(r4)
lwz r15, GP_15(r4)
lwz r16, GP_16(r4)
lwz r17, GP_17(r4)
lwz r18, GP_18(r4)
lwzu r19, GP_19(r4)
#if ( PPC_USE_DATA_CACHE )
dcbt r5, r4
#endif
lwz r20, GP_20-GP_19(r4)
lwz r21, GP_21-GP_19(r4)
lwz r22, GP_22-GP_19(r4)
lwz r23, GP_23-GP_19(r4)
lwz r24, GP_24-GP_19(r4)
lwz r25, GP_25-GP_19(r4)
lwz r26, GP_26-GP_19(r4)
lwz r27, GP_27-GP_19(r4)
lwz r28, GP_28-GP_19(r4)
lwz r29, GP_29-GP_19(r4)
lwz r30, GP_30-GP_19(r4)
lwz r31, GP_31-GP_19(r4)
#endif
lwz r6, GP_CR-GP_19(r4)
lwz r7, GP_PC-GP_19(r4)
lwz r8, GP_MSR-GP_19(r4)
mtcrf 255, r6
mtlr r7
mtmsr r8
blr
/*
* _CPU_Context_restore
*
* This routine is generallu used only to restart self in an
* efficient manner. It may simply be a label in _CPU_Context_switch.
*
* NOTE: May be unnecessary to reload some registers.
*/
/*
* ACB: Don't worry about cache optimisation here - this is not THAT critical.
*/
ALIGN (PPC_CACHE_ALIGNMENT, PPC_CACHE_ALIGN_POWER)
PUBLIC_PROC (_CPU_Context_restore)
PROC (_CPU_Context_restore):
lwz r5, GP_CR(r3)
lwz r6, GP_PC(r3)
lwz r7, GP_MSR(r3)
mtcrf 255, r5
mtlr r6
mtmsr r7
lwz r1, GP_1(r3)
lwz r2, GP_2(r3)
#if (PPC_USE_MULTIPLE == 1)
lmw r13, GP_13(r3)
#else
lwz r13, GP_13(r3)
lwz r14, GP_14(r3)
lwz r15, GP_15(r3)
lwz r16, GP_16(r3)
lwz r17, GP_17(r3)
lwz r18, GP_18(r3)
lwz r19, GP_19(r3)
lwz r20, GP_20(r3)
lwz r21, GP_21(r3)
lwz r22, GP_22(r3)
lwz r23, GP_23(r3)
lwz r24, GP_24(r3)
lwz r25, GP_25(r3)
lwz r26, GP_26(r3)
lwz r27, GP_27(r3)
lwz r28, GP_28(r3)
lwz r29, GP_29(r3)
lwz r30, GP_30(r3)
lwz r31, GP_31(r3)
#endif
blr
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,83 @@
#
# $Id$
#
@SET_MAKE@
srcdir = @srcdir@
top_srcdir = @top_srcdir@
top_builddir = ../../../../../../..
subdir = c/src/exec/score/cpu/powerpc/wrap
INSTALL = @INSTALL@
RTEMS_ROOT = $(top_srcdir)/@RTEMS_TOPdir@
PROJECT_ROOT = @PROJECT_ROOT@
VPATH = @srcdir@
RELS=../$(ARCH)/rtems-cpu.rel
# C source names, if any, go here -- minus the .c
C_PIECES = cpu ppccache
C_FILES=$(C_PIECES:%=%.c)
C_O_FILES=$(C_PIECES:%=${ARCH}/%.o)
ROOT_H_PIECES =
ROOT_H_FILES=$(ROOT_H_PIECES:%=$(srcdir)/%)
RTEMS_SCORE_H_PIECES=cpu.h
RTEMS_SCORE_H_FILES=$(RTEMS_SCORE_H_PIECES:%=$(srcdir)/%)
H_PIECES=$(ROOT_H_PIECES) $(RTEMS_SCORE_H_PIECES)
H_FILES=$(H_PIECES%=$(srcdir)/%)
I_PIECES= c_isr
I_FILES=$(I_PIECES:%=$(srcdir)/%.inl)
# Assembly source names, if any, go here -- minus the .S
S_PIECES = cpu_asm rtems # irq_stub
S_FILES=$(S_PIECES:%=%.S)
S_O_FILES=$(S_FILES:%.S=${ARCH}/%.o)
SRCS=$(C_FILES) $(CC_FILES) $(H_FILES) $(S_FILES) $(EXTERNAL_H_FILES) $(I_FILES)
OBJS=$(C_O_FILES) $(CC_O_FILES) $(S_O_FILES)
include $(RTEMS_ROOT)/make/custom/${RTEMS_BSP}.cfg
include $(RTEMS_ROOT)/make/leaf.cfg
#
# (OPTIONAL) Add local stuff here using +=
#
DEFINES +=
CPPFLAGS +=
CFLAGS += $(CFLAGS_OS_V)
LD_PATHS +=
LD_LIBS +=
LDFLAGS +=
#
# Add your list of files to delete here. The config files
# already know how to delete some stuff, so you may want
# to just run 'make clean' first to see what gets missed.
# 'make clobber' already includes 'make clean'
#
CLEAN_ADDITIONS +=
CLOBBER_ADDITIONS +=
../$(ARCH)/rtems-cpu.rel: $(OBJS)
test -d ../$(ARCH) || mkdir ../$(ARCH)
$(make-rel)
all: ${ARCH} $(SRCS) preinstall $(OBJS) $(RELS)
# Install the program(s), appending _g or _p as appropriate.
# for include files, just use $(INSTALL_CHANGE)
install: all
preinstall: ${ARCH}
$(INSTALL_CHANGE) -m 444 ${RTEMS_SCORE_H_FILES} ${I_FILES} $(PROJECT_INCLUDE)/rtems/score
$(INSTALL_CHANGE) -m 444 ${ROOT_H_FILES} $(PROJECT_INCLUDE)
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
cd $(top_builddir) \
&& CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
@@ -0,0 +1,4 @@
RTEMS_INLINE_ROUTINE boolean _ISR_Is_in_progress( void )
{
return (_ISR_Nest_level != 0);
}
@@ -41,6 +41,7 @@ extern "C" {
#include <rtems/score/ppc.h> /* pick up machine definitions */
#ifndef ASM
struct CPU_Interrupt_frame;
typedef void ( *ppc_isr_entry )( int, struct CPU_Interrupt_frame * );
#include <rtems/score/ppctypes.h>
#endif
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,73 @@
/* ppctypes.h
*
* This include file contains type definitions pertaining to the PowerPC
* processor family.
*
* Author: Andrew Bray <andy@i-cubed.co.uk>
*
* COPYRIGHT (c) 1995 by i-cubed ltd.
*
* To anyone who acknowledges that this file is provided "AS IS"
* without any express or implied warranty:
* permission to use, copy, modify, and distribute this file
* for any purpose is hereby granted without fee, provided that
* the above copyright notice and this notice appears in all
* copies, and that the name of i-cubed limited not be used in
* advertising or publicity pertaining to distribution of the
* software without specific, written prior permission.
* i-cubed limited makes no representations about the suitability
* of this software for any purpose.
*
* Derived from c/src/exec/cpu/no_cpu/no_cputypes.h:
*
* COPYRIGHT (c) 1989-1997.
* On-Line Applications Research Corporation (OAR).
* Copyright assigned to U.S. Government, 1994.
*
* The license and distribution terms for this file may in
* the file LICENSE in this distribution or at
* http://www.OARcorp.com/rtems/license.html.
*
* $Id$
*/
#ifndef __PPC_TYPES_h
#define __PPC_TYPES_h
#ifndef ASM
#ifdef __cplusplus
extern "C" {
#endif
/*
* This section defines the basic types for this processor.
*/
typedef unsigned char unsigned8; /* unsigned 8-bit integer */
typedef unsigned short unsigned16; /* unsigned 16-bit integer */
typedef unsigned int unsigned32; /* unsigned 32-bit integer */
typedef unsigned long long unsigned64; /* unsigned 64-bit integer */
typedef unsigned32 Priority_Bit_map_control;
typedef signed char signed8; /* 8-bit signed integer */
typedef signed short signed16; /* 16-bit signed integer */
typedef signed int signed32; /* 32-bit signed integer */
typedef signed long long signed64; /* 64 bit signed integer */
typedef unsigned32 boolean; /* Boolean value */
typedef float single_precision; /* single precision float */
typedef double double_precision; /* double precision float */
typedef void ppc_isr;
#ifdef __cplusplus
}
#endif
#endif /* !ASM */
#endif
/* end of include file */
@@ -0,0 +1,73 @@
/* ppctypes.h
*
* This include file contains type definitions pertaining to the PowerPC
* processor family.
*
* Author: Andrew Bray <andy@i-cubed.co.uk>
*
* COPYRIGHT (c) 1995 by i-cubed ltd.
*
* To anyone who acknowledges that this file is provided "AS IS"
* without any express or implied warranty:
* permission to use, copy, modify, and distribute this file
* for any purpose is hereby granted without fee, provided that
* the above copyright notice and this notice appears in all
* copies, and that the name of i-cubed limited not be used in
* advertising or publicity pertaining to distribution of the
* software without specific, written prior permission.
* i-cubed limited makes no representations about the suitability
* of this software for any purpose.
*
* Derived from c/src/exec/cpu/no_cpu/no_cputypes.h:
*
* COPYRIGHT (c) 1989-1997.
* On-Line Applications Research Corporation (OAR).
* Copyright assigned to U.S. Government, 1994.
*
* The license and distribution terms for this file may in
* the file LICENSE in this distribution or at
* http://www.OARcorp.com/rtems/license.html.
*
* $Id$
*/
#ifndef __PPC_TYPES_h
#define __PPC_TYPES_h
#ifndef ASM
#ifdef __cplusplus
extern "C" {
#endif
/*
* This section defines the basic types for this processor.
*/
typedef unsigned char unsigned8; /* unsigned 8-bit integer */
typedef unsigned short unsigned16; /* unsigned 16-bit integer */
typedef unsigned int unsigned32; /* unsigned 32-bit integer */
typedef unsigned long long unsigned64; /* unsigned 64-bit integer */
typedef unsigned32 Priority_Bit_map_control;
typedef signed char signed8; /* 8-bit signed integer */
typedef signed short signed16; /* 16-bit signed integer */
typedef signed int signed32; /* 32-bit signed integer */
typedef signed long long signed64; /* 64 bit signed integer */
typedef unsigned32 boolean; /* Boolean value */
typedef float single_precision; /* single precision float */
typedef double double_precision; /* double precision float */
typedef void ppc_isr;
#ifdef __cplusplus
}
#endif
#endif /* !ASM */
#endif
/* end of include file */
@@ -0,0 +1,77 @@
#
# $Id$
#
@SET_MAKE@
srcdir = @srcdir@
top_srcdir = @top_srcdir@
top_builddir = ../../../../../../..
subdir = c/src/exec/score/cpu/powerpc/shared
INSTALL = @INSTALL@
RTEMS_ROOT = $(top_srcdir)/@RTEMS_TOPdir@
PROJECT_ROOT = @PROJECT_ROOT@
VPATH = @srcdir@
RELS=
# C source names, if any, go here -- minus the .c
C_PIECES =
C_FILES=$(C_PIECES:%=%.c)
C_O_FILES=$(C_PIECES:%=${ARCH}/%.o)
ROOT_H_PIECES = asm.h
ROOT_H_FILES=$(ROOT_H_PIECES:%=$(srcdir)/%)
RTEMS_SCORE_H_PIECES=ppc.h ppctypes.h
RTEMS_SCORE_H_FILES=$(RTEMS_SCORE_H_PIECES:%=$(srcdir)/%)
H_PIECES=$(ROOT_H_PIECES) $(RTEMS_SCORE_H_PIECES)
H_FILES=$(H_PIECES%=$(srcdir)/%)
# Assembly source names, if any, go here -- minus the .S
S_PIECES =
S_FILES=$(S_PIECES:%=%.S)
S_O_FILES=$(S_FILES:%.S=${ARCH}/%.o)
SRCS=$(C_FILES) $(CC_FILES) $(H_FILES) $(S_FILES) $(EXTERNAL_H_FILES)
OBJS=$(C_O_FILES) $(CC_O_FILES) $(S_O_FILES)
include $(RTEMS_ROOT)/make/custom/${RTEMS_BSP}.cfg
include $(RTEMS_ROOT)/make/leaf.cfg
#
# (OPTIONAL) Add local stuff here using +=
#
DEFINES +=
CPPFLAGS +=
CFLAGS += $(CFLAGS_OS_V)
LD_PATHS +=
LD_LIBS +=
LDFLAGS +=
#
# Add your list of files to delete here. The config files
# already know how to delete some stuff, so you may want
# to just run 'make clean' first to see what gets missed.
# 'make clobber' already includes 'make clean'
#
CLEAN_ADDITIONS +=
CLOBBER_ADDITIONS +=
all:$(SRCS) preinstall
# Install the program(s), appending _g or _p as appropriate.
# for include files, just use $(INSTALL_CHANGE)
install: all
preinstall: ${ARCH}
$(INSTALL_CHANGE) -m 444 ${RTEMS_SCORE_H_FILES} $(PROJECT_INCLUDE)/rtems/score
$(INSTALL_CHANGE) -m 444 ${ROOT_H_FILES} $(PROJECT_INCLUDE)
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
cd $(top_builddir) \
&& CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+275
View File
@@ -0,0 +1,275 @@
/* asm.h
*
* This include file attempts to address the problems
* caused by incompatible flavors of assemblers and
* toolsets. It primarily addresses variations in the
* use of leading underscores on symbols and the requirement
* that register names be preceded by a %.
*
*
* NOTE: The spacing in the use of these macros
* is critical to them working as advertised.
*
* COPYRIGHT:
*
* This file is based on similar code found in newlib available
* from ftp.cygnus.com. The file which was used had no copyright
* notice. This file is freely distributable as long as the source
* of the file is noted. This file is:
*
* COPYRIGHT (c) 1995.
* i-cubed ltd.
*
* COPYRIGHT (c) 1994.
* On-Line Applications Research Corporation (OAR).
*
* $Id$
*/
#ifndef __PPC_ASM_h
#define __PPC_ASM_h
/*
* Indicate we are in an assembly file and get the basic CPU definitions.
*/
#ifndef ASM
#define ASM
#endif
#include <rtems/score/targopts.h>
#include <rtems/score/ppc.h>
/*
* Recent versions of GNU cpp define variables which indicate the
* need for underscores and percents. If not using GNU cpp or
* the version does not support this, then you will obviously
* have to define these as appropriate.
*/
#ifndef __USER_LABEL_PREFIX__
#define __USER_LABEL_PREFIX__
#endif
#ifndef __REGISTER_PREFIX__
#define __REGISTER_PREFIX__
#endif
#ifndef __FLOAT_REGISTER_PREFIX__
#define __FLOAT_REGISTER_PREFIX__ __REGISTER_PREFIX__
#endif
#if (PPC_ABI == PPC_ABI_POWEROPEN)
#ifndef __PROC_LABEL_PREFIX__
#define __PROC_LABEL_PREFIX__ .
#endif
#endif
#ifndef __PROC_LABEL_PREFIX__
#define __PROC_LABEL_PREFIX__ __USER_LABEL_PREFIX__
#endif
/* ANSI concatenation macros. */
#define CONCAT1(a, b) CONCAT2(a, b)
#define CONCAT2(a, b) a ## b
/* Use the right prefix for global labels. */
#define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
/* Use the right prefix for procedure labels. */
#define PROC(x) CONCAT1 (__PROC_LABEL_PREFIX__, x)
/* Use the right prefix for registers. */
#define REG(x) CONCAT1 (__REGISTER_PREFIX__, x)
/* Use the right prefix for floating point registers. */
#define FREG(x) CONCAT1 (__FLOAT_REGISTER_PREFIX__, x)
/*
* define macros for all of the registers on this CPU
*
* EXAMPLE: #define d0 REG (d0)
*/
#define r0 REG(0)
#define r1 REG(1)
#define r2 REG(2)
#define r3 REG(3)
#define r4 REG(4)
#define r5 REG(5)
#define r6 REG(6)
#define r7 REG(7)
#define r8 REG(8)
#define r9 REG(9)
#define r10 REG(10)
#define r11 REG(11)
#define r12 REG(12)
#define r13 REG(13)
#define r14 REG(14)
#define r15 REG(15)
#define r16 REG(16)
#define r17 REG(17)
#define r18 REG(18)
#define r19 REG(19)
#define r20 REG(20)
#define r21 REG(21)
#define r22 REG(22)
#define r23 REG(23)
#define r24 REG(24)
#define r25 REG(25)
#define r26 REG(26)
#define r27 REG(27)
#define r28 REG(28)
#define r29 REG(29)
#define r30 REG(30)
#define r31 REG(31)
#define f0 FREG(0)
#define f1 FREG(1)
#define f2 FREG(2)
#define f3 FREG(3)
#define f4 FREG(4)
#define f5 FREG(5)
#define f6 FREG(6)
#define f7 FREG(7)
#define f8 FREG(8)
#define f9 FREG(9)
#define f10 FREG(10)
#define f11 FREG(11)
#define f12 FREG(12)
#define f13 FREG(13)
#define f14 FREG(14)
#define f15 FREG(15)
#define f16 FREG(16)
#define f17 FREG(17)
#define f18 FREG(18)
#define f19 FREG(19)
#define f20 FREG(20)
#define f21 FREG(21)
#define f22 FREG(22)
#define f23 FREG(23)
#define f24 FREG(24)
#define f25 FREG(25)
#define f26 FREG(26)
#define f27 FREG(27)
#define f28 FREG(28)
#define f29 FREG(29)
#define f30 FREG(30)
#define f31 FREG(31)
/*
* Some special purpose registers (SPRs).
*/
#define srr0 0x01a
#define srr1 0x01b
#define srr2 0x3de /* IBM 400 series only */
#define srr3 0x3df /* IBM 400 series only */
#define sprg0 0x110
#define sprg1 0x111
#define sprg2 0x112
#define sprg3 0x113
/* the following SPR/DCR registers exist only in IBM 400 series */
#define dear 0x3d5
#define evpr 0x3d6 /* SPR: exception vector prefix register */
#define iccr 0x3fb /* SPR: instruction cache control reg. */
#define dccr 0x3fa /* SPR: data cache control reg. */
#define exisr 0x040 /* DCR: external interrupt status register */
#define exier 0x042 /* DCR: external interrupt enable register */
#define br0 0x080 /* DCR: memory bank register 0 */
#define br1 0x081 /* DCR: memory bank register 1 */
#define br2 0x082 /* DCR: memory bank register 2 */
#define br3 0x083 /* DCR: memory bank register 3 */
#define br4 0x084 /* DCR: memory bank register 4 */
#define br5 0x085 /* DCR: memory bank register 5 */
#define br6 0x086 /* DCR: memory bank register 6 */
#define br7 0x087 /* DCR: memory bank register 7 */
/* end of IBM400 series register definitions */
/* The following registers are for the MPC8x0 */
#define der 0x095 /* Debug Enable Register */
/* end of MPC8x0 registers */
/*
* Following must be tailor for a particular flavor of the C compiler.
* They may need to put underscores in front of the symbols.
*/
#define PUBLIC_VAR(sym) .globl SYM (sym)
#define EXTERN_VAR(sym) .extern SYM (sym)
#define PUBLIC_PROC(sym) .globl PROC (sym)
#define EXTERN_PROC(sym) .extern PROC (sym)
/* Other potentially assembler specific operations */
#if PPC_ASM == PPC_ASM_ELF
#define ALIGN(n,p) .align p
#define DESCRIPTOR(x) \
.section .descriptors,"aw"; \
PUBLIC_VAR (x); \
SYM (x):; \
.long PROC (x); \
.long s.got; \
.long 0
#define EXT_SYM_REF(x) .long x
#define EXT_PROC_REF(x) .long x
/*
* Define macros to handle section beginning and ends.
*/
#define BEGIN_CODE_DCL .text
#define END_CODE_DCL
#define BEGIN_DATA_DCL .data
#define END_DATA_DCL
#define BEGIN_CODE .text
#define END_CODE
#define BEGIN_DATA .data
#define END_DATA
#define BEGIN_BSS .bss
#define END_BSS
#define END
#elif PPC_ASM == PPC_ASM_XCOFF
#define ALIGN(n,p) .align p
#define DESCRIPTOR(x) \
.csect x[DS]; \
.globl x[DS]; \
.long PROC (x)[PR]; \
.long TOC[tc0]
#define EXT_SYM_REF(x) .long x[RW]
#define EXT_PROC_REF(x) .long x[DS]
/*
* Define macros to handle section beginning and ends.
*/
#define BEGIN_CODE_DCL .csect .text[PR]
#define END_CODE_DCL
#define BEGIN_DATA_DCL .csect .data[RW]
#define END_DATA_DCL
#define BEGIN_CODE .csect .text[PR]
#define END_CODE
#define BEGIN_DATA .csect .data[RW]
#define END_DATA
#define BEGIN_BSS .bss
#define END_BSS
#define END
#else
#error "PPC_ASM_TYPE is not properly defined"
#endif
#ifndef PPC_ASM
#error "PPC_ASM_TYPE is not properly defined"
#endif
#endif
/* end of include file */
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,73 @@
/* ppctypes.h
*
* This include file contains type definitions pertaining to the PowerPC
* processor family.
*
* Author: Andrew Bray <andy@i-cubed.co.uk>
*
* COPYRIGHT (c) 1995 by i-cubed ltd.
*
* To anyone who acknowledges that this file is provided "AS IS"
* without any express or implied warranty:
* permission to use, copy, modify, and distribute this file
* for any purpose is hereby granted without fee, provided that
* the above copyright notice and this notice appears in all
* copies, and that the name of i-cubed limited not be used in
* advertising or publicity pertaining to distribution of the
* software without specific, written prior permission.
* i-cubed limited makes no representations about the suitability
* of this software for any purpose.
*
* Derived from c/src/exec/cpu/no_cpu/no_cputypes.h:
*
* COPYRIGHT (c) 1989-1997.
* On-Line Applications Research Corporation (OAR).
* Copyright assigned to U.S. Government, 1994.
*
* The license and distribution terms for this file may in
* the file LICENSE in this distribution or at
* http://www.OARcorp.com/rtems/license.html.
*
* $Id$
*/
#ifndef __PPC_TYPES_h
#define __PPC_TYPES_h
#ifndef ASM
#ifdef __cplusplus
extern "C" {
#endif
/*
* This section defines the basic types for this processor.
*/
typedef unsigned char unsigned8; /* unsigned 8-bit integer */
typedef unsigned short unsigned16; /* unsigned 16-bit integer */
typedef unsigned int unsigned32; /* unsigned 32-bit integer */
typedef unsigned long long unsigned64; /* unsigned 64-bit integer */
typedef unsigned32 Priority_Bit_map_control;
typedef signed char signed8; /* 8-bit signed integer */
typedef signed short signed16; /* 16-bit signed integer */
typedef signed int signed32; /* 32-bit signed integer */
typedef signed long long signed64; /* 64 bit signed integer */
typedef unsigned32 boolean; /* Boolean value */
typedef float single_precision; /* single precision float */
typedef double double_precision; /* double precision float */
typedef void ppc_isr;
#ifdef __cplusplus
}
#endif
#endif /* !ASM */
#endif
/* end of include file */
+1 -1
View File
@@ -82,7 +82,7 @@ SCORE_EXTERN boolean _ISR_Signals_to_thread_executing;
* When this variable is zero, a thread is executing.
*/
SCORE_EXTERN unsigned32 _ISR_Nest_level;
SCORE_EXTERN volatile unsigned32 _ISR_Nest_level;
/*
* The following declares the Vector Table. Application
@@ -234,7 +234,7 @@ SCORE_EXTERN Context_Control _Thread_BSP_context;
* moments.
*/
SCORE_EXTERN unsigned32 _Thread_Dispatch_disable_level;
SCORE_EXTERN volatile unsigned32 _Thread_Dispatch_disable_level;
/*
* If this is non-zero, then the post-task switch extension
@@ -29,10 +29,19 @@
* directives available to an interrupt service routine are restricted.
*/
#if defined(powerpc)
#define CPU_PROVIDES_ISR_IS_IN_PROGRESS
#endif
#ifndef CPU_PROVIDES_ISR_IS_IN_PROGRESS
RTEMS_INLINE_ROUTINE boolean _ISR_Is_in_progress( void )
{
return (_ISR_Nest_level != 0);
}
#else
#include <rtems/score/c_isr.inl>
#endif
/*PAGE
*
+2 -2
View File
@@ -346,7 +346,7 @@ int BSP_rtems_irq_mngt_set(rtems_irq_global_settings* config)
}
}
/*
* must disable slave pic anyway
* must enable slave pic anyway
*/
BSP_irq_enable_at_i8259s (2);
_CPU_ISR_Enable(level);
@@ -374,6 +374,6 @@ void _ThreadProcessSignalsFromIrq (CPU_Exception_frame* ctx)
}
/*
* I plan to process other thread related events here.
* This will include DEBUG session requsted from keyboard...
* This will include DEBUG session requested from keyboard...
*/
}
+1 -1
View File
@@ -93,7 +93,7 @@ static rtems_irq_prio irqPrioTable[BSP_IRQ_LINES_NUMBER]={
* 255 means all other interrupts are masked
* The second entry has a priority of 255 because
* it is the slave pic entry and is should always remain
* unamsked.
* unmasked.
*/
0,0,
255,
@@ -0,0 +1,20 @@
#
# $Id$
#
@SET_MAKE@
srcdir = @srcdir@
VPATH = @srcdir@
RTEMS_ROOT = @top_srcdir@
PROJECT_ROOT = @PROJECT_ROOT@
include $(RTEMS_ROOT)/make/custom/$(RTEMS_BSP).cfg
include $(RTEMS_ROOT)/make/directory.cfg
SRCS=README
all: $(SRCS)
# wrapup is the one that actually builds and installs the library
# from the individual .rel files built in other directories
SUB_DIRS= console include pci residual openpic irq vectors start startup bootloader wrapup
+48
View File
@@ -0,0 +1,48 @@
#
# $Id$
#
BSP NAME: MCP750
BOARD: MCP750 from motorola
BUS: PCI
CPU FAMILY: ppc
CPU: PowerPC 750
COPROCESSORS: N/A
MODE: 32 bit mode
DEBUG MONITOR: PPCBUG mode
PERIPHERALS
===========
TIMERS: PPC internal Timebase register
RESOLUTION: ???
SERIAL PORTS: simulated via bug
REAL-TIME CLOCK: PPC internal Decrementer register
DMA: none
VIDEO: none
SCSI: none
NETWORKING: DEC21140
DRIVER INFORMATION
==================
CLOCK DRIVER: PPC internal
IOSUPP DRIVER: N/A
SHMSUPP: N/A
TIMER DRIVER: PPC internal
TTY DRIVER: PPC internal
STDIO
=====
PORT: Console port 0
ELECTRICAL: na
BAUD: na
BITS PER CHARACTER: na
PARITY: na
STOP BITS: na
Notes
=====
Based on papyrus bsp which only really supports
the PowerOpen ABI with an ELF assembler.
@@ -0,0 +1,84 @@
#
# $Id:
#
@SET_MAKE@
srcdir = @srcdir@
VPATH = @srcdir@:@srcdir@/../../../shared:@srcdir@/../console
RTEMS_ROOT = @top_srcdir@
PROJECT_ROOT = @PROJECT_ROOT@
# C source names, if any, go here -- minus the .c
C_PIECES=misc pci zlib mm em86 polled_io
C_FILES=$(C_PIECES:%=%.c)
C_O_FILES=$(C_PIECES:%=${ARCH}/%.o)
H_FILES=bootldr.h zlib.h pci.h
# Assembly source names, if any, go here -- minus the .s
S_PIECES=head exception em86real consoleLib
S_FILES=$(S_PIECES:%=%.S)
S_O_FILES=$(S_FILES:%.S=${ARCH}/%.o)
SRCS=$(C_FILES) $(CC_FILES) $(H_FILES) $(S_FILES)
OBJS=$(S_O_FILES) $(C_O_FILES)
include $(RTEMS_ROOT)/make/custom/$(RTEMS_BSP).cfg
include $(RTEMS_ROOT)/make/leaf.cfg
CC_PIECES=
CC_FILES=$(CC_PIECES:%=%.cc)
CC_O_FILES=$(CC_PIECES:%=${ARCH}/%.o)
#
# (OPTIONAL) Add local stuff here using +=
#
DEFINES +=
CPPFLAGS += -D__BOOT__ -DDEBUG
CFLAGS += -msoft-float -mstrict-align -fno-builtin -Wall -mmultiple -mstring \
-O2 -fomit-frame-pointer -mrelocatable -ffixed-r13 \
-mno-sdata -D__BOOT__ -DDEBUG
ASFLAGS += -mrelocatable
LD_PATHS +=
LD_LIBS +=
LDFLAGS +=
IMAGES := rtems.gz
#
# Add your list of files to delete here. The config files
# already know how to delete some stuff, so you may want
# to just run 'make clean' first to see what gets missed.
# 'make clobber' already includes 'make clean'
#
CLEAN_ADDITIONS += bootloader
CLOBBER_ADDITIONS += $(IMAGES)
bootloader : ${OBJS} $(IMAGES) $(BINARY_LOADED) ppcboot.lds
$(LD) -o bootloader $(OBJS) --just-symbols=$(BINARY_LOADED) \
-b binary $(IMAGES) -T @srcdir@/ppcboot.lds \
-Map bootloader.map
rtems.gz: $(BINARY_LOADED)
$(OBJCOPY) $(BINARY_LOADED) rtems -O binary -R .comment -S
gzip -vf9 rtems
rm -f rtems
all: ${ARCH} $(SRCS) ${OBJ}
@@ -0,0 +1,251 @@
/*
* include/asm-ppc/bloader.h -- Include file for bootloader.
*
* Copyright (C) 1998 Gabriel Paubert, paubert@iram.es
*
* 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 _PPC_BOOTLDR_H
#define _PPC_BOOTLDR_H
#ifndef ASM
#include <bsp/residual.h>
#include <bsp/consoleIo.h>
#include "pci.h"
#define abs __builtin_abs
#define PTE_REFD 0x100
#define PTE_CHNG (0x80|PTE_REFD) /* Modified implies referenced */
#define PTE_WTHR 0x040
#define PTE_CINH 0x020
#define PTE_COHER 0x010
#define PTE_GUAR 0x008
#define PTE_RO 0x003
#define PTE_RW 0x002
#define PTE_RAM (PTE_CHNG|PTE_COHER|PTE_RW)
#define PTE_ROM (PTE_REFD|PTE_RO)
#define PTE_IO (PTE_CHNG|PTE_CINH|PTE_GUAR|PTE_RW)
typedef struct {}opaque;
/* The context passed during MMU interrupts. */
typedef struct _ctxt {
u_long lr, ctr;
u_int cr, xer;
u_long nip, msr;
u_long regs[32];
} ctxt;
/* The main structure which is pointed to permanently by r13. Things
* are not separated very well between parts because it would cause
* too much code bloat for such a simple program like the bootloader.
* The code is designed to be compiled with the -m relocatable option and
* tries to minimize the number of relocations/fixups and the number of
* functions who have to access the .got2 sections (this increases the
* size of the prologue in every function).
*/
typedef struct _boot_data {
RESIDUAL *residual;
void *load_address;
void *of_entry;
void *r6, *r7, *r8, *r9, *r10;
u_long cache_lsize;
void *image; /* Where to copy ourselves */
void *stack;
void *mover; /* where to copy codemove to avoid overlays */
u_long o_msr, o_hid0, o_r31;
opaque * mm_private;
const struct pci_config_access_functions * pci_functions;
opaque * pci_private;
struct pci_dev * pci_devices;
opaque * v86_private;
char cmd_line[256];
} boot_data;
register boot_data *bd __asm__("r13");
extern inline int
pcibios_read_config_byte(u_char bus, u_char dev_fn,
u_char where, u_char * val) {
return bd->pci_functions->read_config_byte(bus, dev_fn, where, val);
}
extern inline int
pcibios_read_config_word(u_char bus, u_char dev_fn,
u_char where, u_short * val) {
return bd->pci_functions->read_config_word(bus, dev_fn, where, val);
}
extern inline int
pcibios_read_config_dword(u_char bus, u_char dev_fn,
u_char where, u_int * val) {
return bd->pci_functions->read_config_dword(bus, dev_fn, where, val);
}
extern inline int
pcibios_write_config_byte(u_char bus, u_char dev_fn,
u_char where, u_char val) {
return bd->pci_functions->write_config_byte(bus, dev_fn, where, val);
}
extern inline int
pcibios_write_config_word(u_char bus, u_char dev_fn,
u_char where, u_short val) {
return bd->pci_functions->write_config_word(bus, dev_fn, where, val);
}
extern inline int
pcibios_write_config_dword(u_char bus, u_char dev_fn,
u_char where, u_int val) {
return bd->pci_functions->write_config_dword(bus, dev_fn, where, val);
}
extern inline int
pci_read_config_byte(struct pci_dev *dev, u_char where, u_char * val) {
return bd->pci_functions->read_config_byte(dev->bus->number,
dev->devfn,
where, val);
}
extern inline int
pci_read_config_word(struct pci_dev *dev, u_char where, u_short * val) {
return bd->pci_functions->read_config_word(dev->bus->number,
dev->devfn,
where, val);
}
extern inline int
pci_read_config_dword(struct pci_dev *dev, u_char where, u_int * val) {
return bd->pci_functions->read_config_dword(dev->bus->number,
dev->devfn,
where, val);
}
extern inline int
pci_write_config_byte(struct pci_dev *dev, u_char where, u_char val) {
return bd->pci_functions->write_config_byte(dev->bus->number,
dev->devfn,
where, val);
}
extern inline int
pci_write_config_word(struct pci_dev *dev, u_char where, u_short val) {
return bd->pci_functions->write_config_word(dev->bus->number,
dev->devfn,
where, val);
}
extern inline int
pci_write_config_dword(struct pci_dev *dev, u_char where, u_int val) {
return bd->pci_functions->write_config_dword(dev->bus->number,
dev->devfn,
where, val);
}
/* codemove is like memmove, but it also gets the cache line size
* as 4th parameter to synchronize them. If this last parameter is
* zero, it performs more or less like memmove. No copy is performed if
* source and destination addresses are equal. However the caches
* are synchronized. Note that the size is always rounded up to the
* next mutiple of 4.
*/
extern void * codemove(void *, const void *, size_t, unsigned long);
/* The physical memory allocator allows to align memory by
* powers of 2 given by the lower order bits of flags.
* By default it allocates from higher addresses towrds lower ones,
* setting PA_LOW reverses this behaviour.
*/
#define palloc(size) __palloc(size,0)
#define isa_io_base (bd->io_base)
void * __palloc(u_long, int);
void pfree(void *);
#define PA_LOW 0x100
#define PA_PERM 0x200 /* Not freeable by pfree */
#define PA_SUBALLOC 0x400 /* Allocate for suballocation by salloc */
#define PA_ALIGN_MASK 0x1f
void * valloc(u_long size);
void vfree(void *);
int vmap(void *, u_long, u_long);
void vunmap(void *);
void * salloc(u_long size);
void sfree(void *);
void pci_init(void);
void * memset(void *p, int c, size_t n);
void gunzip(void *, int, unsigned char *, int *);
void print_all_maps(const char *);
void print_hash_table(void);
void MMUon(void);
void MMUoff(void);
void hang(const char *, u_long, ctxt *) __attribute__((noreturn));
int init_v86(void);
void cleanup_v86_mess(void);
void em86_main(struct pci_dev *);
int find_max_mem(struct pci_dev *);
#endif
#ifdef ASM
/* These definitions simplify the ugly declarations necessary for
* GOT definitions.
*/
#define GOT_ENTRY(NAME) .L_ ## NAME = . - .LCTOC1 ; .long NAME
#define GOT(NAME) .L_ ## NAME (r30)
#define START_GOT \
.section ".got2","aw"; \
.LCTOC1 = .+ 0x8000
#define END_GOT \
.text
#define GET_GOT \
bl 1f; \
.text 2; \
0: .long .LCTOC1-1f; \
.text ; \
1: mflr r30; \
lwz r0,0b-1b(r30); \
add r30,r0,r30
#define bd r13
#define cache_lsize 32 /* Offset into bd area */
#define image 36
#define stack 40
#define mover 44
#define o_msr 48
#define o_hid0 52
#define o_r31 56
/* Stack offsets for saved registers on exceptions */
#define save_lr 8(r1)
#define save_ctr 12(r1)
#define save_cr 16(r1)
#define save_xer 20(r1)
#define save_nip 24(r1)
#define save_msr 28(r1)
#define save_r(n) 32+4*n(r1)
#endif
#endif
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,466 @@
/*
* arch/ppc/loader/exceotion.S -- Exception handlers for early boot.
*
* Copyright (C) 1998 Gabriel Paubert, paubert@iram.es
*
* 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 is an improved version of the TLB interrupt handling code from
* the 603e users manual (603eUM.pdf) downloaded from the WWW. All the
* visible bugs have been removed. Note that many have survived in the errata
* to the 603 user manual (603UMer.pdf).
*
* This code also pays particular attention to optimization, takes into
* account the differences between 603 and 603e, single/multiple processor
* systems and tries to order instructions for dual dispatch in many places.
*
* The optimization has been performed along two lines:
* 1) to minimize the number of instruction cache lines needed for the most
* common execution paths (the ones that do not result in an exception).
* 2) then to order the code to maximize the number of dual issue and
* completion opportunities without increasing the number of cache lines
* used in the same cases.
*
* The last goal of this code is to fit inside the address range
* assigned to the interrupt vectors: 192 instructions with fixed
* entry points every 64 instructions.
*
* Some typos have also been corrected and the Power l (lowercase L)
* instructions replaced by lwz without comment.
*
* I have attempted to describe the reasons of the order and of the choice
* of the instructions but the comments may be hard to understand without
* the processor manual.
*
* Note that the fact that the TLB are reloaded by software in theory
* allows tremendous flexibility, for example we could avoid setting the
* reference bit of the PTE which will could actually not be accessed because
* of protection violation by changing a few lines of code. However,
* this would significantly slow down most TLB reload operations, and
* this is the reason for which we try never to make checks which would be
* redundant with hardware and usually indicate a bug in a program.
*
* There are some inconsistencies in the documentation concerning the
* settings of SRR1 bit 15. All recent documentations say now that it is set
* for stores and cleared for loads. Anyway this handler never uses this bit.
*
* A final remark, the rfi instruction seems to implicitly clear the
* MSR<14> (tgpr)bit. The documentation claims that this bit is restored
* from SRR1 by rfi, but the corresponding bit in SRR1 is the LRU way bit.
* Anyway, the only exception which can occur while TGPR is set is a machine
* check which would indicate an unrecoverable problem. Recent documentation
* now says in some place that rfi clears MSR<14>.
*
* TLB software load for 602/603/603e/603ev:
* Specific Instructions:
* tlbld - write the dtlb with the pte in rpa reg
* tlbli - write the itlb with the pte in rpa reg
* Specific SPRs:
* dmiss - address of dstream miss
* imiss - address of istream miss
* hash1 - address primary hash PTEG address
* hash2 - returns secondary hash PTEG address
* iCmp - returns the primary istream compare value
* dCmp - returns the primary dstream compare value
* rpa - the second word of pte used by tlblx
* Other specific resources:
* cr0 saved in 4 high order bits of SRR1,
* SRR1 bit 14 [WAY] selects TLB set to load from LRU algorithm
* gprs r0..r3 shadowed by the setting of MSR bit 14 [TGPR]
* other bits in SRR1 (unused by this handler but see earlier comments)
*
* There are three basic flows corresponding to three vectors:
* 0x1000: Instruction TLB miss,
* 0x1100: Data TLB miss on load,
* 0x1200: Data TLB miss on store or not dirty page
*/
/* define the following if code does not have to run on basic 603 */
/* #define USE_KEY_BIT */
/* define the following for safe multiprocessing */
/* #define MULTIPROCESSING */
/* define the following for mixed endian */
/* #define CHECK_MIXED_ENDIAN */
/* define the following if entries always have the reference bit set */
#define ASSUME_REF_SET
/* Some OS kernels may want to keep a single copy of the dirty bit in a per
* page table. In this case writable pages are always write-protected as long
* as they are clean, and the dirty bit set actually means that the page
* is writable.
*/
#define DIRTY_MEANS_WRITABLE
#include <libcpu/cpu.h>
#include "asm.h"
#include "bootldr.h"
/*
* Instruction TLB miss flow
* Entry at 0x1000 with the following:
* srr0 -> address of instruction that missed
* srr1 -> 0:3=cr0, 13=1 (instruction), 14=lru way, 16:31=saved MSR
* msr<tgpr> -> 1
* iMiss -> ea that missed
* iCmp -> the compare value for the va that missed
* hash1 -> pointer to first hash pteg
* hash2 -> pointer to second hash pteg
*
* Register usage:
* r0 is limit address during search / scratch after
* r1 is pte data / error code for ISI exception when search fails
* r2 is pointer to pte
* r3 is compare value during search / scratch after
*/
/* Binutils or assembler bug ? Declaring the section executable and writable
* generates an error message on the @fixup entries.
*/
.section .exception,"aw"
# .org 0x1000 # instruction TLB miss entry point
.globl tlb_handlers
tlb_handlers:
.type tlb_handlers,@function
#define ISIVec tlb_handlers-0x1000+0x400
#define DSIVec tlb_handlers-0x1000+0x300
mfspr r2,HASH1
lwz r1,0(r2) # Start memory access as soon as possible
mfspr r3,ICMP # to load the cache.
0: la r0,48(r2) # Use explicit loop to avoid using ctr
1: cmpw r1,r3 # In theory the loop is somewhat slower
beq- 2f # than documentation example
cmpw r0,r2 # but we gain from starting cache load
lwzu r1,8(r2) # earlier and using slots between load
bne+ 1b # and comparison for other purposes.
cmpw r1,r3
bne- 4f # Secondary hash check
2: lwz r1,4(r2) # Found: load second word of PTE
mfspr r0,IMISS # get miss address during load delay
#ifdef ASSUME_REF_SET
andi. r3,r1,8 # check for guarded memory
bne- 5f
mtspr RPA,r1
mfsrr1 r3
tlbli r0
#else
/* This is basically the original code from the manual. */
# andi. r3,r1,8 # check for guarded memory
# bne- 5f
# andi. r3,r1,0x100 # check R bit ahead to help folding
/* However there is a better solution: these last three instructions can be
replaced by the following which should cause less pipeline stalls because
both tests are combined and there is a single CR rename buffer */
extlwi r3,r1,6,23 # Keep only RCWIMG in 6 most significant bits.
rlwinm. r3,r3,5,0,27 # Keep only G (in sign) and R and test.
blt- 5f # Negative means guarded, zero R not set.
mfsrr1 r3 # get saved cr0 bits now to dual issue
ori r1,r1,0x100
mtspr RPA,r1
tlbli r0
/* Do not update PTE if R bit already set, this will save one cache line
writeback at a later time, and avoid even more bus traffic in
multiprocessing systems, when several processors access the same PTEGs.
We also hope that the reference bit will be already set. */
bne+ 3f
#ifdef MULTIPROCESSING
srwi r1,r1,8 # get byte 7 of pte
stb r1,+6(r2) # update page table
#else
sth r1,+6(r2) # update page table
#endif
#endif
3: mtcrf 0x80,r3 # restore CR0
rfi # return to executing program
/* The preceding code is 20 to 25 instructions long, which occupies
3 or 4 cache lines. */
4: andi. r0,r3,0x0040 # see if we have done second hash
lis r1,0x4000 # set up error code in case next branch taken
bne- 6f # speculatively issue the following
mfspr r2,HASH2 # get the second pointer
ori r3,r3,0x0040 # change the compare value
lwz r1,0(r2) # load first entry
b 0b # and go back to main loop
/* We are now at 27 to 32 instructions, using 3 or 4 cache lines for all
cases in which the TLB is successfully loaded. */
/* Guarded memory protection violation: synthesize an ISI exception. */
5: lis r1,0x1000 # set srr1<3>=1 to flag guard violation
/* Entry Not Found branches here with r1 correctly set. */
6: mfsrr1 r3
mfmsr r0
insrwi r1,r3,16,16 # build srr1 for ISI exception
mtsrr1 r1 # set srr1
/* It seems few people have realized rlwinm can be used to clear a bit or
a field of contiguous bits in a register by setting mask_begin>mask_end. */
rlwinm r0,r0,0,15,13 # clear the msr<tgpr> bit
mtcrf 0x80, r3 # restore CR0
mtmsr r0 # flip back to the native gprs
isync # Required from 602 doc!
b ISIVec # go to instruction access exception
/* Up to now there are 37 to 42 instructions so at least 20 could be
inserted for complex cases or for statistics recording. */
/*
Data TLB miss on load flow
Entry at 0x1100 with the following:
srr0 -> address of instruction that caused the miss
srr1 -> 0:3=cr0, 13=0 (data), 14=lru way, 15=0, 16:31=saved MSR
msr<tgpr> -> 1
dMiss -> ea that missed
dCmp -> the compare value for the va that missed
hash1 -> pointer to first hash pteg
hash2 -> pointer to second hash pteg
Register usage:
r0 is limit address during search / scratch after
r1 is pte data / error code for DSI exception when search fails
r2 is pointer to pte
r3 is compare value during search / scratch after
*/
.org tlb_handlers+0x100
mfspr r2,HASH1
lwz r1,0(r2) # Start memory access as soon as possible
mfspr r3,DCMP # to load the cache.
0: la r0,48(r2) # Use explicit loop to avoid using ctr
1: cmpw r1,r3 # In theory the loop is somewhat slower
beq- 2f # than documentation example
cmpw r0,r2 # but we gain from starting cache load
lwzu r1,8(r2) # earlier and using slots between load
bne+ 1b # and comparison for other purposes.
cmpw r1,r3
bne- 4f # Secondary hash check
2: lwz r1,4(r2) # Found: load second word of PTE
mfspr r0,DMISS # get miss address during load delay
#ifdef ASSUME_REF_SET
mtspr RPA,r1
mfsrr1 r3
tlbld r0
#else
andi. r3,r1,0x100 # check R bit ahead to help folding
mfsrr1 r3 # get saved cr0 bits now to dual issue
ori r1,r1,0x100
mtspr RPA,r1
tlbld r0
/* Do not update PTE if R bit already set, this will save one cache line
writeback at a later time, and avoid even more bus traffic in
multiprocessing systems, when several processors access the same PTEGs.
We also hope that the reference bit will be already set. */
bne+ 3f
#ifdef MULTIPROCESSING
srwi r1,r1,8 # get byte 7 of pte
stb r1,+6(r2) # update page table
#else
sth r1,+6(r2) # update page table
#endif
#endif
3: mtcrf 0x80,r3 # restore CR0
rfi # return to executing program
/* The preceding code is 18 to 23 instructions long, which occupies
3 cache lines. */
4: andi. r0,r3,0x0040 # see if we have done second hash
lis r1,0x4000 # set up error code in case next branch taken
bne- 9f # speculatively issue the following
mfspr r2,HASH2 # get the second pointer
ori r3,r3,0x0040 # change the compare value
lwz r1,0(r2) # load first entry asap
b 0b # and go back to main loop
/* We are now at 25 to 30 instructions, using 3 or 4 cache lines for all
cases in which the TLB is successfully loaded. */
/*
Data TLB miss on store or not dirty page flow
Entry at 0x1200 with the following:
srr0 -> address of instruction that caused the miss
srr1 -> 0:3=cr0, 13=0 (data), 14=lru way, 15=1, 16:31=saved MSR
msr<tgpr> -> 1
dMiss -> ea that missed
dCmp -> the compare value for the va that missed
hash1 -> pointer to first hash pteg
hash2 -> pointer to second hash pteg
Register usage:
r0 is limit address during search / scratch after
r1 is pte data / error code for DSI exception when search fails
r2 is pointer to pte
r3 is compare value during search / scratch after
*/
.org tlb_handlers+0x200
mfspr r2,HASH1
lwz r1,0(r2) # Start memory access as soon as possible
mfspr r3,DCMP # to load the cache.
0: la r0,48(r2) # Use explicit loop to avoid using ctr
1: cmpw r1,r3 # In theory the loop is somewhat slower
beq- 2f # than documentation example
cmpw r0,r2 # but we gain from starting cache load
lwzu r1,8(r2) # earlier and using slots between load
bne+ 1b # and comparison for other purposes.
cmpw r1,r3
bne- 4f # Secondary hash check
2: lwz r1,4(r2) # Found: load second word of PTE
mfspr r0,DMISS # get miss address during load delay
/* We could simply set the C bit and then rely on hardware to flag protection
violations. This raises the problem that a page which actually has not been
modified may be marked as dirty and violates the OEA model for guaranteed
bit settings (table 5-8 of 603eUM.pdf). This can have harmful consequences
on operating system memory management routines, and play havoc with copy on
write schemes. So the protection check is ABSOLUTELY necessary. */
andi. r3,r1,0x80 # check C bit
beq- 5f # if (C==0) go to check protection
3: mfsrr1 r3 # get the saved cr0 bits
mtspr RPA,r1 # set the pte
tlbld r0 # load the dtlb
mtcrf 0x80,r3 # restore CR0
rfi # return to executing program
/* The preceding code is 20 instructions long, which occupy
3 cache lines. */
4: andi. r0,r3,0x0040 # see if we have done second hash
lis r1,0x4200 # set up error code in case next branch taken
bne- 9f # speculatively issue the following
mfspr r2,HASH2 # get the second pointer
ori r3,r3,0x0040 # change the compare value
lwz r1,0(r2) # load first entry asap
b 0b # and go back to main loop
/* We are now at 27 instructions, using 3 or 4 cache lines for all
cases in which the TLB C bit is already set. */
#ifdef DIRTY_MEANS_WRITABLE
5: lis r1,0x0A00 # protection violation on store
#else
/*
Entry found and C==0: check protection before setting C:
Register usage:
r0 is dMiss register
r1 is PTE entry (to be copied to RPA if success)
r2 is pointer to pte
r3 is trashed
For the 603e, the key bit in SRR1 helps to decide whether there is a
protection violation. However the way the check is done in the manual is
not very efficient. The code shown here works as well for 603 and 603e and
is much more efficient for the 603 and comparable to the manual example
for 603e. This code however has quite a bad structure due to the fact it
has been reordered to speed up the most common cases.
*/
/* The first of the following two instructions could be replaced by
andi. r3,r1,3 but it would compete with cmplwi for cr0 resource. */
5: clrlwi r3,r1,30 # Extract two low order bits
cmplwi r3,2 # Test for PP=10
bne- 7f # assume fallthrough is more frequent
6: ori r1,r1,0x180 # set referenced and changed bit
sth r1,6(r2) # update page table
b 3b # and finish loading TLB
/* We are now at 33 instructions, using 5 cache lines. */
7: bgt- 8f # if PP=11 then DSI protection exception
/* This code only works if key bit is present (602/603e/603ev) */
#ifdef USE_KEY_BIT
mfsrr1 r3 # get the KEY bit and test it
andis. r3,r3,0x0008
beq 6b # default prediction taken, truly better ?
#else
/* This code is for all 602 and 603 family models: */
mfsrr1 r3 # Here the trick is to use the MSR PR bit as a
mfsrin r0,r0 # shift count for an rlwnm. instruction which
extrwi r3,r3,1,17 # extracts and tests the correct key bit from
rlwnm. r3,r0,r3,1,1 # the segment register. RISC they said...
mfspr r0,DMISS # Restore fault address to r0
beq 6b # if 0 load tlb else protection fault
#endif
/* We are now at 40 instructions, (37 if using key bit), using 5 cache
lines in all cases in which the C bit is successfully set */
8: lis r1,0x0A00 # protection violation on store
#endif /* DIRTY_IS_WRITABLE */
/* PTE entry not found branch here with DSISR code in r1 */
9: mfsrr1 r3
mtdsisr r1
clrlwi r2,r3,16 # set up srr1 for DSI exception
mfmsr r0
/* I have some doubts about the usefulness of the xori instruction in
mixed or pure little-endian environment. The address is in the same
doubleword, hence in the same protection domain and performing an exclusive
or with 7 is only valid for byte accesses. */
#ifdef CHECK_MIXED_ENDIAN
andi. r1,r2,1 # test LE bit ahead to help folding
#endif
mtsrr1 r2
rlwinm r0,r0,0,15,13 # clear the msr<tgpr> bit
mfspr r1,DMISS # get miss address
#ifdef CHECK_MIXED_ENDIAN
beq 1f # if little endian then:
xori r1,r1,0x07 # de-mung the data address
1:
#endif
mtdar r1 # put in dar
mtcrf 0x80,r3 # restore CR0
mtmsr r0 # flip back to the native gprs
isync # required from 602 manual
b DSIVec # branch to DSI exception
/* We are now between 50 and 56 instructions. Close to the limit
but should be sufficient in case bugs are found. */
/* Altogether the three handlers occupy 128 instructions in the worst
case, 64 instructions could still be added (non contiguously). */
.org tlb_handlers+0x300
.globl _handler_glue
_handler_glue:
/* Entry code for exceptions: DSI (0x300), ISI(0x400), alignment(0x600) and
* traps(0x700). In theory it is not necessary to save and restore r13 and all
* higher numbered registers, but it is done because it allowed to call the
* firmware (PPCBug) for debugging in the very first stages when writing the
* bootloader.
*/
stwu r1,-160(r1)
stw r0,save_r(0)
mflr r0
stmw r2,save_r(2)
bl 0f
0: mfctr r4
stw r0,save_lr
mflr r9 /* Interrupt vector + few instructions */
la r10,160(r1)
stw r4,save_ctr
mfcr r5
lwz r8,2f-0b(r9)
mfxer r6
stw r5,save_cr
mtctr r8
stw r6,save_xer
mfsrr0 r7
stw r10,save_r(1)
mfsrr1 r8
stw r7,save_nip
la r4,8(r1)
lwz r13,1f-0b(r9)
rlwinm r3,r9,24,0x3f /* Interrupt vector >> 8 */
stw r8,save_msr
bctrl
lwz r7,save_msr
lwz r6,save_nip
mtsrr1 r7
lwz r5,save_xer
mtsrr0 r6
lwz r4,save_ctr
mtxer r5
lwz r3,save_lr
mtctr r4
lwz r0,save_cr
mtlr r3
lmw r2,save_r(2)
mtcr r0
lwz r0,save_r(0)
la r1,160(r1)
rfi
1: .long (__bd)@fixup
2: .long (_handler)@fixup
.section .fixup,"aw"
.align 2
.long 1b, 2b
.previous
@@ -0,0 +1,379 @@
/*
* $Id$
*
* This code is loaded by the ROM loader at some arbitrary location.
* Move it to high memory so that it can load the kernel at 0x0000.
*
*/
#include "bootldr.h"
#include <libcpu/cpu.h>
#include <rtems/score/targopts.h>
#include "asm.h"
#undef TEST_PPCBUG_CALLS
#define FRAME_SIZE 32
#define LOCK_CACHES (HID0_DLOCK|HID0_ILOCK)
#define INVL_CACHES (HID0_DCI|HID0_ICFI)
#define ENBL_CACHES (HID0_DCE|HID0_ICE)
#define USE_PPCBUG
#undef USE_PPCBUG
START_GOT
GOT_ENTRY(_GOT2_TABLE_)
GOT_ENTRY(_FIXUP_TABLE_)
GOT_ENTRY(.bss)
GOT_ENTRY(codemove)
GOT_ENTRY(0)
GOT_ENTRY(__bd)
GOT_ENTRY(moved)
GOT_ENTRY(_binary_rtems_gz_start)
GOT_ENTRY(_binary_initrd_gz_start)
GOT_ENTRY(_binary_initrd_gz_end)
#ifdef TEST_PPCBUG_CALLS
GOT_ENTRY(banner_start)
GOT_ENTRY(banner_end)
#endif
END_GOT
.globl start
.type start,@function
/* Point the stack into the PreP partition header in the x86 reserved
* code area, so that simple C routines can be called.
*/
start: bl 1f
1: mflr r1
li r0,0
stwu r0,start-1b-0x400+0x1b0-FRAME_SIZE(r1)
stmw r26,FRAME_SIZE-24(r1)
GET_GOT
mfmsr r28 /* Turn off interrupts */
ori r0,r28,MSR_EE
xori r0,r0,MSR_EE
mtmsr r0
/* Enable the caches, from now on cr2.eq set means processor is 601 */
mfpvr r0
mfspr r29,HID0
srwi r0,r0,16
cmplwi cr2,r0,1
beq 2,2f
#ifndef USE_PPCBUG
ori r0,r29,ENBL_CACHES|INVL_CACHES|LOCK_CACHES
xori r0,r0,INVL_CACHES|LOCK_CACHES
sync
isync
mtspr HID0,r0
#endif
2: bl reloc
/* save all the parameters and the orginal msr/hid0/r31 */
lwz bd,GOT(__bd)
stw r3,0(bd)
stw r4,4(bd)
stw r5,8(bd)
stw r6,12(bd)
lis r3,__size@sectoff@ha
stw r7,16(bd)
stw r8,20(bd)
addi r3,r3,__size@sectoff@l
stw r9,24(bd)
stw r10,28(bd)
stw r28,o_msr(bd)
stw r29,o_hid0(bd)
stw r31,o_r31(bd)
/* Call the routine to fill boot_data structure from residual data.
* And to find where the code has to be moved.
*/
bl early_setup
/* Now we need to relocate ourselves, where we are told to. First put a
* copy of the codemove routine to some place in memory.
* (which may be where the 0x41 partition was loaded, so size is critical).
*/
lwz r4,GOT(codemove)
li r5,_size_codemove
lwz r3,mover(bd)
lwz r6,cache_lsize(bd)
bl codemove
mtctr r3 # Where the temporary codemove is.
lwz r3,image(bd)
lis r5,_edata@sectoff@ha
lwz r4,GOT(0) # Our own address
addi r5,r5,_edata@sectoff@l
lwz r6,cache_lsize(bd)
lwz r8,GOT(moved)
sub r7,r3,r4 # Difference to adjust pointers.
add r8,r8,r7
add r30,r30,r7
add bd,bd,r7
/* Call the copy routine but return to the new area. */
mtlr r8 # for the return address
bctr # returns to the moved instruction
/* Establish the new top stack frame. */
moved: lwz r1,stack(bd)
li r0,0
stwu r0,-16(r1)
/* relocate again */
bl reloc
/* Clear all of BSS */
lwz r10,GOT(.bss)
li r0,__bss_words@sectoff@l
subi r10,r10,4
cmpwi r0,0
mtctr r0
li r0,0
beq 4f
3: stwu r0,4(r10)
bdnz 3b
/* Final memory initialization. First switch to unmapped mode
* in case the FW had set the MMU on, and flush the TLB to avoid
* stale entries from interfering. No I/O access is allowed
* during this time!
*/
#ifndef USE_PPCBUG
4: bl MMUoff
#endif
bl flush_tlb
/* Some firmware versions leave stale values in the BATs, it's time
* to invalidate them to avoid interferences with our own mappings.
* But the 601 valid bit is in the BATL (IBAT only) and others are in
* the [ID]BATU. Bloat, bloat.. fortunately thrown away later.
*/
li r3,0
beq cr2,5f
mtdbatu 0,r3
mtdbatu 1,r3
mtdbatu 2,r3
mtdbatu 3,r3
5: mtibatu 0,r3
mtibatl 0,r3
mtibatu 1,r3
mtibatl 1,r3
mtibatu 2,r3
mtibatl 2,r3
mtibatu 3,r3
mtibatl 3,r3
lis r3,__size@sectoff@ha
addi r3,r3,__size@sectoff@l
sync # We are going to touch SDR1 !
bl mm_init
bl MMUon
/* Now we are mapped and can perform I/O if we want */
#ifdef TEST_PPCBUG_CALLS
/* Experience seems to show that PPCBug can only be called with the
* data cache disabled and with MMU disabled. Bummer.
*/
li r10,0x22 # .OUTLN
lwz r3,GOT(banner_start)
lwz r4,GOT(banner_end)
sc
#endif
bl setup_hw
lwz r4,GOT(_binary_rtems_gz_start)
lis r5,_rtems_gz_size@sectoff@ha
lwz r6,GOT(_binary_initrd_gz_start)
lis r3,_rtems_size@sectoff@ha
lwz r7,GOT(_binary_initrd_gz_end)
addi r5,r5,_rtems_gz_size@sectoff@l
addi r3,r3,_rtems_size@sectoff@l
sub r7,r7,r6
bl decompress_kernel
/* Back here we are unmapped and we start the kernel, passing up to eight
* parameters just in case, only r3 to r7 used for now. Flush the tlb so
* that the loaded image starts in a clean state.
*/
bl flush_tlb
lwz r3,0(bd)
lwz r4,4(bd)
lwz r5,8(bd)
lwz r6,12(bd)
lwz r7,16(bd)
lwz r8,20(bd)
lwz r9,24(bd)
lwz r10,28(bd)
lwz r30,0(0)
mtctr r30
/*
* Linux code again
lis r30,0xdeadc0de@ha
addi r30,r30,0xdeadc0de@l
stw r30,0(0)
li r30,0
*/
dcbst 0,r30 /* Make sure it's in memory ! */
/* We just flash invalidate and disable the dcache, unless it's a 601,
* critical areas have been flushed and we don't care about the stack
* and other scratch areas.
*/
beq cr2,1f
mfspr r0,HID0
ori r0,r0,HID0_DCI|HID0_DCE
sync
mtspr HID0,r0
xori r0,r0,HID0_DCI|HID0_DCE
mtspr HID0,r0
/* Provisional return to FW, works for PPCBug */
#if 0
1: mfmsr r10
ori r10,r10,MSR_IP
mtmsr r10
li r10,0x63
sc
#else
1: bctr
#endif
/* relocation function, r30 must point to got2+0x8000 */
reloc:
/* Adjust got2 pointers, no need to check for 0, this code already puts
* a few entries in the table.
*/
li r0,__got2_entries@sectoff@l
la r12,GOT(_GOT2_TABLE_)
lwz r11,GOT(_GOT2_TABLE_)
mtctr r0
sub r11,r12,r11
addi r12,r12,-4
1: lwzu r0,4(r12)
add r0,r0,r11
stw r0,0(r12)
bdnz 1b
/* Now adjust the fixups and the pointers to the fixups in case we need
* to move ourselves again.
*/
2: li r0,__fixup_entries@sectoff@l
lwz r12,GOT(_FIXUP_TABLE_)
cmpwi r0,0
mtctr r0
addi r12,r12,-4
beqlr
3: lwzu r10,4(r12)
lwzux r0,r10,r11
add r0,r0,r11
stw r10,0(r12)
stw r0,0(r10)
bdnz 3b
blr
/* Set the MMU on and off: code is always mapped 1:1 and does not need MMU,
* but it does not cost so much to map it also and it catches calls through
* NULL function pointers.
*/
.globl MMUon
.type MMUon,@function
MMUon: mfmsr r0
ori r0,r0,MSR_IR|MSR_DR|MSR_IP
mflr r11
xori r0,r0,MSR_IP
mtsrr0 r11
mtsrr1 r0
rfi
.globl MMUoff
.type MMUoff,@function
MMUoff: mfmsr r0
ori r0,r0,MSR_IR|MSR_DR|MSR_IP
mflr r11
xori r0,r0,MSR_IR|MSR_DR
mtsrr0 r11
mtsrr1 r0
rfi
/* Due to the PPC architecture (and according to the specifications), a
* series of tlbie which goes through a whole 256 MB segment always flushes
* the whole TLB. This is obviously overkill and slow, but who cares ?
* It takes about 1 ms on a 200 MHz 603e and works even if residual data
* get the number of TLB entries wrong.
*/
flush_tlb:
lis r11,0x1000
1: addic. r11,r11,-0x1000
tlbie r11
bnl 1b
/* tlbsync is not implemented on 601, so use sync which seems to be a superset
* of tlbsync in all cases and do not bother with CPU dependant code
*/
sync
blr
/* A few utility functions, some copied from arch/ppc/lib/string.S */
#if 0
.globl strnlen
.type strnlen,@function
strnlen:
addi r4,r4,1
mtctr r4
addi r4,r3,-1
1: lbzu r0,1(r4)
cmpwi 0,r0,0
bdnzf eq,1b
subf r3,r3,r4
blr
#endif
.globl codemove
codemove:
.type codemove,@function
/* r3 dest, r4 src, r5 length in bytes, r6 cachelinesize */
cmplw cr1,r3,r4
addi r0,r5,3
srwi. r0,r0,2
beq cr1,4f /* In place copy is not necessary */
beq 7f /* Protect against 0 count */
mtctr r0
bge cr1,2f
la r8,-4(r4)
la r7,-4(r3)
1: lwzu r0,4(r8)
stwu r0,4(r7)
bdnz 1b
b 4f
2: slwi r0,r0,2
add r8,r4,r0
add r7,r3,r0
3: lwzu r0,-4(r8)
stwu r0,-4(r7)
bdnz 3b
/* Now flush the cache: note that we must start from a cache aligned
* address. Otherwise we might miss one cache line.
*/
4: cmpwi r6,0
add r5,r3,r5
beq 7f /* Always flush prefetch queue in any case */
subi r0,r6,1
andc r3,r3,r0
mr r4,r3
5: cmplw r4,r5
dcbst 0,r4
add r4,r4,r6
blt 5b
sync /* Wait for all dcbst to complete on bus */
mr r4,r3
6: cmplw r4,r5
icbi 0,r4
add r4,r4,r6
blt 6b
7: sync /* Wait for all icbi to complete on bus */
isync
blr
.size codemove,.-codemove
_size_codemove=.-codemove
.section ".data" # .rodata
.align 2
#ifdef TEST_PPCBUG_CALLS
banner_start:
.ascii "This message was printed by PPCBug with MMU enabled"
banner_end:
#endif
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,94 @@
OUTPUT_ARCH(powerpc)
OUTPUT_FORMAT(ppcboot)
/* Do we need any of these for elf?
__DYNAMIC = 0; */
SECTIONS
{
.text :
{
/* We have to build the header by hand, painful since ppcboot
format support is very poor in binutils.
objdump -b ppcboot zImage --all-headers can be used to check. */
/* The following line can be added as a branch to use the same image
* for netboot as for prepboots, the only problem is that objdump
* did not in this case recognize the format since it insisted
* in checking the x86 code area held only zeroes.
*/
LONG(0x48000000+start);
. = 0x1be; BYTE(0x80); BYTE(0)
BYTE(2); BYTE(0); BYTE(0x41); BYTE(1);
BYTE(0x12); BYTE(0x4f); LONG(0);
BYTE(((_edata + 0x1ff)>>9)&0xff);
BYTE(((_edata + 0x1ff)>>17)&0xff);
BYTE(((_edata + 0x1ff)>>25)&0xff);
. = 0x1fe;
BYTE(0x55);
BYTE(0xaa);
BYTE(start&0xff);
BYTE((start>>8)&0xff);
BYTE((start>>16)&0xff);
BYTE((start>>24)&0xff);
BYTE(_edata&0xff);
BYTE((_edata>>8)&0xff);
BYTE((_edata>>16)&0xff);
BYTE((_edata>>24)&0xff);
BYTE(0); /* flags */
BYTE(0); /* os_id */
BYTE(0x4C); BYTE(0x69); BYTE(0x6e);
BYTE(0x75); BYTE(0x78); /* Partition name */
. = 0x400;
*(.text)
*(.sdata2)
*(.rodata)
}
/* . = ALIGN(16); */
.image :
{
rtems.gz(*)
. = ALIGN(4);
*.gz(*)
}
/* Read-write section, merged into data segment: */
/* . = ALIGN(4096); */
.reloc :
{
*(.got)
_GOT2_TABLE_ = .;
*(.got2)
_FIXUP_TABLE_ = .;
*(.fixup)
}
__got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >>2;
__fixup_entries = (. - _FIXUP_TABLE_)>>2;
.handlers :
{
*(.exception)
}
.data :
{
*(.data)
*(.sdata)
. = ALIGN(4);
_edata = .;
}
PROVIDE(_binary_initrd_gz_start = 0);
PROVIDE(_binary_initrd_gz_end = 0);
_rtems_gz_size = _binary_rtems_gz_end - _binary_rtems_gz_start;
_rtems_size = __rtems_end - __rtems_start;
.bss :
{
*(.sbss)
*(.bss)
. = ALIGN(4);
}
__bss_words = SIZEOF(.bss)>>2;
__size = . ;
/DISCARD/ :
{
*(.comment)
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,438 @@
/* $Id$ */
/*
* This file is derived from zlib.h and zconf.h from the zlib-0.95
* distribution by Jean-loup Gailly and Mark Adler, with some additions
* by Paul Mackerras to aid in implementing Deflate compression and
* decompression for PPP packets.
*/
/*
* ==FILEVERSION 960122==
*
* This marker is used by the Linux installation script to determine
* whether an up-to-date version of this file is already installed.
*/
/* zlib.h -- interface of the 'zlib' general purpose compression library
version 0.95, Aug 16th, 1995.
Copyright (C) 1995 Jean-loup Gailly and Mark Adler
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
Jean-loup Gailly Mark Adler
gzip@prep.ai.mit.edu madler@alumni.caltech.edu
*/
#ifndef _ZLIB_H
#define _ZLIB_H
#define local
#ifdef DEBUG_ZLIB
#include <bsp/consoleIo.h>
#define fprintf printk
#endif
/* #include "zconf.h" */ /* included directly here */
/* zconf.h -- configuration of the zlib compression library
* Copyright (C) 1995 Jean-loup Gailly.
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* From: zconf.h,v 1.12 1995/05/03 17:27:12 jloup Exp */
/*
The library does not install any signal handler. It is recommended to
add at least a handler for SIGSEGV when decompressing; the library checks
the consistency of the input data whenever possible but may go nuts
for some forms of corrupted input.
*/
/*
* Compile with -DMAXSEG_64K if the alloc function cannot allocate more
* than 64k bytes at a time (needed on systems with 16-bit int).
* Compile with -DUNALIGNED_OK if it is OK to access shorts or ints
* at addresses which are not a multiple of their size.
* Under DOS, -DFAR=far or -DFAR=__far may be needed.
*/
#ifndef STDC
# if defined(MSDOS) || defined(__STDC__) || defined(__cplusplus)
# define STDC
# endif
#endif
#ifdef __MWERKS__ /* Metrowerks CodeWarrior declares fileno() in unix.h */
# include <unix.h>
#endif
/* Maximum value for memLevel in deflateInit2 */
#ifndef MAX_MEM_LEVEL
# ifdef MAXSEG_64K
# define MAX_MEM_LEVEL 8
# else
# define MAX_MEM_LEVEL 9
# endif
#endif
#ifndef FAR
# define FAR
#endif
/* Maximum value for windowBits in deflateInit2 and inflateInit2 */
#ifndef MAX_WBITS
# define MAX_WBITS 15 /* 32K LZ77 window */
#endif
/* The memory requirements for deflate are (in bytes):
1 << (windowBits+2) + 1 << (memLevel+9)
that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values)
plus a few kilobytes for small objects. For example, if you want to reduce
the default memory requirements from 256K to 128K, compile with
make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
Of course this will generally degrade compression (there's no free lunch).
The memory requirements for inflate are (in bytes) 1 << windowBits
that is, 32K for windowBits=15 (default value) plus a few kilobytes
for small objects.
*/
/* Type declarations */
#ifndef OF /* function prototypes */
# ifdef STDC
# define OF(args) args
# else
# define OF(args) ()
# endif
#endif
typedef unsigned char Byte; /* 8 bits */
typedef unsigned int uInt; /* 16 bits or more */
typedef unsigned long uLong; /* 32 bits or more */
typedef Byte FAR Bytef;
typedef char FAR charf;
typedef int FAR intf;
typedef uInt FAR uIntf;
typedef uLong FAR uLongf;
#ifdef STDC
typedef void FAR *voidpf;
typedef void *voidp;
#else
typedef Byte FAR *voidpf;
typedef Byte *voidp;
#endif
/* end of original zconf.h */
#define ZLIB_VERSION "0.95P"
/*
The 'zlib' compression library provides in-memory compression and
decompression functions, including integrity checks of the uncompressed
data. This version of the library supports only one compression method
(deflation) but other algorithms may be added later and will have the same
stream interface.
For compression the application must provide the output buffer and
may optionally provide the input buffer for optimization. For decompression,
the application must provide the input buffer and may optionally provide
the output buffer for optimization.
Compression can be done in a single step if the buffers are large
enough (for example if an input file is mmap'ed), or can be done by
repeated calls of the compression function. In the latter case, the
application must provide more input and/or consume the output
(providing more output space) before each call.
*/
typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size));
typedef void (*free_func) OF((voidpf opaque, voidpf address, uInt nbytes));
struct internal_state;
typedef struct z_stream_s {
Bytef *next_in; /* next input byte */
uInt avail_in; /* number of bytes available at next_in */
uLong total_in; /* total nb of input bytes read so far */
Bytef *next_out; /* next output byte should be put there */
uInt avail_out; /* remaining free space at next_out */
uLong total_out; /* total nb of bytes output so far */
char *msg; /* last error message, NULL if no error */
struct internal_state FAR *state; /* not visible by applications */
alloc_func zalloc; /* used to allocate the internal state */
free_func zfree; /* used to free the internal state */
voidp opaque; /* private data object passed to zalloc and zfree */
Byte data_type; /* best guess about the data type: ascii or binary */
} z_stream;
/*
The application must update next_in and avail_in when avail_in has
dropped to zero. It must update next_out and avail_out when avail_out
has dropped to zero. The application must initialize zalloc, zfree and
opaque before calling the init function. All other fields are set by the
compression library and must not be updated by the application.
The opaque value provided by the application will be passed as the first
parameter for calls of zalloc and zfree. This can be useful for custom
memory management. The compression library attaches no meaning to the
opaque value.
zalloc must return Z_NULL if there is not enough memory for the object.
On 16-bit systems, the functions zalloc and zfree must be able to allocate
exactly 65536 bytes, but will not be required to allocate more than this
if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS,
pointers returned by zalloc for objects of exactly 65536 bytes *must*
have their offset normalized to zero. The default allocation function
provided by this library ensures this (see zutil.c). To reduce memory
requirements and avoid any allocation of 64K objects, at the expense of
compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h).
The fields total_in and total_out can be used for statistics or
progress reports. After compression, total_in holds the total size of
the uncompressed data and may be saved for use in the decompressor
(particularly if the decompressor wants to decompress everything in
a single step).
*/
/* constants */
#define Z_NO_FLUSH 0
#define Z_PARTIAL_FLUSH 1
#define Z_FULL_FLUSH 2
#define Z_SYNC_FLUSH 3 /* experimental: partial_flush + byte align */
#define Z_FINISH 4
#define Z_PACKET_FLUSH 5
/* See deflate() below for the usage of these constants */
#define Z_OK 0
#define Z_STREAM_END 1
#define Z_ERRNO (-1)
#define Z_STREAM_ERROR (-2)
#define Z_DATA_ERROR (-3)
#define Z_MEM_ERROR (-4)
#define Z_BUF_ERROR (-5)
/* error codes for the compression/decompression functions */
#define Z_BEST_SPEED 1
#define Z_BEST_COMPRESSION 9
#define Z_DEFAULT_COMPRESSION (-1)
/* compression levels */
#define Z_FILTERED 1
#define Z_HUFFMAN_ONLY 2
#define Z_DEFAULT_STRATEGY 0
#define Z_BINARY 0
#define Z_ASCII 1
#define Z_UNKNOWN 2
/* Used to set the data_type field */
#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */
extern char *zlib_version;
/* The application can compare zlib_version and ZLIB_VERSION for consistency.
If the first character differs, the library code actually used is
not compatible with the zlib.h header file used by the application.
*/
/* basic functions */
extern int inflateInit OF((z_stream *strm));
/*
Initializes the internal stream state for decompression. The fields
zalloc and zfree must be initialized before by the caller. If zalloc and
zfree are set to Z_NULL, inflateInit updates them to use default allocation
functions.
inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not
enough memory. msg is set to null if there is no error message.
inflateInit does not perform any decompression: this will be done by
inflate().
*/
extern int inflate OF((z_stream *strm, int flush));
/*
Performs one or both of the following actions:
- Decompress more input starting at next_in and update next_in and avail_in
accordingly. If not all input can be processed (because there is not
enough room in the output buffer), next_in is updated and processing
will resume at this point for the next call of inflate().
- Provide more output starting at next_out and update next_out and avail_out
accordingly. inflate() always provides as much output as possible
(until there is no more input data or no more space in the output buffer).
Before the call of inflate(), the application should ensure that at least
one of the actions is possible, by providing more input and/or consuming
more output, and updating the next_* and avail_* values accordingly.
The application can consume the uncompressed output when it wants, for
example when the output buffer is full (avail_out == 0), or after each
call of inflate().
If the parameter flush is set to Z_PARTIAL_FLUSH or Z_PACKET_FLUSH,
inflate flushes as much output as possible to the output buffer. The
flushing behavior of inflate is not specified for values of the flush
parameter other than Z_PARTIAL_FLUSH, Z_PACKET_FLUSH or Z_FINISH, but the
current implementation actually flushes as much output as possible
anyway. For Z_PACKET_FLUSH, inflate checks that once all the input data
has been consumed, it is expecting to see the length field of a stored
block; if not, it returns Z_DATA_ERROR.
inflate() should normally be called until it returns Z_STREAM_END or an
error. However if all decompression is to be performed in a single step
(a single call of inflate), the parameter flush should be set to
Z_FINISH. In this case all pending input is processed and all pending
output is flushed; avail_out must be large enough to hold all the
uncompressed data. (The size of the uncompressed data may have been saved
by the compressor for this purpose.) The next operation on this stream must
be inflateEnd to deallocate the decompression state. The use of Z_FINISH
is never required, but can be used to inform inflate that a faster routine
may be used for the single inflate() call.
inflate() returns Z_OK if some progress has been made (more input
processed or more output produced), Z_STREAM_END if the end of the
compressed data has been reached and all uncompressed output has been
produced, Z_DATA_ERROR if the input data was corrupted, Z_STREAM_ERROR if
the stream structure was inconsistent (for example if next_in or next_out
was NULL), Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if no
progress is possible or if there was not enough room in the output buffer
when Z_FINISH is used. In the Z_DATA_ERROR case, the application may then
call inflateSync to look for a good compression block. */
extern int inflateEnd OF((z_stream *strm));
/*
All dynamically allocated data structures for this stream are freed.
This function discards any unprocessed input and does not flush any
pending output.
inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state
was inconsistent. In the error case, msg may be set but then points to a
static string (which must not be deallocated).
*/
/* advanced functions */
extern int inflateInit2 OF((z_stream *strm,
int windowBits));
/*
This is another version of inflateInit with more compression options. The
fields next_out, zalloc and zfree must be initialized before by the caller.
The windowBits parameter is the base two logarithm of the maximum window
size (the size of the history buffer). It should be in the range 8..15 for
this version of the library (the value 16 will be allowed soon). The
default value is 15 if inflateInit is used instead. If a compressed stream
with a larger window size is given as input, inflate() will return with
the error code Z_DATA_ERROR instead of trying to allocate a larger window.
If next_out is not null, the library will use this buffer for the history
buffer; the buffer must either be large enough to hold the entire output
data, or have at least 1<<windowBits bytes. If next_out is null, the
library will allocate its own buffer (and leave next_out null). next_in
need not be provided here but must be provided by the application for the
next call of inflate().
If the history buffer is provided by the application, next_out must
never be changed by the application since the decompressor maintains
history information inside this buffer from call to call; the application
can only reset next_out to the beginning of the history buffer when
avail_out is zero and all output has been consumed.
inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was
not enough memory, Z_STREAM_ERROR if a parameter is invalid (such as
windowBits < 8). msg is set to null if there is no error message.
inflateInit2 does not perform any decompression: this will be done by
inflate().
*/
extern int inflateSync OF((z_stream *strm));
/*
Skips invalid compressed data until the special marker (see deflate()
above) can be found, or until all available input is skipped. No output
is provided.
inflateSync returns Z_OK if the special marker has been found, Z_BUF_ERROR
if no more input was provided, Z_DATA_ERROR if no marker has been found,
or Z_STREAM_ERROR if the stream structure was inconsistent. In the success
case, the application may save the current current value of total_in which
indicates where valid compressed data was found. In the error case, the
application may repeatedly call inflateSync, providing more input each time,
until success or end of the input data.
*/
extern int inflateReset OF((z_stream *strm));
/*
This function is equivalent to inflateEnd followed by inflateInit,
but does not free and reallocate all the internal decompression state.
The stream will keep attributes that may have been set by inflateInit2.
inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
stream state was inconsistent (such as zalloc or state being NULL).
*/
extern int inflateIncomp OF((z_stream *strm));
/*
This function adds the data at next_in (avail_in bytes) to the output
history without performing any output. There must be no pending output,
and the decompressor must be expecting to see the start of a block.
Calling this function is equivalent to decompressing a stored block
containing the data at next_in (except that the data is not output).
*/
/* checksum functions */
/*
This function is not related to compression but is exported
anyway because it might be useful in applications using the
compression library.
*/
extern uLong adler32 OF((uLong adler, Bytef *buf, uInt len));
/*
Update a running Adler-32 checksum with the bytes buf[0..len-1] and
return the updated checksum. If buf is NULL, this function returns
the required initial value for the checksum.
An Adler-32 checksum is almost as reliable as a CRC32 but can be computed
much faster. Usage example:
uLong adler = adler32(0L, Z_NULL, 0);
while (read_buffer(buffer, length) != EOF) {
adler = adler32(adler, buffer, length);
}
if (adler != original_adler) error();
*/
#ifndef _Z_UTIL_H
struct internal_state {int dummy;}; /* hack for buggy compilers */
#endif
#endif /* _ZLIB_H */
+23
View File
@@ -0,0 +1,23 @@
%rename cpp old_cpp
%rename lib old_lib
%rename endfile old_endfile
%rename startfile old_startfile
%rename link old_link
*cpp:
%(old_cpp) %{qrtems: -D__embedded__} -Asystem(embedded)
*lib:
%{!qrtems: %(old_lib)} %{qrtems: --start-group \
%{!qrtems_debug: -lrtemsall} %{qrtems_debug: -lrtemsall_g} \
-lc -lgcc --end-group ecrtn%O%s \
%{!qnolinkcmds: -T linkcmds%s}}
*startfile:
%{!qrtems: %(old_startfile)} %{qrtems: ecrti%O%s \
%{!qrtems_debug: start.o%s} \
%{qrtems_debug: start_g.o%s}}
*link:
%{!qrtems: %(old_link)} %{qrtems: -Qy -dp -Bstatic -T linkcmds%s -e __rtems_entry_point -u __vectors}
@@ -0,0 +1,63 @@
#
# $Id:
#
@SET_MAKE@
srcdir = @srcdir@
VPATH = @srcdir@:@srcdir@/../../../shared
RTEMS_ROOT = @top_srcdir@
PROJECT_ROOT = @PROJECT_ROOT@
INSTALL = @INSTALL@
# C source names, if any, go here -- minus the .c
C_PIECES=polled_io uart console inch
C_FILES=$(C_PIECES:%=%.c)
C_O_FILES=$(C_PIECES:%=${ARCH}/%.o)
H_FILES=$(srcdir)/consoleIo.h $(srcdir)/keyboard.h $(srcdir)/uart.h
# Assembly source names, if any, go here -- minus the .s
S_PIECES=
S_FILES=$(S_PIECES:%=%.S)
S_O_FILES=$(S_FILES:%.S=${ARCH}/%.o)
SRCS=$(C_FILES) $(CC_FILES) $(H_FILES) $(S_FILES)
OBJS=$(S_O_FILES) $(C_O_FILES)
include $(RTEMS_ROOT)/make/custom/$(RTEMS_BSP).cfg
include $(RTEMS_ROOT)/make/leaf.cfg
CC_PIECES=
CC_FILES=$(CC_PIECES:%=%.cc)
CC_O_FILES=$(CC_PIECES:%=${ARCH}/%.o)
#
# (OPTIONAL) Add local stuff here using +=
#
CPPFLAGS += -DSTATIC_LOG_ALLOC
#
# Add your list of files to delete here. The config files
# already know how to delete some stuff, so you may want
# to just run 'make clean' first to see what gets missed.
# 'make clobber' already includes 'make clean'
#
preinstall:
$(MKDIR) $(PROJECT_INCLUDE)/bsp
$(INSTALL_CHANGE) -m 444 $(H_FILES) $(PROJECT_INCLUDE)/bsp
all: ${ARCH} $(SRCS) preinstall ${OBJS}
@@ -0,0 +1,398 @@
/*-------------------------------------------------------------------------+
| console.c v1.1 - PC386 BSP - 1997/08/07
+--------------------------------------------------------------------------+
| This file contains the PC386 console I/O package.
+--------------------------------------------------------------------------+
| (C) Copyright 1997 -
| - NavIST Group - Real-Time Distributed Systems and Industrial Automation
|
| http://pandora.ist.utl.pt
|
| Instituto Superior Tecnico * Lisboa * PORTUGAL
+--------------------------------------------------------------------------+
| Disclaimer:
|
| This file is provided "AS IS" without warranty of any kind, either
| expressed or implied.
+--------------------------------------------------------------------------+
| This code is based on:
| console.c,v 1.4 1995/12/19 20:07:23 joel Exp - go32 BSP
| With the following copyright notice:
| **************************************************************************
| * COPYRIGHT (c) 1989-1998.
| * On-Line Applications Research Corporation (OAR).
| * Copyright assigned to U.S. Government, 1994.
| *
| * The license and distribution terms for this file may be
| * found in found in the file LICENSE in this distribution or at
| * http://www.OARcorp.com/rtems/license.html.
| **************************************************************************
|
| $Id$
+--------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#undef __assert
void __assert (const char *file, int line, const char *msg);
#include <bsp.h>
#include <bsp/irq.h>
#include <rtems/libio.h>
#include <termios.h>
#include <bsp/uart.h>
#include <bsp/consoleIo.h>
/* Definitions for BSPConsolePort */
#define BSP_CONSOLE_PORT_CONSOLE (-1)
#define BSP_CONSOLE_PORT_COM1 (BSP_UART_COM1)
#define BSP_CONSOLE_PORT_COM2 (BSP_UART_COM2)
/*
* Possible value for console input/output :
* BSP_CONSOLE_PORT_CONSOLE
* BSP_UART_COM1
* BSP_UART_COM2
*/
int BSPConsolePort = BSP_UART_COM1;
/* int BSPConsolePort = BSP_UART_COM2; */
int BSPBaseBaud = 115200;
/*-------------------------------------------------------------------------+
| External Prototypes
+--------------------------------------------------------------------------*/
static int conSetAttr(int minor, const struct termios *);
static void isr_on(const rtems_irq_connect_data *);
static void isr_off(const rtems_irq_connect_data *);
static int isr_is_on(const rtems_irq_connect_data *);
static rtems_irq_connect_data console_isr_data = {BSP_ISA_UART_COM1_IRQ,
BSP_uart_termios_isr_com1,
isr_on,
isr_off,
isr_is_on};
static void
isr_on(const rtems_irq_connect_data *unused)
{
return;
}
static void
isr_off(const rtems_irq_connect_data *unused)
{
return;
}
static int
isr_is_on(const rtems_irq_connect_data *irq)
{
return BSP_irq_enabled_at_i8259s(irq->name);
}
void console_reserve_resources(rtems_configuration_table *conf)
{
if(BSPConsolePort != BSP_CONSOLE_PORT_CONSOLE)
{
rtems_termios_reserve_resources(conf, 1);
}
return;
}
void __assert (const char *file, int line, const char *msg)
{
static char exit_msg[] = "EXECUTIVE SHUTDOWN! Any key to reboot...";
unsigned char ch;
/*
* Note we cannot call exit or printf from here,
* assert can fail inside ISR too
*/
/*
* Close console
*/
close(2);
close(1);
close(0);
printk("\nassert failed: %s: ", file);
printk("%d: ", line);
printk("%s\n\n", msg);
printk(exit_msg);
ch = debug_getc();
printk("\n\n");
rtemsReboot();
}
/*-------------------------------------------------------------------------+
| Console device driver INITIALIZE entry point.
+--------------------------------------------------------------------------+
| Initilizes the I/O console (keyboard + VGA display) driver.
+--------------------------------------------------------------------------*/
rtems_device_driver
console_initialize(rtems_device_major_number major,
rtems_device_minor_number minor,
void *arg)
{
rtems_status_code status;
/*
* The video was initialized in the start.s code and does not need
* to be reinitialized.
*/
/*
* Set up TERMIOS
*/
rtems_termios_initialize ();
/*
* Do device-specific initialization
*/
/* 9600-8-N-1 */
BSP_uart_init(BSPConsolePort, 9600, 0);
/* Set interrupt handler */
if(BSPConsolePort == BSP_UART_COM1)
{
console_isr_data.name = BSP_ISA_UART_COM1_IRQ;
console_isr_data.hdl = BSP_uart_termios_isr_com1;
}
else
{
assert(BSPConsolePort == BSP_UART_COM2);
console_isr_data.name = BSP_ISA_UART_COM2_IRQ;
console_isr_data.hdl = BSP_uart_termios_isr_com2;
}
status = BSP_install_rtems_irq_handler(&console_isr_data);
if (!status){
printk("Error installing serial console interrupt handler!\n");
rtems_fatal_error_occurred(status);
}
/*
* Register the device
*/
status = rtems_io_register_name ("/dev/console", major, 0);
if (status != RTEMS_SUCCESSFUL)
{
printk("Error registering console device!\n");
rtems_fatal_error_occurred (status);
}
if(BSPConsolePort == BSP_UART_COM1)
{
printk("Initialized console on port COM1 9600-8-N-1\n\n");
}
else
{
printk("Initialized console on port COM2 9600-8-N-1\n\n");
}
return RTEMS_SUCCESSFUL;
} /* console_initialize */
static int console_open_count = 0;
static int console_last_close(int major, int minor, void *arg)
{
BSP_remove_rtems_irq_handler (&console_isr_data);
return 0;
}
/*-------------------------------------------------------------------------+
| Console device driver OPEN entry point
+--------------------------------------------------------------------------*/
rtems_device_driver
console_open(rtems_device_major_number major,
rtems_device_minor_number minor,
void *arg)
{
rtems_status_code status;
static rtems_termios_callbacks cb =
{
NULL, /* firstOpen */
console_last_close, /* lastClose */
NULL, /* pollRead */
BSP_uart_termios_write_com1, /* write */
conSetAttr, /* setAttributes */
NULL, /* stopRemoteTx */
NULL, /* startRemoteTx */
1 /* outputUsesInterrupts */
};
if(BSPConsolePort == BSP_UART_COM2)
{
cb.write = BSP_uart_termios_write_com2;
}
status = rtems_termios_open (major, minor, arg, &cb);
if(status != RTEMS_SUCCESSFUL)
{
printk("Error openning console device\n");
return status;
}
/*
* Pass data area info down to driver
*/
BSP_uart_termios_set(BSPConsolePort,
((rtems_libio_open_close_args_t *)arg)->iop->data1);
/* Enable interrupts on channel */
BSP_uart_intr_ctrl(BSPConsolePort, BSP_UART_INTR_CTRL_TERMIOS);
return RTEMS_SUCCESSFUL;
}
/*-------------------------------------------------------------------------+
| Console device driver CLOSE entry point
+--------------------------------------------------------------------------*/
rtems_device_driver
console_close(rtems_device_major_number major,
rtems_device_minor_number minor,
void *arg)
{
rtems_device_driver res = RTEMS_SUCCESSFUL;
res = rtems_termios_close (arg);
return res;
} /* console_close */
/*-------------------------------------------------------------------------+
| Console device driver READ entry point.
+--------------------------------------------------------------------------+
| Read characters from the I/O console. We only have stdin.
+--------------------------------------------------------------------------*/
rtems_device_driver
console_read(rtems_device_major_number major,
rtems_device_minor_number minor,
void *arg)
{
rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *)arg;
char *buffer = rw_args->buffer;
int count, maximum = rw_args->count;
return rtems_termios_read (arg);
} /* console_read */
/*-------------------------------------------------------------------------+
| Console device driver WRITE entry point.
+--------------------------------------------------------------------------+
| Write characters to the I/O console. Stderr and stdout are the same.
+--------------------------------------------------------------------------*/
rtems_device_driver
console_write(rtems_device_major_number major,
rtems_device_minor_number minor,
void * arg)
{
rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *)arg;
char *buffer = rw_args->buffer;
int count, maximum = rw_args->count;
return rtems_termios_write (arg);
} /* console_write */
/*
* Handle ioctl request.
*/
rtems_device_driver
console_control(rtems_device_major_number major,
rtems_device_minor_number minor,
void * arg
)
{
return rtems_termios_ioctl (arg);
}
static int
conSetAttr(int minor, const struct termios *t)
{
int baud;
switch (t->c_cflag & CBAUD)
{
case B50:
baud = 50;
break;
case B75:
baud = 75;
break;
case B110:
baud = 110;
break;
case B134:
baud = 134;
break;
case B150:
baud = 150;
break;
case B200:
baud = 200;
break;
case B300:
baud = 300;
break;
case B600:
baud = 600;
break;
case B1200:
baud = 1200;
break;
case B1800:
baud = 1800;
break;
case B2400:
baud = 2400;
break;
case B4800:
baud = 4800;
break;
case B9600:
baud = 9600;
break;
case B19200:
baud = 19200;
break;
case B38400:
baud = 38400;
break;
case B57600:
baud = 57600;
break;
case B115200:
baud = 115200;
break;
default:
baud = 0;
rtems_fatal_error_occurred (RTEMS_INTERNAL_ERROR);
return 0;
}
BSP_uart_set_baud(BSPConsolePort, baud);
return 0;
}
@@ -0,0 +1,33 @@
#ifndef __CONSOLE_IO_H
#define __CONSOLE_IO_H
typedef enum {
CONSOLE_LOG = 1,
CONSOLE_SERIAL = 2,
CONSOLE_VGA = 3,
CONSOLE_VACUUM = 4
}ioType;
typedef volatile unsigned char * __io_ptr;
typedef struct {
__io_ptr io_base;
__io_ptr isa_mem_base;
__io_ptr pci_mmio_base;
__io_ptr pci_dma_offset;
} board_memory_map;
extern board_memory_map *ptr_mem_map;
extern unsigned long ticks_per_ms;
extern int select_console(ioType t);
extern int printk(const char *, ...) __attribute__((format(printf, 1, 2)));
extern void udelay(int);
extern void debug_putc(const unsigned char c);
extern int debug_getc(void);
extern int debug_tstc(void);
int kbdreset(void);
#endif

Some files were not shown because too many files have changed in this diff Show More