btrfs: Attempt to fix GCC2 build.
[haiku.git] / src / system / kernel / platform / atari_m68k / platform.cpp
blobfe6599c49e2bb02a649d1ee6b725368a5e463bfe
1 /*
2 Atari kernel platform code.
3 */
5 #include <arch_platform.h>
7 #include <new>
8 #include <util/kernel_cpp.h>
10 #include <KernelExport.h>
12 #include <boot/kernel_args.h>
13 #include <arch/cpu.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>
18 #include <timer.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)
49 // ?
50 #define SCC_C0_VECTOR_BASE (MFP1_VECTOR_BASE+16)
51 // ??
52 #define SCC_C1_VECTOR_BASE (0x1BC/4)
54 #define IKBD_BASE 0xFFFFFC00
55 #define IKBD_CTRL 0
56 #define IKBD_DATA 2
57 #define IKBD_STATUS_READ_BUFFER_FULL 0x01
59 // keyboard scancodes, very much like PC ones
60 // see
61 // http://www.classiccmp.org/dunfield/atw800/h/atw800k.jpg
62 // ST Mag Nr 57 page 55
63 enum keycodes {
64 LEFT_SHIFT = 42,
65 RIGHT_SHIFT = 54,
67 LEFT_CONTROL = 29,
69 LEFT_ALT = 56,
71 CURSOR_LEFT = 75,
72 CURSOR_RIGHT = 77,
73 CURSOR_UP = 72,
74 CURSOR_DOWN = 80,
75 CURSOR_HOME = 71,
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 ?
80 DELETE = 83,
81 F12 = 88, // but it's shifted
85 #define in8(a) (*(volatile uint8 *)(a))
86 #define out8(v, a) (*(volatile uint8 *)(a) = v)
89 namespace BPrivate {
91 //class MfpPIC;
93 // #pragma mark - Atari (Falcon)
96 class M68KAtari : public M68KPlatform {
97 public:
98 class MFP {
99 public:
100 MFP(uint32 base, int vector);
101 ~MFP();
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);
113 private:
114 uint32 fBase;
115 int fVector;
118 class RTC {
119 public:
120 RTC(uint32 base, int vector);
121 ~RTC();
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); };
129 private:
130 uint32 fBase;
131 int fVector;
134 M68KAtari();
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);
166 private:
167 MFP *MFPForIrq(int irq);
168 static int32 MFPTimerInterrupt(void *data);
170 MFP *fMFP[2];
172 RTC *fRTC;
174 // native features (ARAnyM emulator)
175 uint32 (*nfGetID)(const char *name);
176 int32 (*nfCall)(uint32 ID, ...);
177 char *nfPage;
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)];
194 // constructor
195 M68KAtari::MFP::MFP(uint32 base, int vector)
197 fBase = base;
198 fVector = vector;
202 M68KAtari::MFP::~MFP()
206 #warning M68K: use enable or mark register ?
208 void
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) {
216 val |= bit;
217 out8(val, reg);
222 void
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);
229 if (val & bit) {
230 val &= ~bit;
231 out8(val, reg);
236 bool
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);
243 if (val & bit) {
244 val &= ~bit;
245 out8(val, reg);
246 return true;
248 return false;
252 // #pragma mark - M68KAtari::RTc
255 static char sRTCBuffer[sizeof(M68KAtari::RTC)];
257 // constructor
258 M68KAtari::RTC::RTC(uint32 base, int vector)
260 fBase = base;
261 fVector = vector;
265 M68KAtari::RTC::~RTC()
270 uint8
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
277 out8(0x0a, fBase+1);
278 while((in8(fBase+3) & 0x80) && --waitTime);
281 out8((uint8)reg,fBase+1);
282 return in8(fBase+3);
286 // #pragma mark - M68KAtari
289 // constructor
290 M68KAtari::M68KAtari()
291 : M68KPlatform(M68K_PLATFORM_ATARI)
296 // destructor
297 M68KAtari::~M68KAtari()
302 void
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);
315 } else
316 panic("TT RTC required!");
320 status_t
321 M68KAtari::Init(struct kernel_args *kernelArgs)
323 fMFP[0] = NULL;
324 fMFP[1] = NULL;
325 fRTC = NULL;
327 // initialize ARAnyM NatFeatures
328 nfGetID =
329 kernelArgs->arch_args.plat_args.atari.nat_feat.nf_get_id;
330 nfCall =
331 kernelArgs->arch_args.plat_args.atari.nat_feat.nf_call;
332 nfPage = (char *)
333 kernelArgs->arch_args.plat_args.atari.nat_feat.nf_page;
335 // probe for ST-MFP
336 if (m68k_is_hw_register_readable(MFP0_BASE)) {
337 fMFP[0] = new(sMFP0Buffer) M68KAtari::MFP(MFP0_BASE, MFP0_VECTOR_BASE);
338 } else
339 // won't really work anyway from here
340 panic("You MUST have an ST MFP! Wait, is that *really* an Atari ???");
342 return B_OK;
346 status_t
347 M68KAtari::InitSerialDebug(struct kernel_args *kernelArgs)
349 nfDebugPrintfID =
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);
359 return B_OK;
363 status_t
364 M68KAtari::InitPostVM(struct kernel_args *kernelArgs)
366 #if 0
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 "
371 "to KDL.");
372 #endif
373 return B_NO_INIT;
374 return B_OK;
378 status_t
379 M68KAtari::InitPIC(struct kernel_args *kernelArgs)
381 return B_OK;
385 status_t
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;
391 return B_OK;
395 status_t
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);
401 return B_OK;
405 char
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;
418 uint8 key = 0;
420 if (special & 0x80) {
421 special &= ~0x80;
422 return '[';
424 if (special != 0) {
425 key = special;
426 special = 0;
427 return key;
429 if (special2 != 0) {
430 key = special2;
431 special2 = 0;
432 return key;
435 while (true) {
436 uint8 status = in8(IKBD_BASE+IKBD_CTRL);
438 if ((status & IKBD_STATUS_READ_BUFFER_FULL) == 0) {
439 // no data in keyboard buffer
440 spin(200);
441 //kprintf("no key\n");
442 continue;
445 spin(200);
446 key = in8(IKBD_BASE+IKBD_DATA);
448 kprintf("key: %02x, %sshift %scontrol %salt\n",
449 key,
450 shiftPressed?"":"!",
451 controlPressed?"":"!",
452 altPressed?"":"!");
455 if (key & 0x80) {
456 // key up
457 switch (key & ~0x80) {
458 case LEFT_SHIFT:
459 case RIGHT_SHIFT:
460 shiftPressed = false;
461 break;
462 case LEFT_CONTROL:
463 controlPressed = false;
464 break;
465 case LEFT_ALT:
466 altPressed = false;
467 break;
469 } else {
470 // key down
471 switch (key) {
472 case LEFT_SHIFT:
473 case RIGHT_SHIFT:
474 shiftPressed = true;
475 break;
477 case LEFT_CONTROL:
478 controlPressed = true;
479 break;
481 case LEFT_ALT:
482 altPressed = true;
483 break;
485 // start escape sequence for cursor movement
486 case CURSOR_UP:
487 special = 0x80 | 'A';
488 return '\x1b';
489 case CURSOR_DOWN:
490 special = 0x80 | 'B';
491 return '\x1b';
492 case CURSOR_RIGHT:
493 special = 0x80 | 'C';
494 return '\x1b';
495 case CURSOR_LEFT:
496 special = 0x80 | 'D';
497 return '\x1b';
498 case CURSOR_HOME:
499 special = 0x80 | 'H';
500 return '\x1b';
501 case CURSOR_END:
502 special = 0x80 | 'F';
503 return '\x1b';
504 case PAGE_UP:
505 special = 0x80 | '5';
506 special2 = '~';
507 return '\x1b';
508 case PAGE_DOWN:
509 special = 0x80 | '6';
510 special2 = '~';
511 return '\x1b';
514 case DELETE:
515 if (controlPressed && altPressed)
516 arch_cpu_shutdown(true);
518 special = 0x80 | '3';
519 special2 = '~';
520 return '\x1b';
522 default:
523 if (controlPressed) {
524 char c = kShiftedKeymap[key];
525 if (c >= 'A' && c <= 'Z')
526 return 0x1f & c;
529 if (altPressed)
530 return kAltedKeymap[key];
532 return shiftPressed
533 ? kShiftedKeymap[key] : kUnshiftedKeymap[key];
540 char
541 M68KAtari::SerialDebugGetChar()
543 //WRITEME
544 return BlueScreenGetChar();
545 //return 0;
549 void
550 M68KAtari::SerialDebugPutChar(char c)
552 if (nfCall && nfDebugPrintfID) {
553 #if 0
554 static char buffer[2] = { '\0', '\0' };
555 buffer[0] = c;
557 nfCall(nfDebugPrintfID /*| 0*/, buffer);
558 #endif
559 nfPage[0] = c;
560 nfPage[1] = '\0';
561 nfCall(nfDebugPrintfID /*| 0*/, nfPage);
564 #warning M68K: WRITEME
565 // real serial
566 //panic("WRITEME");
570 void
571 M68KAtari::EnableIOInterrupt(int irq)
573 MFP *mfp = MFPForIrq(irq);
575 if (mfp)
576 mfp->EnableIOInterrupt(irq - mfp->Vector());
580 void
581 M68KAtari::DisableIOInterrupt(int irq)
583 MFP *mfp = MFPForIrq(irq);
585 if (mfp)
586 mfp->DisableIOInterrupt(irq - mfp->Vector());
590 bool
591 M68KAtari::AcknowledgeIOInterrupt(int irq)
593 MFP *mfp = MFPForIrq(irq);
595 if (mfp)
596 return mfp->AcknowledgeIOInterrupt(irq - mfp->Vector());
597 return false;
601 uint8
602 M68KAtari::ReadRTCReg(uint8 reg)
604 // fake century
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 :)
607 if (reg == 0x32)
608 return 0x20;
609 return fRTC->ReadReg(reg);
613 void
614 M68KAtari::WriteRTCReg(uint8 reg, uint8 val)
616 fRTC->WriteReg(reg, val);
619 void
620 M68KAtari::SetHardwareRTC(uint32 seconds)
622 #warning M68K: WRITEME
626 uint32
627 M68KAtari::GetHardwareRTC()
629 #warning M68K: WRITEME
630 return 0;
634 void
635 M68KAtari::SetHardwareTimer(bigtime_t timeout)
637 uint8 nextEventClocks;
638 if (timeout <= 0)
639 nextEventClocks = 2;
640 else if (timeout < MFP_MAX_TIMER_INTERVAL)
641 nextEventClocks = timeout * MFP_TIMER_RATE / 1000000;
642 else
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);
648 // enable irq
649 EnableIOInterrupt(MFP1_VECTOR_BASE + SYS_TVECTOR);
653 void
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);
663 void
664 M68KAtari::ShutDown(bool reboot)
666 panic("Bombs!");
667 panic("WRITEME");
671 M68KAtari::MFP *
672 M68KAtari::MFPForIrq(int irq)
674 int i;
676 for (i = 0; i < 2; i++) {
677 if (fMFP[i]) {
678 if (irq >= fMFP[i]->Vector() && irq < fMFP[i]->Vector() + 16)
679 return fMFP[i];
682 return NULL;
685 int32
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();
691 // handle the timer
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;