2 Atari kernel platform code.
5 #include <arch_platform.h>
8 #include <util/kernel_cpp.h>
10 #include <KernelExport.h>
12 #include <boot/kernel_args.h>
14 //#include <platform/openfirmware/openfirmware.h>
15 #include <platform/atari_m68k/MFP.h>
16 #include <platform/atari_m68k/platform_atari_m68k.h>
17 #include <real_time_clock.h>
20 #include "debugger_keymaps.h"
22 /* which MFP timer to use */
23 #define SYS_TDR MFP_TADR
24 #define SYS_TCR MFP_TACR
25 #define SYS_TCRMASK 0x0f /* mask for timer control (0xf for A&B, 0x7 for C, 0x38 for D) */
26 #define SYS_TENABLE 0x01 /* delay mode with /4 prescaler: 0x01 (<<3 for timer D) */
27 #define SYS_TDISABLE 0x00
28 #define SYS_TVECTOR 13
29 #define MFP_PRESCALER 4
31 /* used for timer interrupt */
32 #define MFP_TIMER_RATE (MFP_FREQ/MFP_PRESCALER)
33 #define MFP_MAX_TIMER_INTERVAL (0xff * 1000000L / MFP_TIMER_RATE)
35 /* used for system_time() calculation */
36 #define MFP_SYSTEM_TIME_RATE (MFP_FREQ/MFP_PRESCALER)
39 #define MFP0_BASE 0xFFFFFA00
40 #define MFP1_BASE 0xFFFFFA80
42 #define MFP0_VECTOR_BASE 64
43 #define MFP1_VECTOR_BASE (MFP0_VECTOR_BASE+16)
45 #define TT_RTC_BASE 0xFFFF8960
47 #define TT_RTC_VECTOR (MFP1_VECTOR_BASE+14)
50 #define SCC_C0_VECTOR_BASE (MFP1_VECTOR_BASE+16)
52 #define SCC_C1_VECTOR_BASE (0x1BC/4)
54 #define IKBD_BASE 0xFFFFFC00
57 #define IKBD_STATUS_READ_BUFFER_FULL 0x01
59 // keyboard scancodes, very much like PC ones
61 // http://www.classiccmp.org/dunfield/atw800/h/atw800k.jpg
62 // ST Mag Nr 57 page 55
76 CURSOR_END
= 79, // not on real atari keyboard
77 PAGE_UP
= 73, // not on real atari keyboard XXX remap Help ?
78 PAGE_DOWN
= 81, // not on real atari keyboard XXX remap Undo ?
81 F12
= 88, // but it's shifted
85 #define in8(a) (*(volatile uint8 *)(a))
86 #define out8(v, a) (*(volatile uint8 *)(a) = v)
93 // #pragma mark - Atari (Falcon)
96 class M68KAtari
: public M68KPlatform
{
100 MFP(uint32 base
, int vector
);
103 uint32
Base() const { return fBase
; };
104 int Vector() const { return fVector
; };
106 uint8
ReadReg(uint32 reg
) { return in8(fBase
+ reg
); };
107 void WriteReg(uint32 reg
, uint8 v
) { out8(v
, fBase
+ reg
); };
109 void EnableIOInterrupt(int irq
);
110 void DisableIOInterrupt(int irq
);
111 bool AcknowledgeIOInterrupt(int irq
);
120 RTC(uint32 base
, int vector
);
123 uint32
Base() const { return fBase
; };
124 int Vector() const { return fVector
; };
126 uint8
ReadReg(uint32 reg
);
127 void WriteReg(uint32 reg
, uint8 v
) { out8((uint8
)reg
,fBase
+1); out8(v
,fBase
+3); };
135 virtual ~M68KAtari();
137 void ProbeHardware(struct kernel_args
*kernelArgs
);
139 virtual status_t
Init(struct kernel_args
*kernelArgs
);
140 virtual status_t
InitSerialDebug(struct kernel_args
*kernelArgs
);
141 virtual status_t
InitPostVM(struct kernel_args
*kernelArgs
);
142 virtual status_t
InitPIC(struct kernel_args
*kernelArgs
);
143 virtual status_t
InitRTC(struct kernel_args
*kernelArgs
,
144 struct real_time_data
*data
);
145 virtual status_t
InitTimer(struct kernel_args
*kernelArgs
);
147 virtual char BlueScreenGetChar();
149 virtual char SerialDebugGetChar();
150 virtual void SerialDebugPutChar(char c
);
152 virtual void EnableIOInterrupt(int irq
);
153 virtual void DisableIOInterrupt(int irq
);
154 virtual bool AcknowledgeIOInterrupt(int irq
);
156 virtual uint8
ReadRTCReg(uint8 reg
);
157 virtual void WriteRTCReg(uint8 reg
, uint8 val
);
158 virtual void SetHardwareRTC(uint32 seconds
);
159 virtual uint32
GetHardwareRTC();
161 virtual void SetHardwareTimer(bigtime_t timeout
);
162 virtual void ClearHardwareTimer(void);
164 virtual void ShutDown(bool reboot
);
167 MFP
*MFPForIrq(int irq
);
168 static int32
MFPTimerInterrupt(void *data
);
174 // native features (ARAnyM emulator)
175 uint32 (*nfGetID
)(const char *name
);
176 int32 (*nfCall
)(uint32 ID
, ...);
178 uint32 nfDebugPrintfID
;
183 } // namespace BPrivate
185 using BPrivate::M68KAtari
;
188 // #pragma mark - M68KAtari::MFP
191 static char sMFP0Buffer
[sizeof(M68KAtari::MFP
)];
192 static char sMFP1Buffer
[sizeof(M68KAtari::MFP
)];
195 M68KAtari::MFP::MFP(uint32 base
, int vector
)
202 M68KAtari::MFP::~MFP()
206 #warning M68K: use enable or mark register ?
209 M68KAtari::MFP::EnableIOInterrupt(int irq
)
211 uint8 bit
= 1 << (irq
% 8);
212 // I*B[0] is vector+0, I*A[0] is vector+8
213 uint32 reg
= Base() + ((irq
> 8) ? (MFP_IERA
) : (MFP_IERB
));
214 uint8 val
= in8(reg
);
215 if (val
& bit
== 0) {
223 M68KAtari::MFP::DisableIOInterrupt(int irq
)
225 uint8 bit
= 1 << (irq
% 8);
226 // I*B[0] is vector+0, I*A[0] is vector+8
227 uint32 reg
= Base() + ((irq
> 8) ? (MFP_IERA
) : (MFP_IERB
));
228 uint8 val
= in8(reg
);
237 M68KAtari::MFP::AcknowledgeIOInterrupt(int irq
)
239 uint8 bit
= 1 << (irq
% 8);
240 // I*B[0] is vector+0, I*A[0] is vector+8
241 uint32 reg
= Base() + ((irq
> 8) ? (MFP_ISRA
) : (MFP_ISRB
));
242 uint8 val
= in8(reg
);
252 // #pragma mark - M68KAtari::RTc
255 static char sRTCBuffer
[sizeof(M68KAtari::RTC
)];
258 M68KAtari::RTC::RTC(uint32 base
, int vector
)
265 M68KAtari::RTC::~RTC()
271 M68KAtari::RTC::ReadReg(uint32 reg
)
273 int waitTime
= 10000;
275 if (reg
< 0x0a) { // time of day stuff...
276 // check for in progress updates before accessing
278 while((in8(fBase
+3) & 0x80) && --waitTime
);
281 out8((uint8
)reg
,fBase
+1);
286 // #pragma mark - M68KAtari
290 M68KAtari::M68KAtari()
291 : M68KPlatform(M68K_PLATFORM_ATARI
)
297 M68KAtari::~M68KAtari()
303 M68KAtari::ProbeHardware(struct kernel_args
*kernelArgs
)
305 dprintf("Atari hardware:\n");
306 // if we are here we already know we have one
307 dprintf(" ST MFP\n");
308 if (m68k_is_hw_register_readable(MFP1_BASE
)) {
309 dprintf(" TT MFP\n");
310 fMFP
[1] = new(sMFP1Buffer
) M68KAtari::MFP(MFP1_BASE
, MFP1_VECTOR_BASE
);
312 if (m68k_is_hw_register_readable(TT_RTC_BASE
)) {
313 dprintf(" TT RTC MC146818A\n");
314 fRTC
= new(sRTCBuffer
) M68KAtari::RTC(TT_RTC_BASE
,TT_RTC_VECTOR
);
316 panic("TT RTC required!");
321 M68KAtari::Init(struct kernel_args
*kernelArgs
)
327 // initialize ARAnyM NatFeatures
329 kernelArgs
->arch_args
.plat_args
.atari
.nat_feat
.nf_get_id
;
331 kernelArgs
->arch_args
.plat_args
.atari
.nat_feat
.nf_call
;
333 kernelArgs
->arch_args
.plat_args
.atari
.nat_feat
.nf_page
;
336 if (m68k_is_hw_register_readable(MFP0_BASE
)) {
337 fMFP
[0] = new(sMFP0Buffer
) M68KAtari::MFP(MFP0_BASE
, MFP0_VECTOR_BASE
);
339 // won't really work anyway from here
340 panic("You MUST have an ST MFP! Wait, is that *really* an Atari ???");
347 M68KAtari::InitSerialDebug(struct kernel_args
*kernelArgs
)
350 kernelArgs
->arch_args
.plat_args
.atari
.nat_feat
.nf_dprintf_id
;
352 #warning M68K: add real serial debug output someday
354 //out8(0x11, IKBD_BASE+IKBD_DATA);
356 // now we can expect to see something
357 ProbeHardware(kernelArgs
);
364 M68KAtari::InitPostVM(struct kernel_args
*kernelArgs
)
367 add_debugger_command("of_exit", &debug_command_of_exit
,
368 "Exit to the Open Firmware prompt. No way to get back into the OS!");
369 add_debugger_command("of_enter", &debug_command_of_enter
,
370 "Enter a subordinate Open Firmware interpreter. Quitting it returns "
379 M68KAtari::InitPIC(struct kernel_args
*kernelArgs
)
386 M68KAtari::InitRTC(struct kernel_args
*kernelArgs
,
387 struct real_time_data
*data
)
389 // XXX we should do this in the bootloader maybe...
390 kernelArgs
->arch_args
.time_base_frequency
= MFP_SYSTEM_TIME_RATE
;
396 M68KAtari::InitTimer(struct kernel_args
*kernelArgs
)
399 fMFP
[0]->WriteReg(MFP_TACR
, 0); // stop it
400 install_io_interrupt_handler(fMFP
[0]->Vector()+13, &MFPTimerInterrupt
, this, 0);
406 M68KAtari::BlueScreenGetChar()
408 /* polling the keyboard, similar to code in keyboard
409 * driver, but without using an interrupt
410 * taken almost straight from x86 code
411 * XXX: maybe use the keymap from the _AKP cookie instead ?
413 static bool shiftPressed
= false;
414 static bool controlPressed
= false;
415 static bool altPressed
= false;
416 static uint8 special
= 0;
417 static uint8 special2
= 0;
420 if (special
& 0x80) {
436 uint8 status
= in8(IKBD_BASE
+IKBD_CTRL
);
438 if ((status
& IKBD_STATUS_READ_BUFFER_FULL
) == 0) {
439 // no data in keyboard buffer
441 //kprintf("no key\n");
446 key
= in8(IKBD_BASE
+IKBD_DATA
);
448 kprintf("key: %02x, %sshift %scontrol %salt\n",
451 controlPressed?"":"!",
457 switch (key
& ~0x80) {
460 shiftPressed
= false;
463 controlPressed
= false;
478 controlPressed
= true;
485 // start escape sequence for cursor movement
487 special
= 0x80 | 'A';
490 special
= 0x80 | 'B';
493 special
= 0x80 | 'C';
496 special
= 0x80 | 'D';
499 special
= 0x80 | 'H';
502 special
= 0x80 | 'F';
505 special
= 0x80 | '5';
509 special
= 0x80 | '6';
515 if (controlPressed
&& altPressed
)
516 arch_cpu_shutdown(true);
518 special
= 0x80 | '3';
523 if (controlPressed
) {
524 char c
= kShiftedKeymap
[key
];
525 if (c
>= 'A' && c
<= 'Z')
530 return kAltedKeymap
[key
];
533 ? kShiftedKeymap
[key
] : kUnshiftedKeymap
[key
];
541 M68KAtari::SerialDebugGetChar()
544 return BlueScreenGetChar();
550 M68KAtari::SerialDebugPutChar(char c
)
552 if (nfCall
&& nfDebugPrintfID
) {
554 static char buffer
[2] = { '\0', '\0' };
557 nfCall(nfDebugPrintfID
/*| 0*/, buffer
);
561 nfCall(nfDebugPrintfID
/*| 0*/, nfPage
);
564 #warning M68K: WRITEME
571 M68KAtari::EnableIOInterrupt(int irq
)
573 MFP
*mfp
= MFPForIrq(irq
);
576 mfp
->EnableIOInterrupt(irq
- mfp
->Vector());
581 M68KAtari::DisableIOInterrupt(int irq
)
583 MFP
*mfp
= MFPForIrq(irq
);
586 mfp
->DisableIOInterrupt(irq
- mfp
->Vector());
591 M68KAtari::AcknowledgeIOInterrupt(int irq
)
593 MFP
*mfp
= MFPForIrq(irq
);
596 return mfp
->AcknowledgeIOInterrupt(irq
- mfp
->Vector());
602 M68KAtari::ReadRTCReg(uint8 reg
)
605 // (on MC146818A it's in the RAM, but probably it's used for that purpose...)
606 // but just in case, we're in 20xx now anyway :)
609 return fRTC
->ReadReg(reg
);
614 M68KAtari::WriteRTCReg(uint8 reg
, uint8 val
)
616 fRTC
->WriteReg(reg
, val
);
620 M68KAtari::SetHardwareRTC(uint32 seconds
)
622 #warning M68K: WRITEME
627 M68KAtari::GetHardwareRTC()
629 #warning M68K: WRITEME
635 M68KAtari::SetHardwareTimer(bigtime_t timeout
)
637 uint8 nextEventClocks
;
640 else if (timeout
< MFP_MAX_TIMER_INTERVAL
)
641 nextEventClocks
= timeout
* MFP_TIMER_RATE
/ 1000000;
643 nextEventClocks
= 0xff;
645 fMFP
[0]->WriteReg(SYS_TDR
, nextEventClocks
);
646 // delay mode, device by 4
647 fMFP
[0]->WriteReg(SYS_TCR
, (fMFP
[0]->ReadReg(SYS_TCR
) & SYS_TCRMASK
) | SYS_TENABLE
);
649 EnableIOInterrupt(MFP1_VECTOR_BASE
+ SYS_TVECTOR
);
654 M68KAtari::ClearHardwareTimer(void)
656 // disable the irq (as on PC but I'm not sure it's needed)
657 DisableIOInterrupt(MFP1_VECTOR_BASE
+ SYS_TVECTOR
);
658 // stop it, we don't want another countdown
659 fMFP
[0]->WriteReg(SYS_TCR
, (fMFP
[0]->ReadReg(SYS_TCR
) & SYS_TCRMASK
) | SYS_TDISABLE
);
664 M68KAtari::ShutDown(bool reboot
)
672 M68KAtari::MFPForIrq(int irq
)
676 for (i
= 0; i
< 2; i
++) {
678 if (irq
>= fMFP
[i
]->Vector() && irq
< fMFP
[i
]->Vector() + 16)
686 M68KAtari::MFPTimerInterrupt(void *data
)
688 M68KAtari
*_this
= (M68KAtari
*)data
;
689 // disable the timer, else it will loop again with the same value
690 _this
->ClearHardwareTimer();
692 return timer_interrupt();
696 // static buffer for constructing the actual M68KPlatform
697 static char *sM68KPlatformBuffer
[sizeof(M68KAtari
)];
698 #warning PTR HERE ???
701 M68KPlatform
*instanciate_m68k_platform_atari()
703 return new(sM68KPlatformBuffer
) M68KAtari
;