1 /*
2 Atari kernel platform code.
3 */
4
5 #include <arch_platform.h>
6
7 #include <new>
8 #include <util/kernel_cpp.h>
9
10 #include <KernelExport.h>
11
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>
19
20 #include "debugger_keymaps.h"
21
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
30
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)
34
35 /* used for system_time() calculation */
36 #define MFP_SYSTEM_TIME_RATE (MFP_FREQ/MFP_PRESCALER)
37
38
39 #define MFP0_BASE 0xFFFFFA00
40 #define MFP1_BASE 0xFFFFFA80
41
42 #define MFP0_VECTOR_BASE 64
43 #define MFP1_VECTOR_BASE (MFP0_VECTOR_BASE+16)
44
45 #define TT_RTC_BASE 0xFFFF8960
46
47 #define TT_RTC_VECTOR (MFP1_VECTOR_BASE+14)
48
49 // ?
50 #define SCC_C0_VECTOR_BASE (MFP1_VECTOR_BASE+16)
51 // ??
52 #define SCC_C1_VECTOR_BASE (0x1BC/4)
53
54 #define IKBD_BASE 0xFFFFFC00
55 #define IKBD_CTRL 0
56 #define IKBD_DATA 2
57 #define IKBD_STATUS_READ_BUFFER_FULL 0x01
58
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,
66
67 LEFT_CONTROL = 29,
68
69 LEFT_ALT = 56,
70
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 ?
79
80 DELETE = 83,
81 F12 = 88, // but it's shifted
82
83 };
84
85 #define in8(a) (*(volatile uint8 *)(a))
86 #define out8(v, a) (*(volatile uint8 *)(a) = v)
87
88
89 namespace BPrivate {
90
91 //class MfpPIC;
92
93 // #pragma mark - Atari (Falcon)
94
95
96 class M68KAtari : public M68KPlatform {
97 public:
98 class MFP {
99 public:
100 MFP(uint32 base, int vector);
101 ~MFP();
102
Base() const103 uint32 Base() const { return fBase; };
Vector() const104 int Vector() const { return fVector; };
105
ReadReg(uint32 reg)106 uint8 ReadReg(uint32 reg) { return in8(fBase + reg); };
WriteReg(uint32 reg,uint8 v)107 void WriteReg(uint32 reg, uint8 v) { out8(v, fBase + reg); };
108
109 void EnableIOInterrupt(int32 irq);
110 void DisableIOInterrupt(int32 irq);
111 bool AcknowledgeIOInterrupt(int32 irq);
112
113 private:
114 uint32 fBase;
115 int fVector;
116 };
117
118 class RTC {
119 public:
120 RTC(uint32 base, int vector);
121 ~RTC();
122
Base() const123 uint32 Base() const { return fBase; };
Vector() const124 int Vector() const { return fVector; };
125
126 uint8 ReadReg(uint32 reg);
WriteReg(uint32 reg,uint8 v)127 void WriteReg(uint32 reg, uint8 v) { out8((uint8)reg,fBase+1); out8(v,fBase+3); };
128
129 private:
130 uint32 fBase;
131 int fVector;
132 };
133
134 M68KAtari();
135 virtual ~M68KAtari();
136
137 void ProbeHardware(struct kernel_args *kernelArgs);
138
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);
146
147 virtual char BlueScreenGetChar();
148
149 virtual char SerialDebugGetChar();
150 virtual void SerialDebugPutChar(char c);
151
152 virtual void EnableIOInterrupt(int32 irq);
153 virtual void DisableIOInterrupt(int32 irq);
154 virtual bool AcknowledgeIOInterrupt(int32 irq);
155
156 virtual uint8 ReadRTCReg(uint8 reg);
157 virtual void WriteRTCReg(uint8 reg, uint8 val);
158 virtual void SetHardwareRTC(uint32 seconds);
159 virtual uint32 GetHardwareRTC();
160
161 virtual void SetHardwareTimer(bigtime_t timeout);
162 virtual void ClearHardwareTimer(void);
163
164 virtual void ShutDown(bool reboot);
165
166 private:
167 MFP *MFPForIrq(int irq);
168 static int32 MFPTimerInterrupt(void *data);
169
170 MFP *fMFP[2];
171
172 RTC *fRTC;
173
174 // native features (ARAnyM emulator)
175 uint32 (*nfGetID)(const char *name);
176 int32 (*nfCall)(uint32 ID, ...);
177 char *nfPage;
178 uint32 nfDebugPrintfID;
179
180 };
181
182
183 } // namespace BPrivate
184
185 using BPrivate::M68KAtari;
186
187
188 // #pragma mark - M68KAtari::MFP
189
190
191 static char sMFP0Buffer[sizeof(M68KAtari::MFP)];
192 static char sMFP1Buffer[sizeof(M68KAtari::MFP)];
193
194 // constructor
MFP(uint32 base,int vector)195 M68KAtari::MFP::MFP(uint32 base, int vector)
196 {
197 fBase = base;
198 fVector = vector;
199 }
200
201
~MFP()202 M68KAtari::MFP::~MFP()
203 {
204 }
205
206 #warning M68K: use enable or mark register ?
207
208 void
EnableIOInterrupt(int irq)209 M68KAtari::MFP::EnableIOInterrupt(int irq)
210 {
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);
218 }
219 }
220
221
222 void
DisableIOInterrupt(int irq)223 M68KAtari::MFP::DisableIOInterrupt(int irq)
224 {
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);
232 }
233 }
234
235
236 bool
AcknowledgeIOInterrupt(int irq)237 M68KAtari::MFP::AcknowledgeIOInterrupt(int irq)
238 {
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;
247 }
248 return false;
249 }
250
251
252 // #pragma mark - M68KAtari::RTc
253
254
255 static char sRTCBuffer[sizeof(M68KAtari::RTC)];
256
257 // constructor
RTC(uint32 base,int vector)258 M68KAtari::RTC::RTC(uint32 base, int vector)
259 {
260 fBase = base;
261 fVector = vector;
262 }
263
264
~RTC()265 M68KAtari::RTC::~RTC()
266 {
267 }
268
269
270 uint8
ReadReg(uint32 reg)271 M68KAtari::RTC::ReadReg(uint32 reg)
272 {
273 int waitTime = 10000;
274
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);
279 }
280
281 out8((uint8)reg,fBase+1);
282 return in8(fBase+3);
283 }
284
285
286 // #pragma mark - M68KAtari
287
288
289 // constructor
M68KAtari()290 M68KAtari::M68KAtari()
291 : M68KPlatform(M68K_PLATFORM_ATARI)
292 {
293 }
294
295
296 // destructor
~M68KAtari()297 M68KAtari::~M68KAtari()
298 {
299 }
300
301
302 void
ProbeHardware(struct kernel_args * kernelArgs)303 M68KAtari::ProbeHardware(struct kernel_args *kernelArgs)
304 {
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);
311 }
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!");
317 }
318
319
320 status_t
Init(struct kernel_args * kernelArgs)321 M68KAtari::Init(struct kernel_args *kernelArgs)
322 {
323 fMFP[0] = NULL;
324 fMFP[1] = NULL;
325 fRTC = NULL;
326
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;
334
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 ???");
341
342 return B_OK;
343 }
344
345
346 status_t
InitSerialDebug(struct kernel_args * kernelArgs)347 M68KAtari::InitSerialDebug(struct kernel_args *kernelArgs)
348 {
349 nfDebugPrintfID =
350 kernelArgs->arch_args.plat_args.atari.nat_feat.nf_dprintf_id;
351
352 #warning M68K: add real serial debug output someday
353
354 //out8(0x11, IKBD_BASE+IKBD_DATA);
355
356 // now we can expect to see something
357 ProbeHardware(kernelArgs);
358
359 return B_OK;
360 }
361
362
363 status_t
InitPostVM(struct kernel_args * kernelArgs)364 M68KAtari::InitPostVM(struct kernel_args *kernelArgs)
365 {
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;
375 }
376
377
378 status_t
InitPIC(struct kernel_args * kernelArgs)379 M68KAtari::InitPIC(struct kernel_args *kernelArgs)
380 {
381 return B_OK;
382 }
383
384
385 status_t
InitRTC(struct kernel_args * kernelArgs,struct real_time_data * data)386 M68KAtari::InitRTC(struct kernel_args *kernelArgs,
387 struct real_time_data *data)
388 {
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;
392 }
393
394
395 status_t
InitTimer(struct kernel_args * kernelArgs)396 M68KAtari::InitTimer(struct kernel_args *kernelArgs)
397 {
398
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;
402 }
403
404
405 char
BlueScreenGetChar()406 M68KAtari::BlueScreenGetChar()
407 {
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 ?
412 */
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;
419
420 if (special & 0x80) {
421 special &= ~0x80;
422 return '[';
423 }
424 if (special != 0) {
425 key = special;
426 special = 0;
427 return key;
428 }
429 if (special2 != 0) {
430 key = special2;
431 special2 = 0;
432 return key;
433 }
434
435 while (true) {
436 uint8 status = in8(IKBD_BASE+IKBD_CTRL);
437
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;
443 }
444
445 spin(200);
446 key = in8(IKBD_BASE+IKBD_DATA);
447 /*
448 kprintf("key: %02x, %sshift %scontrol %salt\n",
449 key,
450 shiftPressed?"":"!",
451 controlPressed?"":"!",
452 altPressed?"":"!");
453 */
454
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;
468 }
469 } else {
470 // key down
471 switch (key) {
472 case LEFT_SHIFT:
473 case RIGHT_SHIFT:
474 shiftPressed = true;
475 break;
476
477 case LEFT_CONTROL:
478 controlPressed = true;
479 break;
480
481 case LEFT_ALT:
482 altPressed = true;
483 break;
484
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';
512
513
514 case DELETE:
515 if (controlPressed && altPressed)
516 arch_cpu_shutdown(true);
517
518 special = 0x80 | '3';
519 special2 = '~';
520 return '\x1b';
521
522 default:
523 if (controlPressed) {
524 char c = kShiftedKeymap[key];
525 if (c >= 'A' && c <= 'Z')
526 return 0x1f & c;
527 }
528
529 if (altPressed)
530 return kAltedKeymap[key];
531
532 return shiftPressed
533 ? kShiftedKeymap[key] : kUnshiftedKeymap[key];
534 }
535 }
536 }
537 }
538
539
540 char
SerialDebugGetChar()541 M68KAtari::SerialDebugGetChar()
542 {
543 //WRITEME
544 return BlueScreenGetChar();
545 //return 0;
546 }
547
548
549 void
SerialDebugPutChar(char c)550 M68KAtari::SerialDebugPutChar(char c)
551 {
552 if (nfCall && nfDebugPrintfID) {
553 #if 0
554 static char buffer[2] = { '\0', '\0' };
555 buffer[0] = c;
556
557 nfCall(nfDebugPrintfID /*| 0*/, buffer);
558 #endif
559 nfPage[0] = c;
560 nfPage[1] = '\0';
561 nfCall(nfDebugPrintfID /*| 0*/, nfPage);
562 }
563
564 #warning M68K: WRITEME
565 // real serial
566 //panic("WRITEME");
567 }
568
569
570 void
EnableIOInterrupt(int32 irq)571 M68KAtari::EnableIOInterrupt(int32 irq)
572 {
573 MFP *mfp = MFPForIrq(irq);
574
575 if (mfp)
576 mfp->EnableIOInterrupt(irq - mfp->Vector());
577 }
578
579
580 void
DisableIOInterrupt(int32 irq)581 M68KAtari::DisableIOInterrupt(int32 irq)
582 {
583 MFP *mfp = MFPForIrq(irq);
584
585 if (mfp)
586 mfp->DisableIOInterrupt(irq - mfp->Vector());
587 }
588
589
590 bool
AcknowledgeIOInterrupt(int32 irq)591 M68KAtari::AcknowledgeIOInterrupt(int32 irq)
592 {
593 MFP *mfp = MFPForIrq(irq);
594
595 if (mfp)
596 return mfp->AcknowledgeIOInterrupt(irq - mfp->Vector());
597 return false;
598 }
599
600
601 uint8
ReadRTCReg(uint8 reg)602 M68KAtari::ReadRTCReg(uint8 reg)
603 {
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);
610 }
611
612
613 void
WriteRTCReg(uint8 reg,uint8 val)614 M68KAtari::WriteRTCReg(uint8 reg, uint8 val)
615 {
616 fRTC->WriteReg(reg, val);
617 }
618
619 void
SetHardwareRTC(uint32 seconds)620 M68KAtari::SetHardwareRTC(uint32 seconds)
621 {
622 #warning M68K: WRITEME
623 }
624
625
626 uint32
GetHardwareRTC()627 M68KAtari::GetHardwareRTC()
628 {
629 #warning M68K: WRITEME
630 return 0;
631 }
632
633
634 void
SetHardwareTimer(bigtime_t timeout)635 M68KAtari::SetHardwareTimer(bigtime_t timeout)
636 {
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;
644
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);
650 }
651
652
653 void
ClearHardwareTimer(void)654 M68KAtari::ClearHardwareTimer(void)
655 {
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);
660 }
661
662
663 void
ShutDown(bool reboot)664 M68KAtari::ShutDown(bool reboot)
665 {
666 panic("Bombs!");
667 panic("WRITEME");
668 }
669
670
671 M68KAtari::MFP *
MFPForIrq(int irq)672 M68KAtari::MFPForIrq(int irq)
673 {
674 int i;
675
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];
680 }
681 }
682 return NULL;
683 }
684
685 int32
MFPTimerInterrupt(void * data)686 M68KAtari::MFPTimerInterrupt(void *data)
687 {
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();
693 }
694
695
696 // static buffer for constructing the actual M68KPlatform
697 static char *sM68KPlatformBuffer[sizeof(M68KAtari)];
698 #warning PTR HERE ???
699
700
701 M68KPlatform *instanciate_m68k_platform_atari()
702 {
703 return new(sM68KPlatformBuffer) M68KAtari;
704 }
705