📄 ttyin.c
字号:
/* * Copyright (C) 1998, 1999, Jonathan S. Shapiro. * * This file is part of the EROS Operating System. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#include "linedisc.h"const uint32_t __rt_stack_pages = 0; const uint32_t __rt_stack_pointer = 0x21000;#define KR_VOID 0#define KR_CONSOLEKEY 9#define KR_SLEEPKEY 10#define KR_KBDKEY 8#define KR_LINEDISC 7#define KR_KEYBITS 11#define KR_TTYSEG 5#define KR_LINESEG 6#define KR_TMP 4#define KR_RK0 12#define KR_RK1 13#define KR_RK2 14#define KR_RETURN 15struct shared *kdb_buf;intstrlen(const char *s){ const char *send = s; while (*send) send++; return send - s;}voidWrite(const char *s){ Message msg; msg.snd_key0 = KR_VOID; msg.snd_key1 = KR_VOID; msg.snd_key2 = KR_VOID; msg.snd_key3 = KR_VOID; msg.rcv_key0 = KR_VOID; msg.rcv_key1 = KR_VOID; msg.rcv_key2 = KR_VOID; msg.rcv_key3 = KR_VOID; msg.snd_data = (uint8_t *) s; msg.snd_len = strlen(s); /* omit trailing null! */ msg.rcv_len = 0; /* no data returned */ msg.snd_invKey = KR_CONSOLEKEY; msg.snd_code = 1; (void) CALL(&msg);}voidSleep(uint32_t nsec){ Message msg; uint64_t ms = nsec; ms *= 1000; msg.snd_key0 = KR_VOID; msg.snd_key1 = KR_VOID; msg.snd_key2 = KR_VOID; msg.snd_key3 = KR_VOID; msg.rcv_key0 = KR_VOID; msg.rcv_key1 = KR_VOID; msg.rcv_key2 = KR_VOID; msg.rcv_key3 = KR_VOID; msg.snd_data = &ms; msg.snd_len = sizeof(ms); /* omit trailing null! */ msg.rcv_len = 0; /* no data returned */ msg.snd_invKey = KR_SLEEPKEY; msg.snd_code = 1; (void) CALL(&msg);}chargetc(){ Message msg; char chr[2]; /* chr + 0 */ uint16_t Result; uint32_t bytes = 1; msg.snd_key0 = KR_VOID; msg.snd_key1 = KR_VOID; msg.snd_key2 = KR_VOID; msg.snd_key3 = KR_VOID; msg.rcv_key0 = KR_VOID; msg.rcv_key1 = KR_VOID; msg.rcv_key2 = KR_VOID; msg.rcv_key3 = KR_VOID; msg.snd_len = sizeof(bytes); msg.snd_data = &bytes; msg.rcv_len = sizeof(chr); msg.rcv_data = chr; msg.snd_invKey = KR_KBDKEY; msg.snd_code = 0; Result = CALL(&msg); if (Result != RC_OK) return 0; else return (*chr); /* return the character */}voidcook (uint16_t chr) { Message msg; msg.snd_key0 = KR_VOID; msg.snd_key1 = KR_VOID; msg.snd_key2 = KR_VOID; msg.snd_key3 = KR_VOID; msg.rcv_key0 = KR_VOID; msg.rcv_key1 = KR_VOID; msg.rcv_key2 = KR_VOID; msg.rcv_key3 = KR_VOID; msg.snd_len = 1; msg.snd_data = &chr; msg.rcv_len = 0; msg.snd_invKey = KR_LINEDISC; msg.snd_code = LD_WRITE; CALL(&msg); }uint32_tnotifyLine (uint32_t oc) { /* * tell line disp to wake us up when it starts to * empty the buffer */ Message msg; msg.snd_key0 = KR_VOID; msg.snd_key1 = KR_VOID; msg.snd_key2 = KR_VOID; msg.snd_key3 = KR_VOID; msg.rcv_key0 = KR_VOID; msg.rcv_key1 = KR_VOID; msg.rcv_key2 = KR_VOID; msg.rcv_key3 = KR_VOID; msg.snd_len = 0; /* no data to send */ msg.rcv_len = 0; /* no data to send */ msg.snd_invKey = KR_LINEDISC; msg.snd_code = oc;#ifdef DEBUG kprintf(KR_CONSOLEKEY, "TTYin: CALLING linedisc with oc %x...\n", msg.snd_code); #endif CALL(&msg); if (msg.rcv_code == RC_OK) return 1; else return 0;}void_exit (){ /* * tell line disp to wake us up when it starts to * empty the buffer */ Message msg; msg.snd_key0 = KR_VOID; msg.snd_key1 = KR_VOID; msg.snd_key2 = KR_VOID; msg.snd_key3 = KR_VOID; msg.rcv_key0 = KR_VOID; msg.rcv_key1 = KR_VOID; msg.rcv_key2 = KR_VOID; msg.rcv_key3 = KR_VOID; msg.snd_len = 0; /* no data to send */ msg.rcv_len = 0; /* no data to send */ msg.snd_invKey = KR_VOID; msg.snd_code = 1;#ifdef DEBUG kprintf(KR_CONSOLEKEY, "TTYin: RETURNING to zero number key\n");#endif RETURN(&msg); }voidtty_init (){ /* * intialize various data structs */ /* copy domain1's 10th slot, put into tmp */ node_copy(KR_LINESEG, SH_SLOT, KR_TMP); /* copy tmp into our 10th slot */ node_swap(KR_TTYSEG, SH_SLOT, KR_TMP, KR_VOID); kdb_buf = (struct shared *) SH_ADDR; kdb_buf->mode = COOKED; /* set to COOKED by default -- arbitrary */ kdb_buf->wakeup = SIK_BUFSZ+1; /* set wakeup out of bounds */ kdb_buf->head = 0; kdb_buf->tail = 0; kdb_buf->full = 0; }uint16_taddtoBuf (char chr){ /* * this will be slighly less trivial once * we support more than one chr at a time */ if (kdb_buf->full) return 0; kdb_buf->buf[kdb_buf->head] = chr; if (kdb_buf->head == (SIK_BUFSZ - 1)) kdb_buf->head = 0; else kdb_buf->head++; if (kdb_buf->head == kdb_buf->tail) kdb_buf->full = 1; return 1;}intProcessRequest(Message *msg){ /* * a nice feature of the new IPC logic is that * multiple domains can be set running from the start. * * proceed to call the kdb key in an infinite loop * notify linedisp of changes in buffer as we reach critical * (wakeup) points * */ char Result; uint32_t added; /* flag to indicate whether a char made it into the buffer */#ifdef DEBUG kprintf(KR_CONSOLEKEY, "TTYin: starting...\n"); #endif tty_init(); /* intialize various data structs */#ifdef DEBUG kprintf(KR_CONSOLEKEY, "TTYin: init done. starting loop...\n"); #endif for ( ; ; ) {#ifdef DEBUG kprintf(KR_CONSOLEKEY, "TTYin: looping...\n"); #endif /* * currently getc() returns a single character * someday we will be dealing with multiples with early termination * * that is, what we'd like to do is move the COOKED mode * early \n termination logic into the kernel * * until then, COOKED mode is going to be slower than * it could be */ Result = getc(); /* try to read a character */#ifdef DEBUG kprintf(KR_CONSOLEKEY, "TTYin: Result from getc is %x\n",Result);#endif if (kdb_buf->mode == COOKED) cook (Result); /* contacts the linedisp domain, not console */#ifdef DEBUG kprintf (KR_CONSOLEKEY, "TTYin: attempting to addtoBuf...\n");#endif added = 0; /* * FIX: Alright you bonehead, this code is bloody * unreadable -- do something about it */ while (!added) { if ((kdb_buf->mode == RAW) || ((kdb_buf->mode == COOKED) && (Result > US))) { if (addtoBuf(Result)) { added = 1;#ifdef DEBUG kprintf (KR_CONSOLEKEY, "TTYin: addtoBuf h %x t %x w %x....\n", kdb_buf->head, kdb_buf->tail, kdb_buf->wakeup);#endif if ((kdb_buf->head == kdb_buf->wakeup) && (kdb_buf->mode == RAW)) {#ifdef DEBUG kprintf (KR_CONSOLEKEY, "TTYin: Wakeup linedisc...\n");#endif notifyLine(LD_WAKEUP); } } else /* AddtoBuf failed; buffer full */ {#ifdef DEBUG kprintf (KR_CONSOLEKEY, "TTYin: Buffer full. Waiting...\n");#endif /* * we want to return to the available state * so that the linedisc can wake us up when * the buffer is empty again. * * first we need to tell linedisc about the * situation; so we will CALL linedisc then * return to ZERO. * * When linedisc wakes us up it will do a fork * on us. */ if (notifyLine(LD_NOTIFY)) _exit();#ifdef DEBUG kprintf (KR_CONSOLEKEY, "TTYin: Back from the dead...\n");#endif } } else if (Result == 13) {#ifdef DEBUG kprintf (KR_CONSOLEKEY, "TTYin: Wakeup linedisc...\n");#endif notifyLine(LD_WAKEUP); added = 1; } else added = 1; } } return 1;}static uint8_t rcvData[EROS_PAGE_SIZE];voidmain(){ Message msg; msg.snd_invKey = KR_VOID; msg.snd_key0 = KR_VOID; msg.snd_key1 = KR_VOID; msg.snd_key2 = KR_VOID; msg.snd_key3 = KR_VOID; msg.snd_data = 0; msg.snd_len = 0; msg.snd_code = 0; msg.snd_w1 = 0; msg.snd_w2 = 0; msg.snd_w3 = 0; msg.rcv_key0 = KR_RK0; msg.rcv_key1 = KR_RK1; msg.rcv_key2 = KR_RK2; msg.rcv_key3 = KR_RETURN; msg.rcv_data = rcvData; msg.rcv_code = 0; msg.rcv_w1 = 0; msg.rcv_w2 = 0; msg.rcv_w3 = 0; msg.rcv_len = EROS_PAGE_SIZE; msg.snd_invKey = KR_RETURN; ProcessRequest(&msg); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -