The Pedigree Project  0.1
Pit.cc
1 /*
2  * Copyright (c) 2008-2014, Pedigree Developers
3  *
4  * Please see the CONTRIB file in the root of the source tree for a full
5  * list of contributors.
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include "Pit.h"
21 #include "pedigree/kernel/compiler.h"
22 #include "pedigree/kernel/machine/IrqManager.h"
23 #include "pedigree/kernel/machine/Machine.h"
24 #include "pedigree/kernel/machine/TimerHandler.h"
25 #include "pedigree/kernel/processor/types.h"
26 
28 #ifdef BOCHS
29 #define PIT_FREQUENCY 10
30 #else
31 #define PIT_FREQUENCY 100
32 #endif
33 
35 
36 bool Pit::registerHandler(TimerHandler *handler)
37 {
38  if (UNLIKELY(handler == 0 && m_Handler != 0))
39  return false;
40 
41  m_Handler = handler;
42  return true;
43 }
44 
46 {
47  // Allocate the PIT I/O range
48  if (m_IoPort.allocate(0x40, 4) == false)
49  return false;
50 
51  // Allocate the IRQ
52  IrqManager &irqManager = *Machine::instance().getIrqManager();
53  m_IrqId = irqManager.registerIsaIrqHandler(0, this, true);
54  if (m_IrqId == 0)
55  return false;
56 
57  // Set the PIT frequency
58  // The value we send to the PIT is the value to divide it's input clock
59  // (1193180 Hz) by, to get our required frequency. Important to note is
60  // that the divisor must be small enough to fit into 16-bits.
61  size_t divisor = 1193180 / PIT_FREQUENCY;
62 
63  // Send the command byte.
64  m_IoPort.write8(0x36, 3);
65 
66  // Divisor has to be sent byte-wise, so split here into upper/lower bytes.
67  uint8_t l = divisor & 0xFF;
68  uint8_t h = (divisor >> 8) & 0xFF;
69 
70  // Send the frequency divisor.
71  m_IoPort.write8(l, 0);
72  m_IoPort.write8(h, 0);
73 
74  return true;
75 }
77 {
78  // TODO: Reset the PIT frequency
79 
80  // Free the IRQ
81  if (m_IrqId != 0)
82  {
83  IrqManager &irqManager = *Machine::instance().getIrqManager();
84  irqManager.unregisterHandler(m_IrqId, this);
85  }
86 
87  // Free the PIT I/O range
88  m_IoPort.free();
89 }
90 
91 Pit::Pit() : m_IoPort("PIT"), m_IrqId(0), m_Handler(0)
92 {
93 }
94 
95 bool Pit::irq(irq_id_t number, InterruptState &state)
96 {
97  // TODO: Delta is wrong
98  if (LIKELY(m_Handler != 0))
99  m_Handler->timer(0, state);
100 
101  // Processor::information().getScheduler().checkEventState(state.getStackPointer());
102 
103  return true;
104 }
IoPort m_IoPort
Definition: Pit.h:78
irq_id_t m_IrqId
Definition: Pit.h:80
Definition: Pit.h:36
void free()
Definition: IoPort.cc:49
void uninitialise()
Definition: Pit.cc:76
virtual void unregisterHandler(irq_id_t Id, IrqHandler *handler)=0
virtual bool irq(irq_id_t number, InterruptState &state)
Definition: Pit.cc:95
bool allocate(io_port_t ioPort, size_t size)
Definition: IoPort.cc:34
virtual void timer(uint64_t delta, InterruptState &state)=0
virtual irq_id_t registerIsaIrqHandler(uint8_t irq, IrqHandler *handler, bool bEdge=false)=0
bool initialise() INITIALISATION_ONLY
Definition: Pit.cc:45
TimerHandler * m_Handler
Definition: Pit.h:82
static Pit m_Instance
Definition: Pit.h:85
virtual void write8(uint8_t value, size_t offset=0)
Pit() INITIALISATION_ONLY
Definition: Pit.cc:91