xref: /haiku/src/system/kernel/platform/atari_m68k/platform.cpp (revision 8df6a8dbf579280f55b61d725e470dee5d504e83)
1 /*
2 	Just a dummy. No BIOS services are required in the kernel.
3 */
4 
5 #include <arch_platform.h>
6 
7 #include <new>
8 
9 #include <KernelExport.h>
10 
11 #include <boot/kernel_args.h>
12 #include <arch/cpu.h>
13 //#include <platform/openfirmware/openfirmware.h>
14 #include <platform/atari_m68k/MFP.h>
15 #include <real_time_clock.h>
16 #include <util/kernel_cpp.h>
17 
18 #include "debugger_keymaps.h"
19 
20 #define MFP0_BASE	0xFFFFFA00
21 #define MFP1_BASE	0xFFFFFA80
22 
23 #define MFP0_VECTOR_BASE	64
24 #define MFP1_VECTOR_BASE	(MFP0_VECTOR_BASE+16)
25 // ?
26 #define SCC_C0_VECTOR_BASE	(MFP1_VECTOR_BASE+16)
27 // ??
28 #define SCC_C1_VECTOR_BASE	(0x1BC/4)
29 
30 #define IKBD_BASE	0xFFFFFC00
31 #define IKBD_CTRL	0
32 #define IKBD_DATA	2
33 #define IKBD_STATUS_READ_BUFFER_FULL	0x01
34 
35 // keyboard scancodes, very much like PC ones
36 // see
37 // http://www.classiccmp.org/dunfield/atw800/h/atw800k.jpg
38 // ST Mag Nr 57 page 55
39 enum keycodes {
40 	LEFT_SHIFT		= 42,
41 	RIGHT_SHIFT		= 54,
42 
43 	LEFT_CONTROL	= 29,
44 
45 	LEFT_ALT		= 56,
46 
47 	CURSOR_LEFT		= 75,
48 	CURSOR_RIGHT	= 77,
49 	CURSOR_UP		= 72,
50 	CURSOR_DOWN		= 80,
51 	CURSOR_HOME		= 71,
52 	CURSOR_END		= 79,	// not on real atari keyboard
53 	PAGE_UP			= 73,	// not on real atari keyboard XXX remap Help ?
54 	PAGE_DOWN		= 81,	// not on real atari keyboard XXX remap Undo ?
55 
56 	DELETE			= 83,
57 	F12				= 88,	// but it's shifted
58 
59 };
60 
61 #define in8(a)  (*(volatile uint8 *)(a))
62 #define out8(a, v)  (*(volatile uint8 *)(a) = v)
63 
64 
65 namespace BPrivate {
66 
67 //class MfpPIC;
68 
69 // #pragma mark - Atari (Falcon)
70 
71 
72 class M68KAtari : public M68KPlatform {
73 public:
74 	class MFP {
75 	public:
76 		MFP(uint32 base, int vector);
77 		~MFP();
78 
79 		uint32 Base() const { return fBase; };
80 		int Vector() const { return fVector; };
81 
82 		void EnableIOInterrupt(int irq);
83 		void DisableIOInterrupt(int irq);
84 		bool AcknowledgeIOInterrupt(int irq);
85 
86 	private:
87 		uint32 fBase;
88 		int fVector;
89 	};
90 
91 	M68KAtari();
92 	virtual ~M68KAtari();
93 
94 	virtual status_t Init(struct kernel_args *kernelArgs);
95 	virtual status_t InitSerialDebug(struct kernel_args *kernelArgs);
96 	virtual status_t InitPostVM(struct kernel_args *kernelArgs);
97 	virtual status_t InitPIC(struct kernel_args *kernelArgs);
98 	virtual status_t InitRTC(struct kernel_args *kernelArgs,
99 		struct real_time_data *data);
100 	virtual status_t InitTimer(struct kernel_args *kernelArgs);
101 
102 	virtual char BlueScreenGetChar();
103 
104 	virtual char SerialDebugGetChar();
105 	virtual void SerialDebugPutChar(char c);
106 
107 	virtual void EnableIOInterrupt(int irq);
108 	virtual void DisableIOInterrupt(int irq);
109 	virtual bool AcknowledgeIOInterrupt(int irq);
110 
111 	virtual	void SetHardwareRTC(uint32 seconds);
112 	virtual	uint32 GetHardwareRTC();
113 
114 	virtual void SetHardwareTimer(bigtime_t timeout);
115 	virtual void ClearHardwareTimer(void);
116 
117 	virtual	void ShutDown(bool reboot);
118 
119 private:
120 	MFP	*MFPForIrq(int irq);
121 	int	fRTC;
122 
123 	MFP	*fMFP[2];
124 
125 	// native features (ARAnyM emulator)
126 	uint32 (*nfGetID)(const char *name);
127 	int32 (*nfCall)(uint32 ID, ...);
128 	char *nfPage;
129 	uint32 nfDebugPrintfID;
130 
131 };
132 
133 
134 }	// namespace BPrivate
135 
136 using BPrivate::M68KAtari;
137 
138 
139 // #pragma mark - M68KAtari::MFP
140 
141 
142 static char sMFP0Buffer[sizeof(M68KAtari::MFP)];
143 static char sMFP1Buffer[sizeof(M68KAtari::MFP)];
144 
145 // constructor
146 M68KAtari::MFP::MFP(uint32 base, int vector)
147 {
148 	fBase = base;
149 	fVector = vector;
150 }
151 
152 
153 M68KAtari::MFP::~MFP()
154 {
155 }
156 
157 #warning M68K: use enable or mark register ?
158 
159 void
160 M68KAtari::MFP::EnableIOInterrupt(int irq)
161 {
162 	uint8 bit = 1 << (irq % 8);
163 	// I*B[0] is vector+0, I*A[0] is vector+8
164 	uint32 reg = Base() + ((irq > 8) ? (MFP_IERA) : (MFP_IERB));
165 	uint8 val = in8(reg);
166 	if (val & bit == 0) {
167 		val |= bit;
168 		out8(reg, val);
169 	}
170 }
171 
172 
173 void
174 M68KAtari::MFP::DisableIOInterrupt(int irq)
175 {
176 	uint8 bit = 1 << (irq % 8);
177 	// I*B[0] is vector+0, I*A[0] is vector+8
178 	uint32 reg = Base() + ((irq > 8) ? (MFP_IERA) : (MFP_IERB));
179 	uint8 val = in8(reg);
180 	if (val & bit) {
181 		val &= ~bit;
182 		out8(reg, val);
183 	}
184 }
185 
186 
187 bool
188 M68KAtari::MFP::AcknowledgeIOInterrupt(int irq)
189 {
190 	uint8 bit = 1 << (irq % 8);
191 	// I*B[0] is vector+0, I*A[0] is vector+8
192 	uint32 reg = Base() + ((irq > 8) ? (MFP_ISRA) : (MFP_ISRB));
193 	uint8 val = in8(reg);
194 	if (val & bit) {
195 		val &= ~bit;
196 		out8(reg, val);
197 		return true;
198 	}
199 	return false;
200 }
201 
202 
203 // #pragma mark - M68KAtari
204 
205 
206 // constructor
207 M68KAtari::M68KAtari()
208 	: M68KPlatform(B_ATARI_PLATFORM, M68K_PLATFORM_ATARI),
209 	  fRTC(-1)
210 {
211 }
212 
213 
214 // destructor
215 M68KAtari::~M68KAtari()
216 {
217 }
218 
219 
220 status_t
221 M68KAtari::Init(struct kernel_args *kernelArgs)
222 {
223 	fMFP[0] = NULL;
224 	fMFP[1] = NULL;
225 
226 	nfGetID =
227 		kernelArgs->arch_args.plat_args.atari.nat_feat.nf_get_id;
228 	nfCall =
229 		kernelArgs->arch_args.plat_args.atari.nat_feat.nf_call;
230 	nfPage = (char *)
231 		kernelArgs->arch_args.plat_args.atari.nat_feat.nf_page;
232 
233 	return B_OK;
234 }
235 
236 
237 status_t
238 M68KAtari::InitSerialDebug(struct kernel_args *kernelArgs)
239 {
240 	nfDebugPrintfID =
241 		kernelArgs->arch_args.plat_args.atari.nat_feat.nf_dprintf_id;
242 
243 #warning M68K: add real serial debug output someday
244 
245 	//out8(IKBD_BASE+IKBD_DATA, 0x11);
246 
247 	return B_OK;
248 }
249 
250 
251 status_t
252 M68KAtari::InitPostVM(struct kernel_args *kernelArgs)
253 {
254 #if 0
255 	add_debugger_command("of_exit", &debug_command_of_exit,
256 		"Exit to the Open Firmware prompt. No way to get back into the OS!");
257 	add_debugger_command("of_enter", &debug_command_of_enter,
258 		"Enter a subordinate Open Firmware interpreter. Quitting it returns "
259 		"to KDL.");
260 #endif
261 	return B_NO_INIT;
262 	return B_OK;
263 }
264 
265 
266 status_t
267 M68KAtari::InitPIC(struct kernel_args *kernelArgs)
268 {
269 	panic("WRITEME");
270 	fMFP[0] = new(sMFP0Buffer) M68KAtari::MFP(MFP0_BASE, MFP0_VECTOR_BASE);
271 	//if (kernelArgs->arch_args.machine == /*TT*/) {
272 		fMFP[1] = new(sMFP1Buffer) M68KAtari::MFP(MFP1_BASE, MFP1_VECTOR_BASE);
273 	//}
274 	return B_NO_INIT;
275 }
276 
277 
278 status_t
279 M68KAtari::InitRTC(struct kernel_args *kernelArgs,
280 	struct real_time_data *data)
281 {
282 	panic("WRITEME");
283 	return B_NO_INIT;
284 	return B_OK;
285 }
286 
287 
288 status_t
289 M68KAtari::InitTimer(struct kernel_args *kernelArgs)
290 {
291 	panic("WRITEME");
292 	return B_NO_INIT;
293 }
294 
295 
296 char
297 M68KAtari::BlueScreenGetChar()
298 {
299 	/* polling the keyboard, similar to code in keyboard
300 	 * driver, but without using an interrupt
301 	 * taken almost straight from x86 code
302 	 * XXX: maybe use the keymap from the _AKP cookie instead ?
303 	 */
304 	static bool shiftPressed = false;
305 	static bool controlPressed = false;
306 	static bool altPressed = false;
307 	static uint8 special = 0;
308 	static uint8 special2 = 0;
309 	uint8 key = 0;
310 
311 	if (special & 0x80) {
312 		special &= ~0x80;
313 		return '[';
314 	}
315 	if (special != 0) {
316 		key = special;
317 		special = 0;
318 		return key;
319 	}
320 	if (special2 != 0) {
321 		key = special2;
322 		special2 = 0;
323 		return key;
324 	}
325 
326 	while (true) {
327 		uint8 status = in8(IKBD_BASE+IKBD_CTRL);
328 
329 		if ((status & IKBD_STATUS_READ_BUFFER_FULL) == 0) {
330 			// no data in keyboard buffer
331 			spin(200);
332 			//kprintf("no key\n");
333 			continue;
334 		}
335 
336 		spin(200);
337 		key = in8(IKBD_BASE+IKBD_DATA);
338 		/*
339 		kprintf("key: %02x, %sshift %scontrol %salt\n",
340 			key,
341 			shiftPressed?"":"!",
342 			controlPressed?"":"!",
343 			altPressed?"":"!");
344 		*/
345 
346 		if (key & 0x80) {
347 			// key up
348 			switch (key & ~0x80) {
349 				case LEFT_SHIFT:
350 				case RIGHT_SHIFT:
351 					shiftPressed = false;
352 					break;
353 				case LEFT_CONTROL:
354 					controlPressed = false;
355 					break;
356 				case LEFT_ALT:
357 					altPressed = false;
358 					break;
359 			}
360 		} else {
361 			// key down
362 			switch (key) {
363 				case LEFT_SHIFT:
364 				case RIGHT_SHIFT:
365 					shiftPressed = true;
366 					break;
367 
368 				case LEFT_CONTROL:
369 					controlPressed = true;
370 					break;
371 
372 				case LEFT_ALT:
373 					altPressed = true;
374 					break;
375 
376 				// start escape sequence for cursor movement
377 				case CURSOR_UP:
378 					special = 0x80 | 'A';
379 					return '\x1b';
380 				case CURSOR_DOWN:
381 					special = 0x80 | 'B';
382 					return '\x1b';
383 				case CURSOR_RIGHT:
384 					special = 0x80 | 'C';
385 					return '\x1b';
386 				case CURSOR_LEFT:
387 					special = 0x80 | 'D';
388 					return '\x1b';
389 				case CURSOR_HOME:
390 					special = 0x80 | 'H';
391 					return '\x1b';
392 				case CURSOR_END:
393 					special = 0x80 | 'F';
394 					return '\x1b';
395 				case PAGE_UP:
396 					special = 0x80 | '5';
397 					special2 = '~';
398 					return '\x1b';
399 				case PAGE_DOWN:
400 					special = 0x80 | '6';
401 					special2 = '~';
402 					return '\x1b';
403 
404 
405 				case DELETE:
406 					if (controlPressed && altPressed)
407 						arch_cpu_shutdown(true);
408 
409 					special = 0x80 | '3';
410 					special2 = '~';
411 					return '\x1b';
412 
413 				default:
414 					if (controlPressed) {
415 						char c = kShiftedKeymap[key];
416 						if (c >= 'A' && c <= 'Z')
417 							return 0x1f & c;
418 					}
419 
420 					if (altPressed)
421 						return kAltedKeymap[key];
422 
423 					return shiftPressed
424 						? kShiftedKeymap[key] : kUnshiftedKeymap[key];
425 			}
426 		}
427 	}
428 }
429 
430 
431 char
432 M68KAtari::SerialDebugGetChar()
433 {
434 	//WRITEME
435 	return BlueScreenGetChar();
436 	//return 0;
437 }
438 
439 
440 void
441 M68KAtari::SerialDebugPutChar(char c)
442 {
443 	if (nfCall && nfDebugPrintfID) {
444 #if 0
445 		static char buffer[2] = { '\0', '\0' };
446 		buffer[0] = c;
447 
448 		nfCall(nfDebugPrintfID /*| 0*/, buffer);
449 #endif
450 		nfPage[0] = c;
451 		nfPage[1] = '\0';
452 		nfCall(nfDebugPrintfID /*| 0*/, nfPage);
453 	}
454 
455 #warning M68K: WRITEME
456 	// real serial
457 	//panic("WRITEME");
458 }
459 
460 
461 void
462 M68KAtari::EnableIOInterrupt(int irq)
463 {
464 	MFP *mfp = MFPForIrq(irq);
465 
466 	if (mfp)
467 		mfp->EnableIOInterrupt(irq - mfp->Vector());
468 }
469 
470 
471 void
472 M68KAtari::DisableIOInterrupt(int irq)
473 {
474 	MFP *mfp = MFPForIrq(irq);
475 
476 	if (mfp)
477 		mfp->DisableIOInterrupt(irq - mfp->Vector());
478 }
479 
480 
481 bool
482 M68KAtari::AcknowledgeIOInterrupt(int irq)
483 {
484 	MFP *mfp = MFPForIrq(irq);
485 
486 	if (mfp)
487 		return mfp->AcknowledgeIOInterrupt(irq - mfp->Vector());
488 	return false;
489 }
490 
491 void
492 M68KAtari::SetHardwareRTC(uint32 seconds)
493 {
494 }
495 
496 
497 uint32
498 M68KAtari::GetHardwareRTC()
499 {
500 	return 0;
501 }
502 
503 
504 void
505 M68KAtari::SetHardwareTimer(bigtime_t timeout)
506 {
507 }
508 
509 
510 void
511 M68KAtari::ClearHardwareTimer(void)
512 {
513 }
514 
515 
516 void
517 M68KAtari::ShutDown(bool reboot)
518 {
519 	panic("Bombs!");
520 	panic("WRITEME");
521 }
522 
523 
524 M68KAtari::MFP *
525 M68KAtari::MFPForIrq(int irq)
526 {
527 	int i;
528 
529 	for (i = 0; i < 2; i++) {
530 		if (fMFP[i]) {
531 			if (irq >= fMFP[i]->Vector() && irq < fMFP[i]->Vector() + 16)
532 				return fMFP[i];
533 		}
534 	}
535 	return NULL;
536 }
537 
538 
539 // static buffer for constructing the actual M68KPlatform
540 static char *sM68KPlatformBuffer[sizeof(M68KAtari)];
541 #warning PTR HERE ???
542 
543 
544 M68KPlatform *instanciate_m68k_platform_atari()
545 {
546 	return new(sM68KPlatformBuffer) M68KAtari;
547 }
548