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 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 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 195 M68KAtari::MFP::MFP(uint32 base, int vector) 196 { 197 fBase = base; 198 fVector = vector; 199 } 200 201 202 M68KAtari::MFP::~MFP() 203 { 204 } 205 206 #warning M68K: use enable or mark register ? 207 208 void 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 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 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 258 M68KAtari::RTC::RTC(uint32 base, int vector) 259 { 260 fBase = base; 261 fVector = vector; 262 } 263 264 265 M68KAtari::RTC::~RTC() 266 { 267 } 268 269 270 uint8 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 290 M68KAtari::M68KAtari() 291 : M68KPlatform(M68K_PLATFORM_ATARI) 292 { 293 } 294 295 296 // destructor 297 M68KAtari::~M68KAtari() 298 { 299 } 300 301 302 void 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 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 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 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 379 M68KAtari::InitPIC(struct kernel_args *kernelArgs) 380 { 381 return B_OK; 382 } 383 384 385 status_t 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 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 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 541 M68KAtari::SerialDebugGetChar() 542 { 543 //WRITEME 544 return BlueScreenGetChar(); 545 //return 0; 546 } 547 548 549 void 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 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 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 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 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 614 M68KAtari::WriteRTCReg(uint8 reg, uint8 val) 615 { 616 fRTC->WriteReg(reg, val); 617 } 618 619 void 620 M68KAtari::SetHardwareRTC(uint32 seconds) 621 { 622 #warning M68K: WRITEME 623 } 624 625 626 uint32 627 M68KAtari::GetHardwareRTC() 628 { 629 #warning M68K: WRITEME 630 return 0; 631 } 632 633 634 void 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 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 664 M68KAtari::ShutDown(bool reboot) 665 { 666 panic("Bombs!"); 667 panic("WRITEME"); 668 } 669 670 671 M68KAtari::MFP * 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 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