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
63enum 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
89namespace BPrivate {
90
91//class MfpPIC;
92
93// #pragma mark - Atari (Falcon)
94
95
96class M68KAtari : public M68KPlatform {
97public:
98	class MFP {
99	public:
100		MFP(uint32 base, int vector);
101		~MFP();
102
103		uint32 Base() const { return fBase; };
104		int Vector() const { return fVector; };
105
106		uint8 ReadReg(uint32 reg) { return in8(fBase + reg); };
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
123		uint32 Base() const { return fBase; };
124		int Vector() const { return fVector; };
125
126		uint8 ReadReg(uint32 reg);
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
166private:
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
185using BPrivate::M68KAtari;
186
187
188// #pragma mark - M68KAtari::MFP
189
190
191static char sMFP0Buffer[sizeof(M68KAtari::MFP)];
192static char sMFP1Buffer[sizeof(M68KAtari::MFP)];
193
194// constructor
195M68KAtari::MFP::MFP(uint32 base, int vector)
196{
197	fBase = base;
198	fVector = vector;
199}
200
201
202M68KAtari::MFP::~MFP()
203{
204}
205
206#warning M68K: use enable or mark register ?
207
208void
209M68KAtari::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
222void
223M68KAtari::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
236bool
237M68KAtari::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
255static char sRTCBuffer[sizeof(M68KAtari::RTC)];
256
257// constructor
258M68KAtari::RTC::RTC(uint32 base, int vector)
259{
260	fBase = base;
261	fVector = vector;
262}
263
264
265M68KAtari::RTC::~RTC()
266{
267}
268
269
270uint8
271M68KAtari::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
290M68KAtari::M68KAtari()
291	: M68KPlatform(M68K_PLATFORM_ATARI)
292{
293}
294
295
296// destructor
297M68KAtari::~M68KAtari()
298{
299}
300
301
302void
303M68KAtari::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
320status_t
321M68KAtari::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
346status_t
347M68KAtari::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
363status_t
364M68KAtari::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
378status_t
379M68KAtari::InitPIC(struct kernel_args *kernelArgs)
380{
381	return B_OK;
382}
383
384
385status_t
386M68KAtari::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
395status_t
396M68KAtari::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
405char
406M68KAtari::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
540char
541M68KAtari::SerialDebugGetChar()
542{
543	//WRITEME
544	return BlueScreenGetChar();
545	//return 0;
546}
547
548
549void
550M68KAtari::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
570void
571M68KAtari::EnableIOInterrupt(int32 irq)
572{
573	MFP *mfp = MFPForIrq(irq);
574
575	if (mfp)
576		mfp->EnableIOInterrupt(irq - mfp->Vector());
577}
578
579
580void
581M68KAtari::DisableIOInterrupt(int32 irq)
582{
583	MFP *mfp = MFPForIrq(irq);
584
585	if (mfp)
586		mfp->DisableIOInterrupt(irq - mfp->Vector());
587}
588
589
590bool
591M68KAtari::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
601uint8
602M68KAtari::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
613void
614M68KAtari::WriteRTCReg(uint8 reg, uint8 val)
615{
616	fRTC->WriteReg(reg, val);
617}
618
619void
620M68KAtari::SetHardwareRTC(uint32 seconds)
621{
622#warning M68K: WRITEME
623}
624
625
626uint32
627M68KAtari::GetHardwareRTC()
628{
629#warning M68K: WRITEME
630	return 0;
631}
632
633
634void
635M68KAtari::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
653void
654M68KAtari::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
663void
664M68KAtari::ShutDown(bool reboot)
665{
666	panic("Bombs!");
667	panic("WRITEME");
668}
669
670
671M68KAtari::MFP *
672M68KAtari::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
685int32
686M68KAtari::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
697static char *sM68KPlatformBuffer[sizeof(M68KAtari)];
698#warning PTR HERE ???
699
700
701M68KPlatform *instanciate_m68k_platform_atari()
702{
703	return new(sM68KPlatformBuffer) M68KAtari;
704}
705