The Pedigree Project  0.1
misc.cc
1 /*
2  * Copyright (c) 2007 Kevin Wolf
3  *
4  * This program is free software. It comes without any warranty, to
5  * the extent permitted by applicable law. You can redistribute it
6  * and/or modify it under the terms of the Do What The Fuck You Want
7  * To Public License, Version 2, as published by Sam Hocevar. See
8  * http://sam.zoy.org/projects/COPYING.WTFPL for more details.
9  */
10 
11 #include <stdbool.h>
12 #include <stddef.h>
13 #include "cdi-osdep.h"
14 #include "cdi/io.h"
15 #include "cdi/mem.h"
16 #include "pedigree/kernel/LockGuard.h"
17 #include "pedigree/kernel/Log.h"
18 #include "pedigree/kernel/Spinlock.h"
19 #include "pedigree/kernel/compiler.h"
20 #include "pedigree/kernel/machine/IrqHandler.h"
21 #include "pedigree/kernel/machine/IrqManager.h"
22 #include "pedigree/kernel/machine/Machine.h"
23 #include "pedigree/kernel/machine/types.h"
24 #include "pedigree/kernel/process/Semaphore.h"
25 #include "pedigree/kernel/process/Thread.h"
26 #include "pedigree/kernel/processor/MemoryRegion.h"
27 #include "pedigree/kernel/processor/PhysicalMemoryManager.h"
28 #include "pedigree/kernel/processor/Processor.h"
29 #include "pedigree/kernel/processor/ProcessorInformation.h"
30 #include "pedigree/kernel/processor/VirtualAddressSpace.h"
31 #include "pedigree/kernel/processor/state_forward.h"
32 #include "pedigree/kernel/processor/types.h"
33 #include "pedigree/kernel/time/Time.h"
34 #include "pedigree/kernel/utilities/utility.h"
35 
36 struct cdi_device;
37 
38 class CdiIrqHandler : public IrqHandler {
39  virtual bool irq(irq_id_t number, InterruptState &state);
40 };
41 
42 static CdiIrqHandler cdi_irq_handler;
43 
45 #define IRQ_COUNT 0x10
46 
48 static void (*driver_irq_handler[IRQ_COUNT])(struct cdi_device*) = { NULL };
50 static struct cdi_device* driver_irq_device[IRQ_COUNT] = { NULL };
55 static Spinlock irqCountLock;
56 static Semaphore *driver_irq_count[IRQ_COUNT] = {0};
57 // static volatile uint8_t driver_irq_count[IRQ_COUNT] = { 0 };
58 
62 bool CdiIrqHandler::irq(irq_id_t irq, InterruptState &state)
63 {
64  if(driver_irq_count[irq])
65  {
66  irqCountLock.acquire();
67  driver_irq_count[irq]->release();
68  irqCountLock.release();
69  }
70 
71  if (driver_irq_handler[irq]) {
72  driver_irq_handler[irq](driver_irq_device[irq]);
73  }
74 
75  return true;
76 }
77 
78 extern "C" {
79 
87 extern "C" EXPORTED_PUBLIC void cdi_register_irq(uint8_t irq, void (*handler)(struct cdi_device*),
88  struct cdi_device* device)
89 {
90  if (irq >= IRQ_COUNT) {
91  // FIXME: Eigentlich sollte diese Funktion etwas weniger optimistisch
92  // sein, und einen Rueckgabewert haben.
93  return;
94  }
95 
96  // Der Interrupt wurde schon mal registriert
97  if (driver_irq_handler[irq]) {
98  NOTICE("cdi: Versuch IRQ " << irq << " mehrfach zu registrieren");
99  return;
100  }
101 
102  if(driver_irq_count[irq])
103  delete driver_irq_count[irq];
104  driver_irq_count[irq] = new Semaphore(0);
105 
106  driver_irq_handler[irq] = handler;
107  driver_irq_device[irq] = device;
108 
109  Machine::instance().getIrqManager()->registerIsaIrqHandler(irq, static_cast<IrqHandler*>(&cdi_irq_handler));
110 }
111 
119 extern "C" EXPORTED_PUBLIC int cdi_reset_wait_irq(uint8_t irq)
120 {
121  if (irq > IRQ_COUNT) {
122  return -1;
123  }
124 
125  if(driver_irq_count[irq])
126  {
127  irqCountLock.acquire();
128  while(driver_irq_count[irq]->tryAcquire())
129  driver_irq_count[irq]->release();
130  irqCountLock.release();
131  return 0;
132  }
133 
134  return -1;
135 }
136 
137 // Dummy-Callback fuer den timer_register-Aufruf in cdi_wait_irq
138 //static void wait_irq_dummy_callback(void) { }
139 
153 extern "C" EXPORTED_PUBLIC int cdi_wait_irq(uint8_t irq, uint32_t timeout)
154 {
155  if (irq > IRQ_COUNT) {
156  return -1;
157  }
158 
159  if (!driver_irq_handler[irq]) {
160  return -2;
161  }
162 
163  Semaphore *pSem;
164 
165  {
166  LockGuard<Spinlock> lock(irqCountLock);
167 
168  pSem = driver_irq_count[irq];
169  if(!pSem)
170  {
171  pSem = new Semaphore(0);
172  driver_irq_count[irq] = pSem;
173  }
174  }
175 
176  if(pSem)
177  {
178  pSem->acquire(1, 0, timeout * 1000);
179  if(Processor::information().getCurrentThread()->wasInterrupted())
180  return -3;
181  else
182  return 0;
183  }
184  else
185  return -2;
186 }
187 }
188 
207 extern "C" EXPORTED_PUBLIC struct cdi_mem_area* cdi_mem_alloc(size_t size, cdi_mem_flags_t flags)
208 {
210 
211  MemoryRegion* region = new MemoryRegion("cdi");
212  size_t pageSize = PhysicalMemoryManager::getPageSize();
213 
214  if(!PhysicalMemoryManager::instance().allocateRegion(
215  *region, (size + (pageSize - 1)) / pageSize,
217  {
218  WARNING("cdi: cdi_mem_alloc: couldn't allocate memory");
219  delete region;
220  return 0;
221  }
222 
223  struct cdi_mem_area *ret = new struct cdi_mem_area;
224  ret->size = size;
225  ret->vaddr = region->virtualAddress();
226  ret->paddr.num = 1;
227  ret->paddr.items = new struct cdi_mem_sg_item;
228  ret->paddr.items->start = region->physicalAddress();
229  ret->paddr.items->size = size;
230  ret->osdep.pMemRegion = reinterpret_cast<void*>(region);
231  return ret;
232 }
233 
252 extern "C" EXPORTED_PUBLIC struct cdi_mem_area* cdi_mem_map(uintptr_t paddr, size_t size)
253 {
254  MemoryRegion* region = new MemoryRegion("cdi");
255  size_t pageSize = PhysicalMemoryManager::getPageSize();
256 
257  if(!PhysicalMemoryManager::instance().allocateRegion(
258  *region, (size + (pageSize - 1)) / pageSize,
260  paddr))
261  {
262  WARNING("cdi: cdi_mem_map: couldn't allocate memory");
263  delete region;
264  return 0;
265  }
266 
267  struct cdi_mem_area *ret = new struct cdi_mem_area;
268  ret->size = size;
269  ret->vaddr = region->virtualAddress();
270  ret->paddr.num = 1;
271  ret->paddr.items = new struct cdi_mem_sg_item;
272  ret->paddr.items->start = region->physicalAddress();
273  ret->paddr.items->size = size;
274  ret->osdep.pMemRegion = reinterpret_cast<void*>(region);
275  return ret;
276 }
277 
288 extern "C" EXPORTED_PUBLIC void cdi_mem_free(struct cdi_mem_area* p)
289 {
290  if(p)
291  {
292  MemoryRegion *mem = reinterpret_cast<MemoryRegion *>(p->osdep.pMemRegion);
293  delete mem;
294  delete p;
295  }
296 }
297 
325 extern "C" EXPORTED_PUBLIC struct cdi_mem_area* cdi_mem_require_flags(struct cdi_mem_area* p,
326  cdi_mem_flags_t flags)
327 {
328  // Pretend the memory area matches the given flags
330  return p;
331 }
332 
357 extern "C" EXPORTED_PUBLIC int cdi_mem_copy(struct cdi_mem_area* dest, struct cdi_mem_area* src)
358 {
359  if(dest && src && dest->size == src->size)
360  {
361  if(dest->vaddr != src->vaddr)
362  MemoryCopy(dest->vaddr, src->vaddr, src->size);
363  return 0;
364  }
365  else
366  return -1;
367 }
368 
374 extern "C" EXPORTED_PUBLIC int cdi_ioports_alloc(uint16_t start, uint16_t count)
375 {
376  // Not required in Pedigree drivers (ring0)
377  return 0;
378 }
379 
385 extern "C" EXPORTED_PUBLIC int cdi_ioports_free(uint16_t start, uint16_t count)
386 {
387  // Not required in Pedigree drivers (ring0)
388  return 0;
389 }
390 
394 extern "C" EXPORTED_PUBLIC void cdi_sleep_ms(uint32_t ms)
395 {
396  Semaphore sem(0);
397  sem.acquire(1, 0, ms * 1000);
398 }
399 
400 extern "C" EXPORTED_PUBLIC uint64_t cdi_elapsed_ms()
401 {
402  return Time::getTimeNanoseconds();
403 }
404 
405 extern "C" EXPORTED_PUBLIC uint8_t cdi_cmos_read(uint8_t index)
406 {
407  cdi_outb(0x70, index);
408  return cdi_inb(0x71);
409 }
410 
411 extern "C" EXPORTED_PUBLIC void cdi_cmos_write(uint8_t index, uint8_t value)
412 {
413  cdi_outb(0x70, index);
414  cdi_outb(0x71, value);
415 }
void release()
Definition: Spinlock.cc:273
static PhysicalMemoryManager & instance()
bool acquire(size_t n=1, size_t timeoutSecs=0, size_t timeoutUsecs=0)
Definition: Semaphore.h:62
bool acquire(bool recurse=false, bool safe=true)
Definition: Spinlock.cc:43
static ProcessorInformation & information()
Definition: Processor.cc:45
#define WARNING(text)
Definition: Log.h:78
void release(size_t n=1)
Definition: Semaphore.cc:239
#define NOTICE(text)
Definition: Log.h:74
Special memory entity in the kernel&#39;s virtual address space.
Definition: MemoryRegion.h:35
size_t size() const
Definition: MemoryRegion.cc:49
physical_uintptr_t physicalAddress() const
Definition: MemoryRegion.cc:44
virtual irq_id_t registerIsaIrqHandler(uint8_t irq, IrqHandler *handler, bool bEdge=false)=0
void * virtualAddress() const
Definition: MemoryRegion.cc:39
Definition: mem.c:283
virtual bool irq(irq_id_t number, InterruptState &state)
Definition: misc.cc:62