URL
https://opencores.org/ocsvn/thor/thor/trunk
Subversion Repositories thor
[/] [thor/] [trunk/] [software/] [FMTK/] [source/] [kernel/] [keybd.c] - Rev 23
Compare with Previous | Blame | View Log
// The keyboard semaphore is locked only for short durations, so the interrupt // routine doesn't need to make many attempts to lock the semaphore. #include "config.h" #include "const.h" #include "types.h" #include "glo.h" #include "proto.h" #define SC_F12 0x07 #define SC_C 0x21 #define SC_T 0x2C #define SC_Z 0x1A #define SC_KEYUP 0xF0 #define SC_EXTEND 0xE0 #define SC_CTRL 0x14 #define SC_RSHIFT 0x59 #define SC_NUMLOCK 0x77 #define SC_SCROLLLOCK 0x7E #define SC_CAPSLOCK 0x58 #define SC_ALT 0x11 /* #define SC_LSHIFT EQU $12 SC_DEL EQU $71 ; extend SC_LCTRL EQU $58 */ #define SC_TAB 0x0D extern byte keybdExtendedCodes[]; extern byte keybdControlCodes[]; extern byte shiftedScanCodes[]; extern byte unshiftedScanCodes[]; extern signed byte KeybdGetStatus(); extern byte KeybdGetScancode(); extern void KeybdClearRcv(); int kbd_sema = 0; // // KeyState2_ // 76543210 // |||||||+ = shift // ||||||+- = alt // |||||+-- = control // ||||+--- = numlock // |||+---- = capslock // ||+----- = scrolllock // |+------ = // +------- = extended // unsigned int keybd_irq_stack[256]; static hMBX hKeybdMbx = -1; void KeybdIRQ() { __int8 sc; __int8 kh, kt; hTCB ht; TCB *t; JCB *jcb; int nn; prolog asm { sync sw r1,TCB_ir1[tr] sw r2,TCB_ir2[tr] sw r3,TCB_ir3[tr] sw r4,TCB_ir4[tr] sw r5,TCB_ir5[tr] sw r6,TCB_ir6[tr] sw r7,TCB_ir7[tr] sw r8,TCB_ir8[tr] sw r9,TCB_ir9[tr] sw r10,TCB_ir10[tr] sw r11,TCB_ir11[tr] sw r12,TCB_ir12[tr] sw r13,TCB_ir13[tr] sw r14,TCB_ir14[tr] sw r15,TCB_ir15[tr] sw r16,TCB_ir16[tr] sw r17,TCB_ir17[tr] sw r18,TCB_ir18[tr] sw r19,TCB_ir19[tr] sw r20,TCB_ir20[tr] sw r21,TCB_ir21[tr] sw r22,TCB_ir22[tr] sw r23,TCB_ir23[tr] sw r24,TCB_ir24[tr] sw r25,TCB_ir25[tr] sw r26,TCB_ir26[tr] sw r27,TCB_ir27[tr] sws ds,TCB_ids[tr] sws es,TCB_ies[tr] sws fs,TCB_ifs[tr] sws gs,TCB_igs[tr] sws hs,TCB_ihs[tr] sws ss,TCB_iss[tr] sws cs,TCB_ics[tr] sws ds.lmt,TCB_idslmt[tr] sws es.lmt,TCB_ieslmt[tr] sws fs.lmt,TCB_ifslmt[tr] sws gs.lmt,TCB_igslmt[tr] sws hs.lmt,TCB_ihslmt[tr] sws ss.lmt,TCB_isslmt[tr] sws cs.lmt,TCB_icslmt[tr] sws c1,TCB_ic1[tr] sws c2,TCB_ic2[tr] sws c3,TCB_ic3[tr] sws c4,TCB_ic4[tr] sws c5,TCB_ic5[tr] sws c6,TCB_ic6[tr] sws c7,TCB_ic7[tr] sws c8,TCB_ic8[tr] sws c9,TCB_ic9[tr] sws c10,TCB_ic10[tr] sws c11,TCB_ic11[tr] sws c13,TCB_ic13[tr] sws c14,TCB_ic14[tr] sws pregs,TCB_ipregs[tr] ldi sp,#irq_stack_+511*8 ; setup system stack and data segments mtspr ss,r0 ldis ss.lmt,#-1 mtspr ds,r0 ldis ds.lmt,#-1 ldi hs,#$FFD00000 ldi hs.lmt,#$100000 } while (KeybdGetStatus() < 0) { // Is there actually a scancode available ? sc = KeybdGetScancode(); jcb = IOFocusNdx; // Are there any jobs with focus ? if (jcb) { if (LockSemaphore(&kbd_sema,200)) { KeybdClearRcv(); // clear recieve register kh = jcb->KeybdHead; kt = jcb->KeybdTail; kh++; if (kh > jcb->KeybdBufSz) kh = 0; if (kh <> kt) { jcb->KeybdHead = kh; jcb->KeybdBuf[kh] = sc; } UnlockSemaphore(&kbd_sema); } // Trigger debugger if F12 pressed. Set a breakpoint at the RTI // return address. if (sc==SC_F12 && !jcb->KeyState1) { asm { mfspr r1,ipc mtspr dbad0,r1 ; Set breakpoint 0 address mfspr r1,dbctrl or r1,r1,#1 ; enable breakpoint #0 and r1,r1,#~0x30000 mtspr dbctrl,r1 } } // If CTRL-C is pressed, cause the tasks to return to the // catch handler. if (jcb->KeyState2 & 4) { if(sc == SC_C) { // control-c ? for (nn = 0; nn < 8; nn++) { if (jcb->tasks[nn]==-1) break; t = &tcbs[jcb->tasks[nn]]; t->exception = 512+3; // CTRL-C type exception } } else if (sc==SC_T || sc==SC_Z) { t = &tcbs[2]; t->exception = (512 + ((sc==SC_T) ? 20 : 26)) | (GetRunningTCB() << 32); } } if ((jcb->KeyState2 & 2) && sc == SC_TAB) // ALT + TAB ? if (hFocusSwitchMbx >= 0) FMTK_PostMsg(hFocusSwitchMbx,-1,-1,-1); // iof_switch++; } if (hKeybdMbx >= 0) FMTK_PostMsg(hKeybdMbx,-1,-1,-1); } // Restore the processor registers and return using an RTI. epilog asm { lw r1,TCB_ir1[tr] lw r2,TCB_ir2[tr] lw r3,TCB_ir3[tr] lw r4,TCB_ir4[tr] lw r5,TCB_ir5[tr] lw r6,TCB_ir6[tr] lw r7,TCB_ir7[tr] lw r8,TCB_ir8[tr] lw r9,TCB_ir9[tr] lw r10,TCB_ir10[tr] lw r11,TCB_ir11[tr] lw r12,TCB_ir12[tr] lw r13,TCB_ir13[tr] lw r14,TCB_ir14[tr] lw r15,TCB_ir15[tr] lw r16,TCB_ir16[tr] lw r17,TCB_ir17[tr] lw r18,TCB_ir18[tr] lw r19,TCB_ir19[tr] lw r20,TCB_ir20[tr] lw r21,TCB_ir21[tr] lw r22,TCB_ir22[tr] lw r23,TCB_ir23[tr] lw r24,TCB_ir24[tr] lw r25,TCB_ir25[tr] lw r26,TCB_ir26[tr] lw r27,TCB_ir27[tr] lws ds,TCB_ids[tr] lws es,TCB_ies[tr] lws fs,TCB_ifs[tr] lws gs,TCB_igs[tr] lws hs,TCB_ihs[tr] lws ss,TCB_iss[tr] lws cs,TCB_ics[tr] lws ds.lmt,TCB_idslmt[tr] lws es.lmt,TCB_ieslmt[tr] lws fs.lmt,TCB_ifslmt[tr] lws gs.lmt,TCB_igslmt[tr] lws hs.lmt,TCB_ihslmt[tr] lws ss.lmt,TCB_isslmt[tr] lws cs.lmt,TCB_icslmt[tr] lws c1,TCB_ic1[tr] lws c2,TCB_ic2[tr] lws c3,TCB_ic3[tr] lws c4,TCB_ic4[tr] lws c5,TCB_ic5[tr] lws c6,TCB_ic6[tr] lws c7,TCB_ic7[tr] lws c8,TCB_ic8[tr] lws c9,TCB_ic9[tr] lws c10,TCB_ic10[tr] lws c11,TCB_ic11[tr] lws c13,TCB_ic13[tr] lws c14,TCB_ic14[tr] lws pregs,TCB_ipregs[tr] sync rti } } // Return -1 if there is a scancode available in the buffer. int KeybdGetBufferStatus() { JCB *j; __int8 kh, kt; kh = kt = 0; j = GetJCBPtr(); if (LockSemaphore(&kbd_sema,200)) { kh = j->KeybdHead; kt = j->KeybdTail; UnlockSemaphore(&kbd_sema); } if (kh<>kt) return -1; return 0; } // Get a scancode from the keyboard buffer. __int8 KeybdGetBufferedScancode() { JCB *j; __int8 kh, kt; __int8 sc; j = GetJCBPtr(); sc = 0; if (LockSemaphore(&kbd_sema,200)) { kh = j->KeybdHead; kt = j->KeybdTail; if (kh <> kt) { sc = j->KeybdBuf[kt]; kt++; if (kt > j->KeybdBufSz) kt = 0; j->KeybdTail = kt; } UnlockSemaphore(&kbd_sema); } return sc; } private char KeybdGetBufferedChar() { JCB *j; unsigned __int8 sc; char ch; int d1, d2, d3; static int fc = 0; if (!fc) { FMTK_AllocMbx(&hKeybdMbx); fc = 1; } j = GetJCBPtr(); forever { while (KeybdGetBufferStatus() >= 0) { if (j->KeybdWaitFlag==0) return -1; FMTK_WaitMsg(hKeybdMbx, &d1, &d2, &d3, 0x7FFFFFFFFFFFFFFFL); } // The following typecast is needed to avoid a compiler bug in the // optimizer which removes the conversion from byte to word by zero // extension. sc = (unsigned __int8)KeybdGetBufferedScancode(); switch(sc) { case SC_KEYUP: j->KeyState1 = -1; break; case SC_EXTEND: j->KeyState2 |= 0x80; break; case SC_CTRL: if (j->KeyState1 >= 0) j->KeyState2 |= 4; else j->KeyState2 &= ~4; j->KeyState1 = 0; break; case SC_RSHIFT: if (j->KeyState1 >= 0) j->KeyState2 |= 1; else j->KeyState2 &= ~1; j->KeyState1 = 0; break; case SC_NUMLOCK: j->KeyState2 ^= 16; //KeybdSetLEDStatus(); break; case SC_CAPSLOCK: j->KeyState2 ^= 32; //KeybdSetLEDStatus(); break; case SC_SCROLLLOCK: j->KeyState2 ^= 64; //KeybdSetLEDStatus(); break; case SC_ALT: if (j->KeyState1 >= 0) j->KeyState2 |= 2; else j->KeyState2 &= ~2; j->KeyState1 = 0; break; default: if (sc == SC_TAB && (j->KeyState2 & 2) && j->KeyState1==0) { iof_switch++; } else { if (j->KeyState1) { j->KeyState1 = 0; } else { if (j->KeyState2 & 0x80) { // Extended code ? j->KeyState2 &= ~0x80; ch = keybdExtendedCodes[sc]; return ch; } else if (j->KeyState2 & 0x04) { // control ? ch = keybdControlCodes[sc]; return ch; } else if (j->KeyState2 & 0x01) { // shifted ? ch = shiftedScanCodes[sc]; return ch; } else { ch = unshiftedScanCodes[sc]; return ch; } } } } } } char KeybdGetBufferedCharWait() { JCB *j; j = GetJCBPtr(); j->KeybdWaitFlag = 1; return KeybdGetBufferedChar(); } char KeybdGetBufferedCharNoWait() { JCB *j; j = GetJCBPtr(); j->KeybdWaitFlag = 0; return KeybdGetBufferedChar(); }