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

View File

@ -42,6 +42,10 @@ public:
virtual char SerialDebugGetChar() = 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 uint32 GetHardwareRTC() = 0;

View File

@ -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 */

View File

@ -81,16 +81,28 @@ platform_start_kernel(void)
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));
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 #0x0,-(%%sp);" // dummy retval for call to main
"move.l %1,-(%%sp); " // this is the start address
"rts; " // jump.
: : "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");
}

View File

@ -15,6 +15,7 @@
#include <int.h>
#include <arch_platform.h>
#include <arch/smp.h>
#include <boot/kernel_args.h>
#include <device_manager.h>
@ -64,28 +65,30 @@ struct iframe_stack gBootFrameStack;
// interrupt controller interface (initialized
// in arch_int_init_post_device_manager())
static struct interrupt_controller_module_info *sPIC;
static void *sPICCookie;
//static struct interrupt_controller_module_info *sPIC;
//static void *sPICCookie;
void
arch_int_enable_io_interrupt(int irq)
{
if (!sPIC)
return;
//if (!sPIC)
// return;
// 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
arch_int_disable_io_interrupt(int irq)
{
if (!sPIC)
return;
//if (!sPIC)
// 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 31: // autovector interrupt
{
#if 0
if (!sPIC) {
panic("m68k_exception_entry(): external interrupt although we "
"don't have a PIC driver!");
ret = B_HANDLED_INTERRUPT;
break;
}
#endif
M68KPlatform::Default()->AcknowledgeIOInterrupt(vector);
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) {
// TODO: correctly pass level-triggered vs. edge-triggered to the handler!
ret = int_io_interrupt_handler(irq, true);
}
#endif
dprintf("handling I/O interrupts done\n");
break;
}
case 0x1700: // thermal management exception
panic("thermal management exception: unimplemented\n");
break;
case 9: // trace
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);
print_iframe(iframe);
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
arch_int_init(kernel_args *args)
{
@ -302,15 +309,7 @@ arch_int_init(kernel_args *args)
/* fill in the vector table */
for (i = 0; i < M68K_EXCEPTION_VECTOR_COUNT; i++)
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;
/* point VBR to the new table */
asm volatile ("movec %0,%%vbr" : : "r"(vbr):);
@ -482,7 +481,9 @@ probe_pic_device(device_node_handle node, PICModuleList &picModules)
status_t
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 */
// get the interrupt controller driver modules
PICModuleList picModules;
@ -541,7 +542,7 @@ arch_int_init_post_device_manager(struct kernel_args *args)
}
#if 0
#if 0//PPC
// #pragma mark -
struct m68k_cpu_exception_context *

View File

@ -10,9 +10,23 @@
#include <boot/kernel_args.h>
//#include <platform/openfirmware/openfirmware.h>
#include <platform/atari_m68k/MFP.h>
#include <real_time_clock.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 {
@ -20,7 +34,26 @@ namespace BPrivate {
// #pragma mark - Atari (Falcon)
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:
M68KAtari();
virtual ~M68KAtari();
@ -36,6 +69,10 @@ public:
virtual char SerialDebugGetChar();
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 uint32 GetHardwareRTC();
@ -45,7 +82,11 @@ public:
virtual void ShutDown(bool reboot);
private:
MFP *MFPForIrq(int irq);
int fRTC;
MFP *fMFP[2];
// native features (ARAnyM emulator)
uint32 (*nfGetID)(const char *name);
int32 (*nfCall)(uint32 ID, ...);
@ -60,6 +101,71 @@ private:
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
M68KAtari::M68KAtari()
: M68KPlatform(B_ATARI_PLATFORM, M68K_PLATFORM_ATARI),
@ -77,6 +183,9 @@ M68KAtari::~M68KAtari()
status_t
M68KAtari::Init(struct kernel_args *kernelArgs)
{
fMFP[0] = NULL;
fMFP[1] = NULL;
nfGetID =
kernelArgs->arch_args.plat_args.atari.nat_feat.nf_get_id;
nfCall =
@ -119,6 +228,10 @@ status_t
M68KAtari::InitPIC(struct kernel_args *kernelArgs)
{
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;
}
@ -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
M68KAtari::SetHardwareRTC(uint32 seconds)
{
@ -203,6 +345,22 @@ M68KAtari::ShutDown(bool reboot)
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 char *sM68KPlatformBuffer[sizeof(M68KAtari)];
#warning PTR HERE ???