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

📄 mk_deviceprivs.cxx

📁 C++ 编写的EROS RTOS
💻 CXX
字号:
/* * Copyright (C) 2001, 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 <kerninc/kernel.hxx>#include <kerninc/Key.hxx>#include <kerninc/Invocation.hxx>#include <kerninc/Thread.hxx>#include <kerninc/ThreadPile.hxx>#include <kerninc/IRQ.hxx>#include <kerninc/PhysMem.hxx>#include <disk/DiskKey.hxx>#include <kerninc/BootInfo.h>#include <kerninc/ObjectSource.hxx>#include <kerninc/ObjectCache.hxx>#include <eros/target.h>#include <eros/Invoke.h>#include <eros/StdKeyType.h>#if 0#include <kerninc/MsgLog.hxx>#include <kerninc/Thread.hxx>#include <eros/StdKeyType.h>#include <eros/DiscrimKey.h>#include <kerninc/Persist.hxx>#endif#include <eros/DevicePrivs.h>#define dbg_wakeup	0x1u#define dbg_alloc	0x2u#define dbg_sleep	0x4u#define dbg_error	0x8u/* Following should be an OR of some of the above */#define dbg_flags   ( 0u )#define DEBUG(x) if (dbg_##x & dbg_flags)struct UserIrq {  bool       isPending;  bool       isAlloc;  ThreadPile sleepers;} UserIrqEntries[NUM_HW_INTERRUPT];static voidDoUsermodeInterrupt(fixregs_t *ia){  uint32_t irq = IRQ_FROM_EXCEPTION(ia->ExceptNo);  UserIrq& uirq = UserIrqEntries[irq];    assert(IRQ::GetHandler(irq) == DoUsermodeInterrupt);  DEBUG(wakeup)    printf("Waking sleepers for IRQ %d\n", irq);  uirq.isPending = true;  uirq.sleepers.WakeAll();}voidDevicePrivsKey(Invocation& inv){  if (inv.entry.code != OC_DevPrivs_WaitIRQ)    COMMIT_POINT();  unsigned irq = inv.entry.w1;  /* NOTE: we haven't yet range checked irq, because this isn't used   * in all paths, so the resulting reference may well be out of   * range. Must range check before using. */  UserIrq& uirq = UserIrqEntries[irq];  switch(inv.entry.code) {  case OC_DevPrivs_AllocIRQ:    {      DEBUG(alloc)	printf("DevPrivs: Allocating IRQ %d\n", irq);      if (irq >= NUM_HW_INTERRUPT) {	inv.exit.code = RC_RequestError;	break;      }            if (uirq.isAlloc ||	  IRQ::GetHandler(irq) != IRQ::UnboundInterrupt) {	inv.exit.code = RC_DevPrivs_AllocFail;	break;      }            uirq.isPending = false;      IRQ::SetHandler(irq, DoUsermodeInterrupt);      IRQ::Enable(irq);#if 0      static bool WireShared(IntAction*);      static void Unwire(IntAction*);#endif    }      inv.exit.code = RC_OK;    break;      case OC_DevPrivs_ReleaseIRQ:    {      if (irq >= NUM_HW_INTERRUPT) {	inv.exit.code = RC_RequestError;	break;      }            if (!uirq.isAlloc) {	inv.exit.code = RC_DevPrivs_AllocFail;	break;      }            IRQ::UnsetHandler(irq);      uirq.isPending = false;        inv.exit.code = RC_OK;      break;    }      case OC_DevPrivs_EnableIRQ:    {      if (irq >= NUM_HW_INTERRUPT) {	inv.exit.code = RC_RequestError;	break;      }            if (!uirq.isAlloc) {	inv.exit.code = RC_DevPrivs_AllocFail;	break;      }            IRQ::Enable(irq);        inv.exit.code = RC_OK;      break;    }      case OC_DevPrivs_DisableIRQ:    {      if (irq >= NUM_HW_INTERRUPT) {	inv.exit.code = RC_RequestError;	break;      }            if (!uirq.isAlloc) {	inv.exit.code = RC_DevPrivs_AllocFail;	break;      }            IRQ::Disable(irq);        inv.exit.code = RC_OK;      break;    }      case OC_DevPrivs_WaitIRQ:    {      IRQ::Enable(irq);      IRQ::DISABLE();            if (irq < NUM_HW_INTERRUPT && !uirq.isPending) {	DEBUG(sleep)	  printf("DevPrivs: Sleeping for IRQ %d\n", irq);	Thread::Current()->SleepOn(uirq.sleepers);	IRQ::ENABLE();	Thread::Current()->Yield();      }      IRQ::ENABLE();      COMMIT_POINT();      if (irq >= NUM_HW_INTERRUPT) {	DEBUG(error)	  printf("IRQ %d is invalid, bogon\n", irq);	inv.exit.code = RC_RequestError;	break;      }      assert(uirq.isPending);      DEBUG(sleep)	printf("IRQ %d was pending already\n", irq);      IRQ::DISABLE();      uirq.isPending = false;      IRQ::ENABLE();	      /* Else return RC_OK per below */      inv.exit.code = RC_OK;      break;    }      case OC_DevPrivs_PublishMem:    {      kpa_t base = inv.entry.w1;      kpa_t bound = inv.entry.w2;      bool readOnly = inv.entry.w3;      if ((base % EROS_PAGE_SIZE) || (bound % EROS_PAGE_SIZE)) {	inv.exit.code = RC_RequestError;	break;      }      if (base >= bound) {	inv.exit.code = RC_RequestError;	break;      }      PmemInfo *pmi = PhysMem::AddRegion(base, bound, MI_DEVICEMEM, readOnly);      if (pmi) {	ObjectSource *source;	ObjectCache::AddDevicePages(pmi);	source = new ((void *) 1) PhysPageSource(pmi);	ObjectCache::AddSource(source);	inv.exit.code = RC_OK;      }      else {	inv.exit.code = RC_NoAccess;      }      break;    }  case OC_KeyType:    inv.exit.code = RC_OK;    inv.exit.w1 = inv.keyType;    break;  default:    inv.exit.code = RC_UnknownRequest;    break;  }  return;}

⌨️ 快捷键说明

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