⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 linedisc_buddy.c

📁 C++ 编写的EROS RTOS
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (C) 1998, 1999, Jonathan Adams. * Copyright (C) 2001, The EROS Group. * * 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 <eros/target.h>#include <eros/Invoke.h>#include <eros/ReturnerKey.h>#include <eros/ProcessKey.h>#include <eros/NodeKey.h>#include <eros/SleepKey.h>#include <eros/Key.h>#include <eros/StdKeyType.h>#include <domain/Runtime.h>#include "constituents.h"#include "linedisc.h"#include "chars.h"#include <domain/SpaceBankKey.h>#include <domain/ProtoSpace.h>#include <domain/domdbg.h>#define KR_DOMCRE    3#define KR_RETURNER  6#define KR_OSTREAM   7 /* DEBUGGING */#define KR_READERKEY K_READERKEY /* make sure this doesn't conflict */#define KR_CHRSRC    9#define KR_SCRATCH  10#define KR_SCRATCH2 11#define KR_ARG0     28  /* at startup, holds charsrc key */#define KR_SCRATCH3   29 /* Holds a distingueshed start key to linedisc */#define KR_ARG2     30#define KR_RESUME   31 /* DON'T USE IT FOR ANYTHING ELSE! */#define BUDDY SHARED.buddy#define POST_EVENT(evnts) (void)(BUDDY.currentLDEvents |= (evnts))#define READER_READY() (!!(SHARED.readerEventMask & BUDDY.currentLDEvents))/* this is the under-routine for assert, defined in debug.h */#ifndef NDEBUGint __assert(const char *expr, const char *file, int line){  kdprintf(KR_OSTREAM, "%s:%d: Assertion failed: '%s'\n",	   file, line, expr);  return 0;}#endif/* this is the under-routine for YIELD, defined in util.h */void__yield()  /* SMASHES KR_SCRATCH2 */{   node_copy(KR_CONSTIT, KC_SLEEP, KR_SCRATCH2);   sl_sleep(KR_SCRATCH2, 0); /* sleep for 0 ms -- yields the processor */}static inline void *memcpy(void *destptr, const void *srcptr, unsigned len){  register uint8_t *dest = destptr;  register const uint8_t *src = srcptr;  register const uint8_t *end = src + len;    while (src < end) *(dest++) = *(src++);  return destptr;}voiddestroy_self(uint32_t retCode){  register uint32_t retval;  uint32_t keyType;    /* get my address space into scratch */  retval = process_copy(KR_SELF, ProcAddrSpace, KR_SCRATCH);  assert(retval == RC_OK);  DEBUG(destroy)    kprintf(KR_OSTREAM,	    "LineDiscBuddy: destroying databuff page\n");  /* get data page into scratch2 */  retval = node_copy(KR_SCRATCH, DATABUFF_SLOT, KR_SCRATCH);  assert(retval == RC_OK);  key_kt(KR_SCRATCH, &keyType, 0);  if (keyType == AKT_Page) {    /* sell the page back to the space bank */    retval = spcbank_return_data_page(KR_BANK, KR_SCRATCH);    if (retval != RC_OK) {      kdprintf(KR_OSTREAM,"Returning databuff page to spacebank failed!\n");    }  } else {    DEBUG(destroy)      kprintf(KR_OSTREAM,	      "LineDiscBuddy: Databuff not page\n");  }  /* Don't sell back the shared page -- that's linedisc's job */  /* remove it from our address space, though -- don't want protospace     removing it */  retval = process_copy(KR_SELF, ProcAddrSpace, KR_SCRATCH);  assert(retval == RC_OK);    node_swap(KR_SCRATCH,SHARED_SLOT,KR_VOID,KR_VOID);    DEBUG(destroy)    kprintf(KR_OSTREAM,	    "LineDiscBuddy: Suiciding\n");    /* all of my stuff is gone -- better kill myself */  node_copy(KR_CONSTIT,KC_PROTO,KR_SCRATCH);  /* FIXME: Due to Intel's broken architecture, I can't return anything but     RC_OK to the caller.  If retCode != RC_OK, what should I do? */    DEBUG(destroy)    kdprintf(KR_OSTREAM,	    "LineDiscBuddy: Suiciding\n");    protospace_destroy(KR_RETURNER,		     KR_SCRATCH,		     KR_SELF,		     KR_DOMCRE,		     KR_BANK,		     1); /* small space */  /* NOTREACHED */}uint32_tfinish_init_protocol(uint32_t krForShared){  register uint32_t retval;  Message msg;  assert(krForShared != KR_SCRATCH3);    retval = process_make_start_key(KR_SELF, 0u, KR_SCRATCH3);  assert("making start key" && retval == RC_OK);    DEBUG(init)    kprintf(KR_OSTREAM,	    "LineDiscBuddy: RETURNing to linedisc\n");    msg.snd_key0 = KR_SCRATCH3; /* send him a start key */  msg.snd_key1 = KR_VOID;  msg.snd_key2 = KR_VOID;  msg.snd_key3 = KR_VOID;  msg.snd_w1 = 0u;  msg.snd_w2 = 0u;  msg.snd_w3 = 0u;  msg.snd_len = 0u; /* no data */  msg.rcv_key0 = krForShared; /* he'll return shared page */  msg.rcv_key1 = KR_VOID;  msg.rcv_key2 = KR_VOID;  msg.rcv_key3 = KR_RESUME;  /* for his resume key */  msg.rcv_len = 0u; /* no data */    msg.snd_invKey = KR_RESUME;  msg.snd_code = RC_OK; /* We're doing fine */  retval = RETURN(&msg); /* he should CALL us back */  assert("returning to linedisc" && retval == RC_OK);  DEBUG(init)    kprintf(KR_OSTREAM,	    "LineDiscBuddy: We're back! SEND him domain key\n");    /* he's now CALLed us -- we need to SEND him our domain key */  msg.snd_key0 = KR_SELF; /* send him my domain key */  msg.rcv_key0 = KR_VOID; /* no return */  msg.snd_invKey = KR_RESUME;  msg.snd_code = RC_OK;  SEND(&msg);  /* fork linedisc */  /* no way to tell if it succeeded  */  return RC_OK;}voidinitialize_linedisc_buddy(void){  register uint32_t retval;  uint32_t keyType;  /* copy stuff out of constit */  node_copy(KR_CONSTIT, KC_RETURNER, KR_RETURNER);  node_copy(KR_CONSTIT, KC_OSTREAM,  KR_OSTREAM);  /* copy the character source key into its key reg. (I could use     KR_SELF, but the Returner key is much cooler) */  copy_key_reg(KR_RETURNER, KR_ARG0, KR_CHRSRC);  DEBUG(init)    kprintf(KR_OSTREAM,	    "LineDiscBuddy: Returner worked -- buying shared page\n");    /* buy a new page and insert it into address space for the databuff*/  retval = process_copy(KR_SELF, ProcAddrSpace, KR_SCRATCH);  assert("process_copy(ProcAddrSpace)" && retval == RC_OK);  retval = spcbank_buy_data_pages(KR_BANK, 1, KR_SCRATCH2, 0, 0);  assert("spcbank_buy_data_pages(1)" && retval == RC_OK);  /* swap the new node in, putting the old contents key over address node */  retval = node_swap(KR_SCRATCH, DATABUFF_SLOT, KR_SCRATCH2, KR_SCRATCH);  assert("node_swap(AddrSpc,DATABUFF_SLOT,newPage)" && retval == RC_OK);  DEBUG(init) {    uint32_t keyType;    kprintf(KR_OSTREAM,	    "LineDiscBuddy: Databuff page installed -- checking "	    "previous occupant.\n");    key_kt(KR_SCRATCH, &keyType, 0);    if (keyType != RC_Void) {      kdprintf(KR_OSTREAM,	      "Hey! the previous occupant wasn't void!\n");    }    kprintf(KR_OSTREAM,	    "LineDiscBuddy: Checking that databuff is actually there.\n");    assert(DATABUFF[0] == 0);    DATABUFF[0] = 1;    assert(DATABUFF[0] != 0);    DATABUFF[0] = 0;    kprintf(KR_OSTREAM,	    "LineDiscBuddy: Databuff there. \n");      }  /* get the shared page from linedisc */  retval = finish_init_protocol(KR_SCRATCH2);             /* puts the shared page in SCRATCH2 */  assert("finish_init_protocol" && retval == RC_OK);#ifndef NDEBUG  key_kt(KR_SCRATCH, &keyType, 0);  assert(keyType == AKT_Page);#endif    retval = process_copy(KR_SELF, ProcAddrSpace, KR_SCRATCH);  assert("process_copy(ProcAddrSpace)" && retval == RC_OK);  /* swap the new node in, putting the old contents over the address     node */  retval = node_swap(KR_SCRATCH, SHARED_SLOT, KR_SCRATCH2, KR_SCRATCH);  assert("node_swap(AddrSpc,SHARED_SLOT,newPage)" && retval == RC_OK);  DEBUG(init) {    uint32_t keyType;    kprintf(KR_OSTREAM,	    "Shared page there -- checking to make sure there was no "	    "previous occupant.\n");    key_kt(KR_SCRATCH, &keyType, 0);    if (keyType != RC_Void) {      kdprintf(KR_OSTREAM,	      "Hey! the previous occupant wasn't void! (%08x)\n",	       keyType);    }  }  if (SHARED.linedisc_status == LD_Stat_Uninitialized) {    kdprintf(KR_OSTREAM, "LineDiscBuddy: Shared page isn't initialized!\n");  }  /* initialiaze BUDDY */  BUDDY.buffPos = DATABUFF;  SET(BUDDY.wakeupEvents,LD_Wakeup_Chars|LD_Wakeup_ProcFlags);    /* done intializing */  return;}/* tty_write:      This code is complicated by the need to to NL->CRNL    translation.  This is done with some extra code and a flag.  The    extra code does two things:    1.  It makes sure that we only send a newline as the first      character sent.    2.  If the first character to send *is* a newline, it checks the      flag.  If the flag (returnSent) is:      true:  the \r char has been successfully sent     false:  the \r char has not yet been sent.  It attempts to send a            \r char.  If this succeeds, the flag is set.  If it fails,	    the whole routine is exited, to be retried later.      After getting past the test, it knows that \r has been sent, so      it can then continue, having the \n sent with the rest of the      characters.   The returnSent flag is set to false whenever a character is   successfully sent.   NOTE: This expects that all other output processing was done using         write_data_to_buffer.  */  voidtry_write(void){  uint32_t count;  uint32_t newCount;    const char *buffp;  static bool returnSent = false;  register uint32_t doProc = (SHARED.outpProcFlags & LD_Out_DoOutpProc)                          && (SHARED.outpProcFlags & LD_Out_NLtoCRNL);    while (get_chars_to_remove(&SHARED.wrt_buff,			     &buffp,			     &count)) {    register uint32_t retval;    if (doProc) {      const char *curp = buffp;      const char *end = buffp + count;      if (*curp == '\n') {	if (!returnSent) {	  retval = charsrc_write(KR_CHRSRC,				 1,"\r",				 &newCount);	  assert("charsrc_write \\r" && retval == RC_OK);	  if (newCount == 1) {	    returnSent = true; /* true -- the flag is set */	    POST_EVENT(CharSrc_WriteSpaceAvailEvent);	  } else {	    break; /* failed -- get out of the entire routine */	  }	}	/* \r has been sent and the flag is set	   -- treat this as a normal character */	curp++;      }      while (curp < end && *curp != '\n')	curp++;      if (curp < end)	count = curp - buffp; /* write up to, but not inc., the NL */    }	    retval = charsrc_write(KR_CHRSRC,			   count, buffp,			   &newCount);    /* overwrote count with the actually written count */    assert("charsrc_write" && retval == RC_OK);    DEBUG(write)      kprintf(KR_OSTREAM,	      "LineDiscBuddy: charsrc_write done "	      "(actual_count = %08x)\n",	      newCount);        REMOVE_WRITTEN(&SHARED.wrt_buff, newCount);    DEBUG(write)      kprintf(KR_OSTREAM,	      "LineDiscBuddy: REMOVE_WRITTEN returned. "	      "(written %08x, reserved %08x, top %08x)\n",	      SHARED.wrt_buff.ctl.written,	      SHARED.wrt_buff.ctl.reserved,	      SHARED.wrt_buff.ctl.top);    if (newCount != 0)       returnSent = false;    /* we sent the associated \n, so the returnSent flag is cleared */        if (newCount != count) {      /* we didn't write the entire buffer -- return */      break;    } else {      /* Only necessary to post this if they have failed a write	 request */      if (SHARED.out_of_write_space) {	POST_EVENT(CharSrc_WriteSpaceAvailEvent);	SHARED.out_of_write_space = 0;      }    }  } }void write_string(char *string){  while (!write_data_to_buffer(&SHARED.wrt_buff,			       SHARED.outpProcFlags,			       string,			       strlen(string))) {    try_write();  }}voidwrite_beep(void){  write_string(BELL_STRING);}voidfork_reader(uint32_t numBytes){  Message msg;  assert(numBytes <= BUDDY.buffPos - DATABUFF);   DEBUG(waitevent)    kdprintf(KR_OSTREAM,             "Linedisc_buddy: FORKing reader (events 0x%08x bytes 0x%08x)\n",             BUDDY.currentLDEvents,             numBytes);  msg.snd_key0 = KR_VOID;  msg.snd_key1 = KR_VOID;  msg.snd_key2 = KR_VOID;  msg.snd_key3 = KR_VOID;  msg.snd_w1 = numBytes;  msg.snd_w2 = BUDDY.currentLDEvents;  BUDDY.currentLDEvents = 0u;  msg.snd_w3 = 0u;  msg.snd_len = numBytes;  msg.snd_data = DATABUFF;    msg.snd_code = RC_OK;  /* stash the key into a temp register, then reset readerwants.  This     way, we can recieve a reader request even if we don't run for a     while after the SEND. (if we didn't copy the key, then linedisc     could smash it between our resetting readerWants and invoking it)*/  copy_key_reg(KR_RETURNER,KR_READERKEY,KR_SCRATCH);  msg.snd_invKey = KR_SCRATCH;  SHARED.readerWants = UINT32_MAX; /* okay, all of the reader				    information can be smashed. */  SEND(&msg);  if (numBytes < BUDDY.buffPos - DATABUFF) {    memcpy(DATABUFF + numBytes, DATABUFF, numBytes);    /* this assumes memcopy copies first->last */    BUDDY.buffPos -= numBytes;  } else {    BUDDY.buffPos = DATABUFF;  }}voidraw_fork_reader(uint32_t numBytes){  /* SEND to the reader, returning at maximum /numBytes/ bytes. */  DEBUG(waitevent)    kprintf(KR_OSTREAM,	    "LineDiscBuddy -- Forking reader: maxuint8_ts %d buffPos 0x%04x"	    " readerWants %d\n",	    numBytes,	    BUDDY.buffPos - DATABUFF,	    SHARED.readerWants	    );    if (BUDDY.buffPos - DATABUFF < numBytes)    numBytes = BUDDY.buffPos - DATABUFF;  if (numBytes > SHARED.readerWants)    numBytes = SHARED.readerWants;  DEBUG(waitevent)    kprintf(KR_OSTREAM,	    "                 actualBytes: %d\n",numBytes);    fork_reader(numBytes); /* do the fork and update the buffer */}voidrawInputProcess(char *buffpos, uint32_t num){  DEBUG(inpproc)    kprintf(KR_OSTREAM,	    "Processing characters\n");    if (BUDDY.curInpFlags & LD_In_Echo) {    const char *curp = buffpos;    uint32_t maxCnt = num;    uint32_t count;	    while (maxCnt > 0) {      /* FIXME: assumes ascii, is slow -- do a lookup table*/      uint32_t retval = 0;      if ((BUDDY.curInpFlags & LD_In_EchoCtrl)	  && CCLASS(*curp) != 0) {	char toprnt[2] = "^A";	if (*curp <= 32) {	  toprnt[1] = *curp + '@';	} else { /* *curp == 127 */	  toprnt[1] = '?';	}	do {	  retval = write_data_to_buffer(&SHARED.wrt_buff,					SHARED.outpProcFlags,					toprnt,					2);	  if (retval == 0)	    try_write();	      	} while (retval == 0);	    	/* skip past the character */	curp++;	maxCnt--;	continue;      }      count = 0;      if (BUDDY.curInpFlags & LD_In_EchoCtrl) {	/* skip past all non-ctrl chars */	while (count < maxCnt &&	       CCLASS(curp[count]) == 0)	  count++;      } else {	/* we can write them all */	count = maxCnt;      }      do {	retval = write_data_to_buffer(&SHARED.wrt_buff,				      SHARED.outpProcFlags,				      curp,				      count);	if (retval == 0)	  try_write();	          } while (retval == 0);      curp += count;      maxCnt -= count;    }  }}voidrawLoop(void){

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -