forked from Imagelibrary/rtems
powerpc/haleakala: Add network driver
close 1405
This commit is contained in:
committed by
Joel Sherrill
parent
ed4c5568c7
commit
502609c80d
@@ -7,6 +7,7 @@ include_bspdir = $(includedir)/bsp
|
|||||||
dist_project_lib_DATA = bsp_specs
|
dist_project_lib_DATA = bsp_specs
|
||||||
|
|
||||||
include_HEADERS = include/bsp.h
|
include_HEADERS = include/bsp.h
|
||||||
|
include_HEADERS += include/mmu_405.h
|
||||||
include_HEADERS += ../../shared/include/tm27.h
|
include_HEADERS += ../../shared/include/tm27.h
|
||||||
|
|
||||||
nodist_include_HEADERS = include/bspopts.h
|
nodist_include_HEADERS = include/bspopts.h
|
||||||
@@ -30,7 +31,7 @@ libbsp_a_SOURCES += ../../shared/bspclean.c ../../shared/bsplibc.c \
|
|||||||
startup/bspstart.c ../../shared/bootcard.c \
|
startup/bspstart.c ../../shared/bootcard.c \
|
||||||
../../shared/bsppredriverhook.c ../../shared/bspgetworkarea.c \
|
../../shared/bsppredriverhook.c ../../shared/bspgetworkarea.c \
|
||||||
../../shared/bsppretaskinghook.c ../../shared/sbrk.c \
|
../../shared/bsppretaskinghook.c ../../shared/sbrk.c \
|
||||||
../../shared/gnatinstallhandler.c
|
../../shared/gnatinstallhandler.c mmu/mmu_405.c mmu/mmu_405asm.S
|
||||||
|
|
||||||
# dlentry
|
# dlentry
|
||||||
libbsp_a_SOURCES += dlentry/dlentry.S
|
libbsp_a_SOURCES += dlentry/dlentry.S
|
||||||
@@ -47,6 +48,14 @@ include_bsp_HEADERS += irq/irq.h \
|
|||||||
# irq
|
# irq
|
||||||
libbsp_a_SOURCES += irq/irq_init.c irq/irq.c
|
libbsp_a_SOURCES += irq/irq_init.c irq/irq.c
|
||||||
|
|
||||||
|
if HAS_NETWORKING
|
||||||
|
network_CPPFLAGS = -D__INSIDE_RTEMS_BSD_TCPIP_STACK__
|
||||||
|
noinst_PROGRAMS = network.rel
|
||||||
|
network_rel_SOURCES = network/network.c
|
||||||
|
network_rel_CPPFLAGS = $(AM_CPPFLAGS) $(network_CPPFLAGS)
|
||||||
|
network_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
|
||||||
|
endif
|
||||||
|
|
||||||
libbsp_a_LIBADD = ../../../libcpu/@RTEMS_CPU@/@exceptions@/rtems-cpu.rel \
|
libbsp_a_LIBADD = ../../../libcpu/@RTEMS_CPU@/@exceptions@/rtems-cpu.rel \
|
||||||
../../../libcpu/@RTEMS_CPU@/@exceptions@/exc_bspsupport.rel \
|
../../../libcpu/@RTEMS_CPU@/@exceptions@/exc_bspsupport.rel \
|
||||||
../../../libcpu/@RTEMS_CPU@/@exceptions@/irq_bspsupport.rel \
|
../../../libcpu/@RTEMS_CPU@/@exceptions@/irq_bspsupport.rel \
|
||||||
@@ -55,5 +64,9 @@ libbsp_a_LIBADD = ../../../libcpu/@RTEMS_CPU@/@exceptions@/rtems-cpu.rel \
|
|||||||
../../../libcpu/@RTEMS_CPU@/ppc403/clock.rel \
|
../../../libcpu/@RTEMS_CPU@/ppc403/clock.rel \
|
||||||
../../../libcpu/@RTEMS_CPU@/ppc403/timer.rel
|
../../../libcpu/@RTEMS_CPU@/ppc403/timer.rel
|
||||||
|
|
||||||
|
if HAS_NETWORKING
|
||||||
|
libbsp_a_LIBADD += network.rel
|
||||||
|
endif
|
||||||
|
|
||||||
include $(srcdir)/preinstall.am
|
include $(srcdir)/preinstall.am
|
||||||
include $(top_srcdir)/../../../../automake/local.am
|
include $(top_srcdir)/../../../../automake/local.am
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ RTEMS_CANONICALIZE_TOOLS
|
|||||||
RTEMS_PROG_CCAS
|
RTEMS_PROG_CCAS
|
||||||
|
|
||||||
RTEMS_CHECK_NETWORKING
|
RTEMS_CHECK_NETWORKING
|
||||||
|
|
||||||
AM_CONDITIONAL(HAS_NETWORKING,test "$HAS_NETWORKING" = "yes")
|
AM_CONDITIONAL(HAS_NETWORKING,test "$HAS_NETWORKING" = "yes")
|
||||||
|
|
||||||
RTEMS_BSPOPTS_SET([PPC_USE_SPRG],[*],[1])
|
RTEMS_BSPOPTS_SET([PPC_USE_SPRG],[*],[1])
|
||||||
|
|||||||
77
c/src/lib/libbsp/powerpc/haleakala/include/mmu_405.h
Normal file
77
c/src/lib/libbsp/powerpc/haleakala/include/mmu_405.h
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
#ifndef _mmu_405_h
|
||||||
|
#define _mmu_405_h
|
||||||
|
|
||||||
|
/*
|
||||||
|
Simple interface to the PowerPC 405 MMU
|
||||||
|
|
||||||
|
The intention here is just to allow the MMU to be used to define cacheability and
|
||||||
|
read/write/execute permissions in a simple enough way to fit entirely into the
|
||||||
|
64-entry TLB cache.
|
||||||
|
|
||||||
|
This code does not do address relocation and does not generate any MMU-related interrupts.
|
||||||
|
|
||||||
|
The process ID support is there for a possible future extension where RTEMS supports
|
||||||
|
setting the process ID on task switches, which allows per-process stack protection
|
||||||
|
|
||||||
|
This code will call fatal_error() if your add_space() calls overrun the 64 entries
|
||||||
|
|
||||||
|
Michael Hamel ADInstruments 2008
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "stdint.h"
|
||||||
|
|
||||||
|
enum {
|
||||||
|
kAllProcessIDs = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef enum MMUAccessType {
|
||||||
|
executable,
|
||||||
|
readOnlyData,
|
||||||
|
readOnlyNoCache,
|
||||||
|
readWriteData,
|
||||||
|
readWriteNoCache,
|
||||||
|
readWriteExecutable
|
||||||
|
} MMUAccessType;
|
||||||
|
|
||||||
|
/* Initialise and clear the MMU */
|
||||||
|
void mmu_initialise();
|
||||||
|
|
||||||
|
/* Turn on/off data access translation */
|
||||||
|
bool mmu_enable_data(bool enable);
|
||||||
|
|
||||||
|
/* Turn on instruction translation */
|
||||||
|
bool mmu_enable_code(bool enable);
|
||||||
|
|
||||||
|
/* Define properties for an area of memory (must be 1K-aligned) */
|
||||||
|
void mmu_add_space(uint32_t startAddr, uint32_t endAddr, MMUAccessType permissions, uint8_t processID);
|
||||||
|
|
||||||
|
/* Delete a memory property definition */
|
||||||
|
void mmu_remove_space(uint32_t startAddr, uint32_t endAddr);
|
||||||
|
|
||||||
|
/* Return number of TLB entries out of total in use */
|
||||||
|
int mmu_get_tlb_count();
|
||||||
|
|
||||||
|
/* Allocate a new process ID and return it */
|
||||||
|
uint8_t mmu_new_processID();
|
||||||
|
|
||||||
|
/* Free a process ID that has been in use */
|
||||||
|
void mmu_free_processID(uint8_t freeThis);
|
||||||
|
|
||||||
|
/* Return the current process ID */
|
||||||
|
uint8_t mmu_current_processID();
|
||||||
|
|
||||||
|
/* Change the process ID to ID and return the old value */
|
||||||
|
uint8_t mmu_set_processID(uint8_t toID);
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif //_mmu_405.h
|
||||||
281
c/src/lib/libbsp/powerpc/haleakala/mmu/mmu_405.c
Normal file
281
c/src/lib/libbsp/powerpc/haleakala/mmu/mmu_405.c
Normal file
@@ -0,0 +1,281 @@
|
|||||||
|
/*
|
||||||
|
* Simple interface to the PowerPC 405 MMU
|
||||||
|
*
|
||||||
|
* Michael Hamel ADInstruments 2008
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <bsp.h>
|
||||||
|
#include <libcpu/powerpc-utility.h>
|
||||||
|
#include "mmu_405.h"
|
||||||
|
|
||||||
|
/* #define qLogTLB */
|
||||||
|
/* #define qLogTLBDetails */
|
||||||
|
|
||||||
|
|
||||||
|
/*--------------------------------- TLB handling ------------------------------------- */
|
||||||
|
/* The following are in assembler in mmu_405asm.S */
|
||||||
|
extern void MMU_GetTLBEntry(uint8_t index, uint32_t* tagword, uint32_t* dataword, uint8_t* pid);
|
||||||
|
extern void MMU_SetTLBEntry(uint8_t index, uint32_t hiword, uint32_t loword, uint8_t pid);
|
||||||
|
extern void MMU_ClearTLBs();
|
||||||
|
extern int16_t MMU_FindTLBEntry(uint32_t address);
|
||||||
|
|
||||||
|
|
||||||
|
enum { kNTLBs = 64 }; /* for 403GCX and 405 */
|
||||||
|
|
||||||
|
static bool sFreeTLBs[kNTLBs];
|
||||||
|
static uint8_t sLastIndex = 0;
|
||||||
|
static int sNInUse = 0;
|
||||||
|
|
||||||
|
static void MMUFault(const char* what)
|
||||||
|
/* Used for all setup faults; these can't really be ignored */
|
||||||
|
{
|
||||||
|
printk("\n>>>MMU fatal error %s\n",what);
|
||||||
|
rtems_fatal_error_occurred(RTEMS_INTERNAL_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t AllocTLB()
|
||||||
|
{
|
||||||
|
uint8_t index;
|
||||||
|
|
||||||
|
index = sLastIndex;
|
||||||
|
do {
|
||||||
|
index++;
|
||||||
|
if (index == kNTLBs)
|
||||||
|
index = 0;
|
||||||
|
if (index == sLastIndex)
|
||||||
|
MMUFault("TLB table full");
|
||||||
|
} while (! sFreeTLBs[index]);
|
||||||
|
sFreeTLBs[index] = false;
|
||||||
|
sLastIndex = index;
|
||||||
|
sNInUse++;
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void FreeTLB(uint8_t index)
|
||||||
|
{
|
||||||
|
MMU_SetTLBEntry(index,0,0,0);
|
||||||
|
sFreeTLBs[index] = true;
|
||||||
|
sLastIndex = index-1;
|
||||||
|
sNInUse--;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*---------------------------- MMU operations ---------------------------------- */
|
||||||
|
|
||||||
|
int DataMissException(BSP_Exception_frame *f, unsigned int vector);
|
||||||
|
int InstructionMissException(BSP_Exception_frame *f, unsigned int vector);
|
||||||
|
int InstructionFetchException(BSP_Exception_frame *f, unsigned int vector);
|
||||||
|
|
||||||
|
void
|
||||||
|
mmu_initialise()
|
||||||
|
/* Clear the TLBs and set up exception handlers for the MMU miss handlers */
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
MMU_ClearTLBs();
|
||||||
|
for (i=0; i<kNTLBs; i++) {
|
||||||
|
sFreeTLBs[i] = true;
|
||||||
|
MMU_SetTLBEntry(i,0,0,0xFF);
|
||||||
|
}
|
||||||
|
ppc_exc_set_handler(ASM_ISI_VECTOR ,InstructionFetchException);
|
||||||
|
ppc_exc_set_handler(ASM_BOOKE_ITLBMISS_VECTOR ,DataMissException);
|
||||||
|
ppc_exc_set_handler(ASM_BOOKE_DTLBMISS_VECTOR ,InstructionMissException);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
MakeTLBEntries(uint32_t startAt, uint32_t nBytes, bool EX, bool WR, bool I, uint8_t PID)
|
||||||
|
{
|
||||||
|
uint32_t mask, options, tagWord, dataWord;
|
||||||
|
uint8_t index, sizeCode, pid;
|
||||||
|
|
||||||
|
if ((startAt & 0x3FF) != 0)
|
||||||
|
MMUFault("TLB entry not on 1K boundary");
|
||||||
|
if ((nBytes & 0x3FF) != 0)
|
||||||
|
MMUFault("TLB size not on 1K boundary");
|
||||||
|
|
||||||
|
options = 0;
|
||||||
|
if (EX) options += 0x200;
|
||||||
|
if (WR) options += 0x100;
|
||||||
|
if (I) options += 5;
|
||||||
|
|
||||||
|
#ifdef qLogTLB
|
||||||
|
printk("TLB: make entries for $%X bytes from $%X..$%X PID %d",nBytes, startAt, startAt+nBytes-1, PID);
|
||||||
|
if (EX) printk(" EX");
|
||||||
|
if (WR) printk(" WR");
|
||||||
|
if (I) printk(" I");
|
||||||
|
printk("\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
while (nBytes > 0) {
|
||||||
|
/* Find the largest block we can base on this address */
|
||||||
|
mask = 0x3FF;
|
||||||
|
sizeCode = 0;
|
||||||
|
while (mask < nBytes && ((startAt & mask)==0) && sizeCode < 8) {
|
||||||
|
mask = (mask<<2) + 3;
|
||||||
|
sizeCode++;
|
||||||
|
}
|
||||||
|
mask >>= 2;
|
||||||
|
sizeCode--;
|
||||||
|
|
||||||
|
/* Make a TLB entry describing this, ZSEL=0 */
|
||||||
|
tagWord = startAt | (sizeCode<<7) | 0x40;
|
||||||
|
dataWord = startAt | options;
|
||||||
|
index = AllocTLB();
|
||||||
|
MMU_SetTLBEntry( index , tagWord, dataWord, PID);
|
||||||
|
|
||||||
|
{
|
||||||
|
/* Paranoia: check that we can read that back... */
|
||||||
|
uint8_t tdex, oldpid;
|
||||||
|
|
||||||
|
oldpid = mmu_current_processID();
|
||||||
|
mmu_set_processID(PID);
|
||||||
|
tdex = MMU_FindTLBEntry(startAt);
|
||||||
|
mmu_set_processID(oldpid);
|
||||||
|
|
||||||
|
if (tdex != index) {
|
||||||
|
printk(" Add TLB %d: At %X for $%X sizecode %d tagWord $%X ",index, startAt, mask+1,sizeCode,tagWord);
|
||||||
|
printk(" -- find failed, %d/%d!\n",tdex,index);
|
||||||
|
MMU_GetTLBEntry(index, &tagWord, &dataWord, &pid);
|
||||||
|
printk(" -- reads back $%X : $%X, PID %d\n",tagWord,dataWord,pid);
|
||||||
|
} else {
|
||||||
|
#ifdef qLogTLBDetails
|
||||||
|
printk(" Add TLB %d: At %X for $%X sizecode %d tagWord $%X\n",index, startAt, mask+1,sizeCode,tagWord);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Subtract block from startAddr and nBytes */
|
||||||
|
mask++; /* Convert to a byte count */
|
||||||
|
startAt += mask;
|
||||||
|
nBytes -= mask;
|
||||||
|
}
|
||||||
|
#ifdef qLogTLB
|
||||||
|
printk(" %d in use\n",sNInUse);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
mmu_remove_space(uint32_t startAt, uint32_t endAt)
|
||||||
|
{
|
||||||
|
int16_t index;
|
||||||
|
int32_t size;
|
||||||
|
uint32_t tagword, dataword, nBytes;
|
||||||
|
uint8_t pid, sCode;
|
||||||
|
|
||||||
|
nBytes = endAt - startAt;
|
||||||
|
|
||||||
|
#ifdef qLogTLB
|
||||||
|
printk("TLB: delete entries for $%X bytes from $%X\n",nBytes,startAt);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
while (nBytes > 0) {
|
||||||
|
index = MMU_FindTLBEntry( (uint32_t)startAt );
|
||||||
|
size = 1024;
|
||||||
|
if (index >= 0) {
|
||||||
|
MMU_GetTLBEntry(index, &tagword, &dataword, &pid);
|
||||||
|
if ((tagword & 0x40) == 0)
|
||||||
|
MMUFault("Undefine failed: redundant entries?");
|
||||||
|
if ((tagword & 0xFFFFFC00) != (uint32_t)startAt)
|
||||||
|
MMUFault("Undefine not on TLB boundary");
|
||||||
|
FreeTLB(index);
|
||||||
|
sCode = (tagword >> 7) & 7;
|
||||||
|
while (sCode > 0) {
|
||||||
|
size <<= 2;
|
||||||
|
sCode--;
|
||||||
|
}
|
||||||
|
#ifdef qLogTLBDetails
|
||||||
|
printk(" Free TLB %d: At %X for $%X\n",index, startAt, size);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
startAt += size;
|
||||||
|
nBytes -= size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
mmu_add_space(uint32_t startAddr, uint32_t endAddr, MMUAccessType permissions, uint8_t processID)
|
||||||
|
/* Convert accesstype to write-enable, executable, and cache-inhibit bits */
|
||||||
|
{
|
||||||
|
bool EX, WR, I;
|
||||||
|
|
||||||
|
EX = false;
|
||||||
|
WR = false;
|
||||||
|
I = false;
|
||||||
|
switch (permissions) {
|
||||||
|
case executable : EX = true; break;
|
||||||
|
case readOnlyData : break;
|
||||||
|
case readOnlyNoCache : I = true; break;
|
||||||
|
case readWriteData : WR = true; break;
|
||||||
|
case readWriteNoCache : WR = true; I= true; break;
|
||||||
|
case readWriteExecutable: WR = true; EX = true; break;
|
||||||
|
}
|
||||||
|
MakeTLBEntries( (uint32_t)startAddr, (uint32_t)(endAddr-startAddr+1), EX, WR, I, processID);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
mmu_get_tlb_count()
|
||||||
|
{
|
||||||
|
return sNInUse;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------- CPU process ID handling ----------------------------------
|
||||||
|
* Really dumb system where we just hand out sequential numbers and eventually fail
|
||||||
|
* As long as we only use 8-9 processes this isn't a problem */
|
||||||
|
|
||||||
|
static uint8_t sNextPID = 1;
|
||||||
|
|
||||||
|
#define SPR_PID 0x3B1
|
||||||
|
|
||||||
|
uint8_t mmu_new_processID()
|
||||||
|
{
|
||||||
|
return sNextPID++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mmu_free_processID(uint8_t freeThis)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t mmu_current_processID()
|
||||||
|
{
|
||||||
|
return PPC_SPECIAL_PURPOSE_REGISTER(SPR_PID);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t mmu_set_processID(uint8_t newID)
|
||||||
|
{
|
||||||
|
uint8_t prev = mmu_current_processID();
|
||||||
|
PPC_SET_SPECIAL_PURPOSE_REGISTER(SPR_PID,newID);
|
||||||
|
return prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ------------------ Fault handlers ------------------ */
|
||||||
|
|
||||||
|
#define SPR_ESR 0x3D4
|
||||||
|
#define SPR_DEAR 0x3D5
|
||||||
|
|
||||||
|
enum { kESR_DST = 0x00800000 };
|
||||||
|
|
||||||
|
int DataMissException(BSP_Exception_frame *f, unsigned int vector)
|
||||||
|
{
|
||||||
|
uint32_t addr, excSyn;
|
||||||
|
|
||||||
|
addr = PPC_SPECIAL_PURPOSE_REGISTER(SPR_DEAR);
|
||||||
|
excSyn = PPC_SPECIAL_PURPOSE_REGISTER(SPR_ESR);
|
||||||
|
if (excSyn & kESR_DST) printk("\n---Data write to $%X attempted at $%X\n",addr,f->EXC_SRR0);
|
||||||
|
else printk("\n---Data read from $%X attempted at $%X\n",addr,f->EXC_SRR0);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int InstructionMissException(BSP_Exception_frame *f, unsigned int vector)
|
||||||
|
{
|
||||||
|
printk("\n---Instruction fetch attempted from $%X, no TLB exists\n",f->EXC_SRR0);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int InstructionFetchException(BSP_Exception_frame *f, unsigned int vector)
|
||||||
|
{
|
||||||
|
printk("\n---Instruction fetch attempted from $%X, TLB is no-execute\n",f->EXC_SRR0);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
83
c/src/lib/libbsp/powerpc/haleakala/mmu/mmu_405asm.S
Normal file
83
c/src/lib/libbsp/powerpc/haleakala/mmu/mmu_405asm.S
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Low-level interface to the PPC405 MMU
|
||||||
|
|
||||||
|
M.Hamel ADInstruments 2008
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <rtems/asm.h>
|
||||||
|
|
||||||
|
/* Useful MMU SPR values */
|
||||||
|
|
||||||
|
#define SPR_ZPR 0x3B0
|
||||||
|
#define SPR_PID 0x3B1
|
||||||
|
|
||||||
|
.text
|
||||||
|
|
||||||
|
/* void MMU_ClearTLBs(); */
|
||||||
|
PUBLIC_VAR(MMU_ClearTLBs)
|
||||||
|
SYM (MMU_ClearTLBs):
|
||||||
|
tlbia
|
||||||
|
isync
|
||||||
|
lis r3,0x5555 // *** Gratuitous fiddle of ZPR to 0101010101 to take it out of
|
||||||
|
mtspr SPR_ZPR,r3 // the picture
|
||||||
|
blr
|
||||||
|
|
||||||
|
/* void MMU_SetTLBEntry(UInt8 index, UInt32 tagword, UInt32 dataword, UInt8 SPR_PID) */
|
||||||
|
PUBLIC_VAR(MMU_SetTLBEntry)
|
||||||
|
SYM (MMU_SetTLBEntry):
|
||||||
|
mfspr r7,SPR_PID // Save the current SPR_PID
|
||||||
|
mtspr SPR_PID,r6 // Write to SPR_PID
|
||||||
|
tlbwehi r4,r3 // Write hiword
|
||||||
|
mtspr SPR_PID,r7 // Restore the SPR_PID
|
||||||
|
tlbwelo r5,r3 // Write loword
|
||||||
|
isync
|
||||||
|
blr
|
||||||
|
|
||||||
|
/* void MMU_GetTLBEntry(UInt8 index, UInt32& tagword, UInt32& dataword, UInt8& SPR_PID) */
|
||||||
|
PUBLIC_VAR(MMU_GetTLBEntry)
|
||||||
|
SYM (MMU_GetTLBEntry):
|
||||||
|
mfspr r7,SPR_PID // Save the current SPR_PID
|
||||||
|
tlbrehi r8,r3 // Read hiword & SPR_PID
|
||||||
|
mfspr r9,SPR_PID // Copy the SPR_PID
|
||||||
|
mtspr SPR_PID,r7 // Restore original SPR_PID so we can proceed
|
||||||
|
stw r8,0(r4) // Write to r4 pointer
|
||||||
|
stb r9,0(r6) // Write to r6 pointer
|
||||||
|
tlbrelo r8,r3 // Read loword
|
||||||
|
stw r8,0(r5) // Write to r5 pointer
|
||||||
|
blr
|
||||||
|
|
||||||
|
/* SInt16 MMU_FindTLBEntry(UInt32 address) */
|
||||||
|
/* Returns index of covering TLB entry (0..63), or -1 if there isn't one */
|
||||||
|
PUBLIC_VAR(MMU_FindTLBEntry)
|
||||||
|
SYM (MMU_FindTLBEntry):
|
||||||
|
tlbsx. r3,0,r3
|
||||||
|
beqlr
|
||||||
|
li r3,0xFFFFFFFF
|
||||||
|
blr
|
||||||
|
|
||||||
|
/* bool mmu_enable_code(bool enable); */
|
||||||
|
PUBLIC_VAR(mmu_enable_code)
|
||||||
|
SYM (mmu_enable_code):
|
||||||
|
li r5,0x20 // IR bit
|
||||||
|
b msrbits
|
||||||
|
|
||||||
|
/* bool mmu_enable_data(bool enable); */
|
||||||
|
PUBLIC_VAR(mmu_enable_data)
|
||||||
|
SYM (mmu_enable_data):
|
||||||
|
li r5,0x10 // DR bit
|
||||||
|
msrbits: cmpwi r3,0 // Common code: parameter 0?
|
||||||
|
mfmsr r4 // r4 = MSR state
|
||||||
|
beq clrBit
|
||||||
|
or r6,r4,r5 // If 1, r6 = MSR with bit set
|
||||||
|
b setmsr
|
||||||
|
clrBit: andc r6,r4,r5 // If 0 r6 = MSR with bit clear
|
||||||
|
setmsr: mtmsr r6 // Write new MSR
|
||||||
|
and. r3,r4,r5 // Result = old MSR bit
|
||||||
|
beqlr // If zero return zero
|
||||||
|
li r3,0xFF // If nonzero return byte -1
|
||||||
|
blr
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
1243
c/src/lib/libbsp/powerpc/haleakala/network/network.c
Normal file
1243
c/src/lib/libbsp/powerpc/haleakala/network/network.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -41,6 +41,10 @@ $(PROJECT_INCLUDE)/bsp.h: include/bsp.h $(PROJECT_INCLUDE)/$(dirstamp)
|
|||||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp.h
|
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp.h
|
||||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp.h
|
PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp.h
|
||||||
|
|
||||||
|
$(PROJECT_INCLUDE)/mmu_405.h: include/mmu_405.h $(PROJECT_INCLUDE)/$(dirstamp)
|
||||||
|
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/mmu_405.h
|
||||||
|
PREINSTALL_FILES += $(PROJECT_INCLUDE)/mmu_405.h
|
||||||
|
|
||||||
$(PROJECT_INCLUDE)/tm27.h: ../../shared/include/tm27.h $(PROJECT_INCLUDE)/$(dirstamp)
|
$(PROJECT_INCLUDE)/tm27.h: ../../shared/include/tm27.h $(PROJECT_INCLUDE)/$(dirstamp)
|
||||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/tm27.h
|
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/tm27.h
|
||||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/tm27.h
|
PREINSTALL_FILES += $(PROJECT_INCLUDE)/tm27.h
|
||||||
|
|||||||
@@ -78,59 +78,86 @@ enum {
|
|||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
SDR0_PINSTP = 0x40,
|
||||||
SDR0_UART0 = 0x120,
|
SDR0_UART0 = 0x120,
|
||||||
SDR0_UART1 = 0x121,
|
SDR0_UART1 = 0x121,
|
||||||
SDR0_C405 = 0x180,
|
SDR0_C405 = 0x180,
|
||||||
|
SDR0_SRST0 = 0x200,
|
||||||
SDR0_MALTBL = 0x280,
|
SDR0_MALTBL = 0x280,
|
||||||
SDR0_MALRBL = 0x2A0,
|
SDR0_MALRBL = 0x2A0,
|
||||||
SDR0_MALTBS = 0x2C0,
|
SDR0_MALTBS = 0x2C0,
|
||||||
SDR0_MALRBS = 0x2E0
|
SDR0_MALRBS = 0x2E0,
|
||||||
|
SDR0_PFC2 = 0x4102,
|
||||||
|
SDR0_MFR = 0x4300,
|
||||||
|
SDR0_EMAC0RXST = 0x4301,
|
||||||
|
SDR0_HSF = 0x4400
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
CPR0_CLKUPD = 0x20,
|
||||||
|
CPR0_PLLC = 0x40,
|
||||||
|
CPR0_PLLD = 0x60,
|
||||||
|
CPR0_CPUD = 0x80,
|
||||||
|
CPR0_PLBD = 0xA0,
|
||||||
|
CPR0_OPBD = 0xC0,
|
||||||
|
CPR0_PERD = 0xE0,
|
||||||
|
CPR0_AHBD = 0x100,
|
||||||
|
CPR0_ICFG = 0x140
|
||||||
|
};
|
||||||
|
|
||||||
/* Memory-mapped registers */
|
/* Memory-mapped registers */
|
||||||
|
|
||||||
|
|
||||||
/*======================= Ethernet =================== */
|
/*======================= Ethernet =================== */
|
||||||
|
|
||||||
|
|
||||||
typedef struct EthernetRegisters_EX {
|
|
||||||
uint32_t mode0;
|
|
||||||
uint32_t mode1;
|
|
||||||
uint32_t xmtMode0;
|
|
||||||
uint32_t xmtMode1;
|
|
||||||
uint32_t rcvMode;
|
|
||||||
uint32_t intStatus;
|
|
||||||
uint32_t intEnable;
|
|
||||||
uint32_t addrHi;
|
|
||||||
uint32_t addrLo;
|
|
||||||
uint32_t VLANTPID;
|
|
||||||
uint32_t VLANTCI;
|
|
||||||
uint32_t pauseTimer;
|
|
||||||
uint32_t multicastAddr[2];
|
|
||||||
uint32_t multicastMask[2];
|
|
||||||
uint32_t unused[4];
|
|
||||||
uint32_t lastSrcLo;
|
|
||||||
uint32_t lastSrcHi;
|
|
||||||
uint32_t IPGap;
|
|
||||||
uint32_t STAcontrol;
|
|
||||||
uint32_t xmtReqThreshold;
|
|
||||||
uint32_t rcvWatermark;
|
|
||||||
uint32_t bytesXmtd;
|
|
||||||
uint32_t bytesRcvd;
|
|
||||||
uint32_t unused2;
|
|
||||||
uint32_t revID;
|
|
||||||
uint32_t unused3[2];
|
|
||||||
uint32_t indivHash[8];
|
|
||||||
uint32_t groupHash[8];
|
|
||||||
uint32_t xmtPause;
|
|
||||||
} EthernetRegisters_EX;
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
EMAC0Address = 0xEF600900,
|
EMAC0EXAddress = 0xEF600900,
|
||||||
EMAC1Address = 0xEF600A00
|
EMAC1EXAddress = 0xEF600A00,
|
||||||
};
|
|
||||||
|
/* 405EX-specific bits in EMAC_MR1 */
|
||||||
|
keEMAC1000Mbps = 0x00800000,
|
||||||
|
keEMAC16KRxFIFO = 0x00280000,
|
||||||
|
keEMAC8KRxFIFO = 0x00200000,
|
||||||
|
keEMAC4KRxFIFO = 0x00180000,
|
||||||
|
keEMAC2KRxFIFO = 0x00100000,
|
||||||
|
keEMAC1KRxFIFO = 0x00080000,
|
||||||
|
keEMAC16KTxFIFO = 0x00050000,
|
||||||
|
keEMAC8KTxFIFO = 0x00040000,
|
||||||
|
keEMAC4KTxFIFO = 0x00030000,
|
||||||
|
keEMAC2KTxFIFO = 0x00020000,
|
||||||
|
keEMAC1KTxFIFO = 0x00010000,
|
||||||
|
keEMACJumbo = 0x00000800,
|
||||||
|
keEMACIPHYAddr4 = 0x180,
|
||||||
|
keEMACOPB50MHz = 0x00,
|
||||||
|
keEMACOPB66MHz = 0x08,
|
||||||
|
keEMACOPB83MHz = 0x10,
|
||||||
|
keEMACOPB100MHz = 0x18,
|
||||||
|
keEMACOPBGt100 = 0x20,
|
||||||
|
|
||||||
|
/* 405EX-specific bits in MAL0_CFG */
|
||||||
|
keMALRdMaxBurst4 = 0,
|
||||||
|
keMALRdMaxBurst8 = 0x00100000,
|
||||||
|
keMALRdMaxBurst16 = 0x00200000,
|
||||||
|
keMALRdMaxBurst32 = 0x00300000,
|
||||||
|
|
||||||
|
keMALWrLowPriority = 0,
|
||||||
|
keMALWrMedLowPriority = 0x00040000,
|
||||||
|
keMALWrMedHiPriority = 0x00080000,
|
||||||
|
keMALWrHighPriority = 0x000C0000,
|
||||||
|
|
||||||
|
keMALWrMaxBurst4 = 0,
|
||||||
|
keMALWrMaxBurst8 = 0x00010000,
|
||||||
|
keMALWrMaxBurst16 = 0x00020000,
|
||||||
|
keMALWrMaxBurst32 = 0x00030000,
|
||||||
|
|
||||||
|
/* 405EX-specific STA bits */
|
||||||
|
keSTARun = 0x8000,
|
||||||
|
keSTADirectRd = 0x1000,
|
||||||
|
keSTADirectWr = 0x0800,
|
||||||
|
keSTAIndirAddr = 0x2000,
|
||||||
|
keSTAIndirRd = 0x3000,
|
||||||
|
keSTAIndirWr = 0x2800
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct GPIORegisters {
|
typedef struct GPIORegisters {
|
||||||
uint32_t OR;
|
uint32_t OR;
|
||||||
@@ -155,3 +182,10 @@ typedef struct GPIORegisters {
|
|||||||
|
|
||||||
enum { GPIOAddress = 0xEF600800 };
|
enum { GPIOAddress = 0xEF600800 };
|
||||||
|
|
||||||
|
typedef struct RGMIIRegisters {
|
||||||
|
uint32_t FER;
|
||||||
|
uint32_t SSR;
|
||||||
|
} RGMIIRegisters;
|
||||||
|
|
||||||
|
enum { RGMIIAddress = 0xEF600B00 };
|
||||||
|
|
||||||
|
|||||||
@@ -36,6 +36,25 @@ enum {
|
|||||||
EBC0_CFG = 0x23
|
EBC0_CFG = 0x23
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* MAL DCRs, have to be #defines */
|
||||||
|
#define MAL0_CFG 0x180
|
||||||
|
#define MAL0_ESR 0x181
|
||||||
|
#define MAL0_IER 0x182
|
||||||
|
#define MAL0_TXCASR 0x184
|
||||||
|
#define MAL0_TXCARR 0x185
|
||||||
|
#define MAL0_TXEOBISR 0x186
|
||||||
|
#define MAL0_TXDEIR 0x187
|
||||||
|
#define MAL0_RXCASR 0x190
|
||||||
|
#define MAL0_RXCARR 0x191
|
||||||
|
#define MAL0_RXEOBISR 0x192
|
||||||
|
#define MAL0_RXDEIR 0x193
|
||||||
|
#define MAL0_TXCTP0R 0x1A0
|
||||||
|
#define MAL0_TXCTP1R 0x1A1
|
||||||
|
#define MAL0_RXCTP0R 0x1C0
|
||||||
|
#define MAL0_RXCTP1R 0x1C1
|
||||||
|
#define MAL0_RCBS0 0x1E0
|
||||||
|
#define MAL0_RCBS1 0x1E1
|
||||||
|
|
||||||
/* Memory-mapped registers */
|
/* Memory-mapped registers */
|
||||||
|
|
||||||
typedef struct EthernetRegisters_GP {
|
typedef struct EthernetRegisters_GP {
|
||||||
@@ -51,19 +70,28 @@ typedef struct EthernetRegisters_GP {
|
|||||||
uint32_t VLANTPID;
|
uint32_t VLANTPID;
|
||||||
uint32_t VLANTCI;
|
uint32_t VLANTCI;
|
||||||
uint32_t pauseTimer;
|
uint32_t pauseTimer;
|
||||||
uint32_t indivHash[4];
|
uint32_t g_indivHash[4]; /* EX non-IP multicast addr/mask */
|
||||||
uint32_t groupHash[4];
|
uint32_t g_groupHash[4];
|
||||||
uint32_t lastSrcLo;
|
uint32_t lastSrcLo;
|
||||||
uint32_t lastSrcHi;
|
uint32_t lastSrcHi;
|
||||||
uint32_t IPGap;
|
uint32_t IPGap;
|
||||||
uint32_t STAcontrol;
|
uint32_t STAcontrol;
|
||||||
uint32_t xmtReqThreshold;
|
uint32_t xmtReqThreshold;
|
||||||
uint32_t rcvWatermark;
|
uint32_t rcvWatermarks;
|
||||||
uint32_t bytesXmtd;
|
uint32_t bytesXmtd;
|
||||||
uint32_t bytesRcvd;
|
uint32_t bytesRcvd;
|
||||||
|
uint32_t e_unused2;
|
||||||
|
uint32_t e_revID;
|
||||||
|
uint32_t e_unused3[2];
|
||||||
|
uint32_t e_indivHash[8];
|
||||||
|
uint32_t e_groupHash[8];
|
||||||
|
uint32_t e_xmtPause;
|
||||||
} EthernetRegisters_GP;
|
} EthernetRegisters_GP;
|
||||||
|
|
||||||
|
typedef struct EthernetRegisters_GP EthernetRegisters_EX;
|
||||||
|
|
||||||
enum { EMACAddress = 0xEF600800 };
|
enum { EMACAddress = 0xEF600800 };
|
||||||
|
enum { EMAC0GPAddress = 0xEF600800 };
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
// Mode 0 bits
|
// Mode 0 bits
|
||||||
@@ -75,12 +103,19 @@ enum {
|
|||||||
|
|
||||||
// Mode 1 bits
|
// Mode 1 bits
|
||||||
kEMACFullDuplex = 0x80000000,
|
kEMACFullDuplex = 0x80000000,
|
||||||
|
kEMACDoFlowControl = 0x10000000,
|
||||||
kEMACIgnoreSQE = 0x01000000,
|
kEMACIgnoreSQE = 0x01000000,
|
||||||
kEMAC100MBbps = 0x00400000,
|
kEMAC100MBbps = 0x00400000,
|
||||||
kEMAC4KRxFIFO = 0x00300000,
|
kEMAC4KRxFIFO = 0x00300000,
|
||||||
kEMAC2KTxFIFO = 0x00080000,
|
kEMAC2KTxFIFO = 0x00080000,
|
||||||
kEMACTx0Multi = 0x00008000,
|
kEMACTx0Multi = 0x00008000,
|
||||||
kEMACTxDependent= 0x00014000,
|
kEMACTxDependent= 0x00014000,
|
||||||
|
kEMAC100Mbps = 0x00400000,
|
||||||
|
kgEMAC4KRxFIFO = 0x00300000,
|
||||||
|
kgEMAC2KTxFIFO = 0x00080000,
|
||||||
|
kgEMACTx0Multi = 0x00008000,
|
||||||
|
kgEMACTxDependent= 0x00014000,
|
||||||
|
|
||||||
|
|
||||||
// Tx mode bits
|
// Tx mode bits
|
||||||
kEMACNewPacket0 = 0x80000000,
|
kEMACNewPacket0 = 0x80000000,
|
||||||
@@ -98,6 +133,25 @@ enum {
|
|||||||
kEMACHashRcv = 0x00200000,
|
kEMACHashRcv = 0x00200000,
|
||||||
kEMACBrcastRcv = 0x00100000,
|
kEMACBrcastRcv = 0x00100000,
|
||||||
kEMACMultcastRcv = 0x00080000,
|
kEMACMultcastRcv = 0x00080000,
|
||||||
|
keEMACNonIPMultcast = 0x00040000,
|
||||||
|
keEMACRxFIFOAFMax = 7,
|
||||||
|
|
||||||
|
// EMAC_STACR bits
|
||||||
|
kgSTAComplete = 0x8000,
|
||||||
|
kSTAErr = 0x4000,
|
||||||
|
|
||||||
|
// Interrupt status bits
|
||||||
|
kEMACIOverrun = 0x02000000,
|
||||||
|
kEMACIPause = 0x01000000,
|
||||||
|
kEMACIBadPkt = 0x00800000,
|
||||||
|
kEMACIRuntPkt = 0x00400000,
|
||||||
|
kEMACIShortEvt= 0x00200000,
|
||||||
|
kEMACIAlignErr= 0x00100000,
|
||||||
|
kEMACIBadFCS = 0x00080000,
|
||||||
|
kEMACIOverSize= 0x00040000,
|
||||||
|
kEMACILLCRange= 0x00020000,
|
||||||
|
kEMACISQEErr = 0x00000080,
|
||||||
|
kEMACITxErr = 0x00000040,
|
||||||
|
|
||||||
// Buffer descriptor control bits
|
// Buffer descriptor control bits
|
||||||
kMALTxReady = 0x8000,
|
kMALTxReady = 0x8000,
|
||||||
@@ -108,6 +162,21 @@ enum {
|
|||||||
kMALRxFirst = 0x0800,
|
kMALRxFirst = 0x0800,
|
||||||
kMALInterrupt = 0x0400,
|
kMALInterrupt = 0x0400,
|
||||||
|
|
||||||
|
kMALReset = 0x80000000,
|
||||||
|
kMALLowPriority = 0,
|
||||||
|
kMALMedLowPriority = 0x00400000,
|
||||||
|
kMALMedHiPriority = 0x00800000,
|
||||||
|
kMALHighPriority = 0x00C00000,
|
||||||
|
kMALLatency8 = 0x00040000,
|
||||||
|
kMALLockErr = 0x8000,
|
||||||
|
kMALCanBurst = 0x4000,
|
||||||
|
kMALLocksOPB = 0x80,
|
||||||
|
kMALLocksErrs = 0x2,
|
||||||
|
|
||||||
|
// MAL channel masks
|
||||||
|
kMALChannel0 = 0x80000000,
|
||||||
|
kMALChannel1 = 0x40000000,
|
||||||
|
|
||||||
// EMAC Tx descriptor bits sent
|
// EMAC Tx descriptor bits sent
|
||||||
kEMACGenFCS = 0x200,
|
kEMACGenFCS = 0x200,
|
||||||
kEMACGenPad = 0x100,
|
kEMACGenPad = 0x100,
|
||||||
|
|||||||
Reference in New Issue
Block a user