partial support for 68901 MFP chip as interrupt controller, untested.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@26633 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
François Revol
2008-07-25 15:05:52 +00:00
parent c1cec366af
commit 60b11851d4
5 changed files with 229 additions and 29 deletions
@@ -42,6 +42,10 @@ public:
virtual char SerialDebugGetChar() = 0; virtual char SerialDebugGetChar() = 0;
virtual void SerialDebugPutChar(char c) = 0; virtual void SerialDebugPutChar(char c) = 0;
virtual void EnableIOInterrupt(int irq);
virtual void DisableIOInterrupt(int irq);
virtual void AcknowledgeIOInterrupt(int irq);
virtual void SetHardwareRTC(uint32 seconds) = 0; virtual void SetHardwareRTC(uint32 seconds) = 0;
virtual uint32 GetHardwareRTC() = 0; virtual uint32 GetHardwareRTC() = 0;
@@ -0,0 +1,25 @@
#ifndef _MFP_H
#define _MFP_H
#define MFP_GPDR 0x01
#define MFP_AER 0x03
#define MFP_DDR 0x05
#define MFP_IERA 0x07
#define MFP_IERB 0x09
#define MFP_IPRA 0x0b
#define MFP_IPRB 0x0d
#define MFP_ISRA 0x0f
#define MFP_ISRB 0x11
#define MFP_IMRA 0x13
#define MFP_IMRB 0x15
#define MFP_VR 0x17
#define MFP_TACR 0x19
#define MFP_TBCR 0x1b
#define MFP_TCDCR 0x1d
#define MFP_TADR 0x1f
#define MFP_TBDR 0x21
#define MFP_TCDR 0x23
#define MFP_TDDR 0x25
//XXX
#endif /* _MFP_H */
+14 -2
View File
@@ -81,16 +81,28 @@ platform_start_kernel(void)
dprintf("kernel entry at %lx\n", gKernelArgs.kernel_image.elf_header.e_entry); dprintf("kernel entry at %lx\n", gKernelArgs.kernel_image.elf_header.e_entry);
asm("move.l %0, %%sp; " // move stack out of way asm volatile (
"move.l %0, %%sp; " // move stack out of way
: : "m" (stackTop)); : : "m" (stackTop));
asm("move.l #0x0,-(%%sp); " // we're the BSP cpu (0)
asm volatile (
"ori #0x0700,%%sr; "); // disable interrupts
asm volatile (
"move.l #0x0,-(%%sp); " // we're the BSP cpu (0)
"move.l %0,-(%%sp); " // kernel args "move.l %0,-(%%sp); " // kernel args
"move.l #0x0,-(%%sp);" // dummy retval for call to main "move.l #0x0,-(%%sp);" // dummy retval for call to main
"move.l %1,-(%%sp); " // this is the start address "move.l %1,-(%%sp); " // this is the start address
"rts; " // jump. "rts; " // jump.
: : "g" (args), "g" (gKernelArgs.kernel_image.elf_header.e_entry)); : : "g" (args), "g" (gKernelArgs.kernel_image.elf_header.e_entry));
// Huston, we have a problem!
asm volatile (
"andi #0xf8ff,%%sr; "); // reenable interrupts
panic("kernel returned!\n"); panic("kernel returned!\n");
} }
+28 -27
View File
@@ -15,6 +15,7 @@
#include <int.h> #include <int.h>
#include <arch_platform.h>
#include <arch/smp.h> #include <arch/smp.h>
#include <boot/kernel_args.h> #include <boot/kernel_args.h>
#include <device_manager.h> #include <device_manager.h>
@@ -64,28 +65,30 @@ struct iframe_stack gBootFrameStack;
// interrupt controller interface (initialized // interrupt controller interface (initialized
// in arch_int_init_post_device_manager()) // in arch_int_init_post_device_manager())
static struct interrupt_controller_module_info *sPIC; //static struct interrupt_controller_module_info *sPIC;
static void *sPICCookie; //static void *sPICCookie;
void void
arch_int_enable_io_interrupt(int irq) arch_int_enable_io_interrupt(int irq)
{ {
if (!sPIC) //if (!sPIC)
return; // return;
// TODO: I have no idea, what IRQ type is appropriate. // TODO: I have no idea, what IRQ type is appropriate.
sPIC->enable_io_interrupt(sPICCookie, irq, IRQ_TYPE_LEVEL); //sPIC->enable_io_interrupt(sPICCookie, irq, IRQ_TYPE_LEVEL);
M68KPlatform::Default()->EnableIOInterrupt(irq);
} }
void void
arch_int_disable_io_interrupt(int irq) arch_int_disable_io_interrupt(int irq)
{ {
if (!sPIC) //if (!sPIC)
return; // return;
sPIC->disable_io_interrupt(sPICCookie, irq); //sPIC->disable_io_interrupt(sPICCookie, irq);
M68KPlatform::Default()->DisableIOInterrupt(irq);
} }
@@ -243,28 +246,36 @@ m68k_exception_entry(struct iframe *iframe)
case 30: // autovector interrupt case 30: // autovector interrupt
case 31: // autovector interrupt case 31: // autovector interrupt
{ {
#if 0
if (!sPIC) { if (!sPIC) {
panic("m68k_exception_entry(): external interrupt although we " panic("m68k_exception_entry(): external interrupt although we "
"don't have a PIC driver!"); "don't have a PIC driver!");
ret = B_HANDLED_INTERRUPT; ret = B_HANDLED_INTERRUPT;
break; break;
} }
#endif
M68KPlatform::Default()->AcknowledgeIOInterrupt(vector);
dprintf("handling I/O interrupts...\n"); dprintf("handling I/O interrupts...\n");
int irq; ret = int_io_interrupt_handler(vector, true);
#if 0
while ((irq = sPIC->acknowledge_io_interrupt(sPICCookie)) >= 0) { while ((irq = sPIC->acknowledge_io_interrupt(sPICCookie)) >= 0) {
// TODO: correctly pass level-triggered vs. edge-triggered to the handler! // TODO: correctly pass level-triggered vs. edge-triggered to the handler!
ret = int_io_interrupt_handler(irq, true); ret = int_io_interrupt_handler(irq, true);
} }
#endif
dprintf("handling I/O interrupts done\n"); dprintf("handling I/O interrupts done\n");
break; break;
} }
case 0x1700: // thermal management exception
panic("thermal management exception: unimplemented\n");
break;
case 9: // trace case 9: // trace
default: default:
// vectors >= 64 are user defined vectors, used for IRQ
if (vector >= 64) {
M68KPlatform::Default()->AcknowledgeIOInterrupt(irq);
ret = int_io_interrupt_handler(vector, true);
break;
}
dprintf("unhandled exception type 0x%x\n", vector); dprintf("unhandled exception type 0x%x\n", vector);
print_iframe(iframe); print_iframe(iframe);
panic("unhandled exception type\n"); panic("unhandled exception type\n");
@@ -286,10 +297,6 @@ dprintf("handling I/O interrupts done\n");
} }
#warning M68K: WTF do I need that here ?
extern status_t
arch_vm_translation_map_early_query(addr_t va, addr_t *out_physical);
status_t status_t
arch_int_init(kernel_args *args) arch_int_init(kernel_args *args)
{ {
@@ -302,15 +309,7 @@ arch_int_init(kernel_args *args)
/* fill in the vector table */ /* fill in the vector table */
for (i = 0; i < M68K_EXCEPTION_VECTOR_COUNT; i++) for (i = 0; i < M68K_EXCEPTION_VECTOR_COUNT; i++)
gExceptionVectors[i] = &__m68k_exception_common; gExceptionVectors[i] = &__m68k_exception_common;
#if 0
/* get the physical address */
err = arch_vm_translation_map_early_query(
(addr_t)gExceptionVectors, &vbr);
if (err < B_OK) {
panic("can't query phys for vbr");
return err;
}
#endif
vbr = args->arch_args.phys_vbr; vbr = args->arch_args.phys_vbr;
/* point VBR to the new table */ /* point VBR to the new table */
asm volatile ("movec %0,%%vbr" : : "r"(vbr):); asm volatile ("movec %0,%%vbr" : : "r"(vbr):);
@@ -482,7 +481,9 @@ probe_pic_device(device_node_handle node, PICModuleList &picModules)
status_t status_t
arch_int_init_post_device_manager(struct kernel_args *args) arch_int_init_post_device_manager(struct kernel_args *args)
{ {
#warning M68K: init PIC from M68KPlatform:: status_t err;
err = M68KPlatform::Default()->InitPIC(args);
return err;
#if 0 /* PIC modules */ #if 0 /* PIC modules */
// get the interrupt controller driver modules // get the interrupt controller driver modules
PICModuleList picModules; PICModuleList picModules;
@@ -541,7 +542,7 @@ arch_int_init_post_device_manager(struct kernel_args *args)
} }
#if 0 #if 0//PPC
// #pragma mark - // #pragma mark -
struct m68k_cpu_exception_context * struct m68k_cpu_exception_context *
@@ -10,9 +10,23 @@
#include <boot/kernel_args.h> #include <boot/kernel_args.h>
//#include <platform/openfirmware/openfirmware.h> //#include <platform/openfirmware/openfirmware.h>
#include <platform/atari_m68k/MFP.h>
#include <real_time_clock.h> #include <real_time_clock.h>
#include <util/kernel_cpp.h> #include <util/kernel_cpp.h>
#define MFP0_BASE 0xFFFFFA00
#define MFP1_BASE 0xFFFFFA80
#define MFP0_VECTOR_BASE 64
#define MFP1_VECTOR_BASE (MFP0_VECTOR_BASE+16)
// ?
#define SCC_C0_VECTOR_BASE (MFP1_VECTOR_BASE+16)
// ??
#define SCC_C1_VECTOR_BASE (0x1BC/4)
#define inb(a) (*(volatile uint8 *)(a))
#define outb(a, v) (*(volatile uint8 *)(a) = v)
namespace BPrivate { namespace BPrivate {
@@ -20,7 +34,26 @@ namespace BPrivate {
// #pragma mark - Atari (Falcon) // #pragma mark - Atari (Falcon)
class M68KAtari : public M68KPlatform { class M68KAtari : public M68KPlatform {
class MFP {
public:
MFP(uint32 base, int vector);
~MFP();
uint32 Base() const { return fBase; };
int Vector() const { return fVector; };
void EnableIOInterrupt(int irq);
void DisableIOInterrupt(int irq);
void AcknowledgeIOInterrupt(int irq);
private:
uint32 fBase;
int fVector;
};
public: public:
M68KAtari(); M68KAtari();
virtual ~M68KAtari(); virtual ~M68KAtari();
@@ -36,6 +69,10 @@ public:
virtual char SerialDebugGetChar(); virtual char SerialDebugGetChar();
virtual void SerialDebugPutChar(char c); virtual void SerialDebugPutChar(char c);
virtual void EnableIOInterrupt(int irq);
virtual void DisableIOInterrupt(int irq);
virtual void AcknowledgeIOInterrupt(int irq);
virtual void SetHardwareRTC(uint32 seconds); virtual void SetHardwareRTC(uint32 seconds);
virtual uint32 GetHardwareRTC(); virtual uint32 GetHardwareRTC();
@@ -45,7 +82,11 @@ public:
virtual void ShutDown(bool reboot); virtual void ShutDown(bool reboot);
private: private:
MFP *MFPForIrq(int irq);
int fRTC; int fRTC;
MFP *fMFP[2];
// native features (ARAnyM emulator) // native features (ARAnyM emulator)
uint32 (*nfGetID)(const char *name); uint32 (*nfGetID)(const char *name);
int32 (*nfCall)(uint32 ID, ...); int32 (*nfCall)(uint32 ID, ...);
@@ -60,6 +101,71 @@ private:
using BPrivate::M68KAtari; using BPrivate::M68KAtari;
// #pragma mark - M68KAtari::MFP
static char sMFP0Buffer[sizeof(M68KAtari::MFP)];
static char sMFP1Buffer[sizeof(M68KAtari::MFP)];
// constructor
MFP::MFP(uint32 base, int vector)
{
fBase = base;
fVector = vector;
}
MFP::~MFP()
{
}
#warning M68K: use enable or mark register ?
void
MFP::EnableIOInterrupt(int irq)
{
uint8 bit = 1 << (irq % 8);
// I*B[0] is vector+0, I*A[0] is vector+8
uint32 reg = Base() + ((irq > 8) ? (MFP_IERA) : (MFP_IERB));
uint8 val = inb(reg);
if (val & bit == 0) {
val |= bit;
outb(reg, val);
}
}
void
MFP::DisableIOInterrupt(int irq)
{
uint8 bit = 1 << (irq % 8);
// I*B[0] is vector+0, I*A[0] is vector+8
uint32 reg = Base() + ((irq > 8) ? (MFP_IERA) : (MFP_IERB));
uint8 val = inb(reg);
if (val & bit) {
val &= ~bit;
outb(reg, val);
}
}
void
MFP::AcknowledgeIOInterrupt(int irq)
{
uint8 bit = 1 << (irq % 8);
// I*B[0] is vector+0, I*A[0] is vector+8
uint32 reg = Base() + ((irq > 8) ? (MFP_ISRA) : (MFP_ISRB));
uint8 val = inb(reg);
if (val & bit) {
val &= ~bit;
outb(reg, val);
}
}
// #pragma mark - M68KAtari
// constructor // constructor
M68KAtari::M68KAtari() M68KAtari::M68KAtari()
: M68KPlatform(B_ATARI_PLATFORM, M68K_PLATFORM_ATARI), : M68KPlatform(B_ATARI_PLATFORM, M68K_PLATFORM_ATARI),
@@ -77,6 +183,9 @@ M68KAtari::~M68KAtari()
status_t status_t
M68KAtari::Init(struct kernel_args *kernelArgs) M68KAtari::Init(struct kernel_args *kernelArgs)
{ {
fMFP[0] = NULL;
fMFP[1] = NULL;
nfGetID = nfGetID =
kernelArgs->arch_args.plat_args.atari.nat_feat.nf_get_id; kernelArgs->arch_args.plat_args.atari.nat_feat.nf_get_id;
nfCall = nfCall =
@@ -119,6 +228,10 @@ status_t
M68KAtari::InitPIC(struct kernel_args *kernelArgs) M68KAtari::InitPIC(struct kernel_args *kernelArgs)
{ {
panic("WRITEME"); panic("WRITEME");
fMFP[0] = new(sMFP0Buffer) M68KAtari::MFP(MFP0_BASE, MFP0_VECTOR_BASE);
//if (kernelArgs->arch_args.machine == /*TT*/) {
fMFP[1] = new(sMFP1Buffer) M68KAtari::MFP(MFP1_BASE, MFP1_VECTOR_BASE);
//}
return B_NO_INIT; return B_NO_INIT;
} }
@@ -171,6 +284,35 @@ M68KAtari::SerialDebugPutChar(char c)
} }
void
M68KAtari::EnableIOInterrupt(int irq)
{
MFP *mfp = MFPForIrq(irq);
if (mfp)
mfp->EnableIOInterrupt(irq - mfp->Vector());
}
void
M68KAtari::DisableIOInterrupt(int irq)
{
MFP *mfp = MFPForIrq(irq);
if (mfp)
mfp->DisableIOInterrupt(irq - mfp->Vector());
}
void
M68KAtari::AcknowledgeIOInterrupt(int irq)
{
MFP *mfp = MFPForIrq(irq);
if (mfp)
mfp->AcknowledgeIOInterrupt(irq - mfp->Vector());
}
void void
M68KAtari::SetHardwareRTC(uint32 seconds) M68KAtari::SetHardwareRTC(uint32 seconds)
{ {
@@ -203,6 +345,22 @@ M68KAtari::ShutDown(bool reboot)
panic("WRITEME"); panic("WRITEME");
} }
MFP *
M68KAtari::MFPForIrq(int irq)
{
int i;
for (i = 0; i < 2; i++) {
if (fMFP[i]) {
if (irq >= fMFP[i]->Vector() && irq < fMFP[i]->Vector() + 16)
return &fMFP[i];
}
}
return NULL;
}
// static buffer for constructing the actual M68KPlatform // static buffer for constructing the actual M68KPlatform
static char *sM68KPlatformBuffer[sizeof(M68KAtari)]; static char *sM68KPlatformBuffer[sizeof(M68KAtari)];
#warning PTR HERE ??? #warning PTR HERE ???