source: mainline/kernel/arch/mips32/src/interrupt.c@ 3061bc1

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 3061bc1 was 24abb85d, checked in by Jakub Jermar <jakub@…>, 8 years ago

Remove SYS_DEVICE_ASSIGN_DEVNO

  • Property mode set to 100644
File size: 4.6 KB
Line 
1/*
2 * Copyright (c) 2003-2004 Jakub Jermar
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup mips32interrupt
30 * @{
31 */
32/** @file
33 */
34
35#include <interrupt.h>
36#include <arch/interrupt.h>
37#include <typedefs.h>
38#include <arch.h>
39#include <arch/cp0.h>
40#include <arch/smp/dorder.h>
41#include <time/clock.h>
42#include <ipc/sysipc.h>
43
44#define IRQ_COUNT 8
45#define TIMER_IRQ 7
46
47#ifdef MACHINE_msim
48#define DORDER_IRQ 5
49#endif
50
51function virtual_timer_fnc = NULL;
52static irq_t timer_irq;
53
54#ifdef MACHINE_msim
55static irq_t dorder_irq;
56#endif
57
58// TODO: This is SMP unsafe!!!
59
60uint32_t count_hi = 0;
61static unsigned long nextcount;
62static unsigned long lastcount;
63
64/** Disable interrupts.
65 *
66 * @return Old interrupt priority level.
67 */
68ipl_t interrupts_disable(void)
69{
70 ipl_t ipl = (ipl_t) cp0_status_read();
71 cp0_status_write(ipl & ~cp0_status_ie_enabled_bit);
72 return ipl;
73}
74
75/** Enable interrupts.
76 *
77 * @return Old interrupt priority level.
78 */
79ipl_t interrupts_enable(void)
80{
81 ipl_t ipl = (ipl_t) cp0_status_read();
82 cp0_status_write(ipl | cp0_status_ie_enabled_bit);
83 return ipl;
84}
85
86/** Restore interrupt priority level.
87 *
88 * @param ipl Saved interrupt priority level.
89 */
90void interrupts_restore(ipl_t ipl)
91{
92 cp0_status_write(cp0_status_read() | (ipl & cp0_status_ie_enabled_bit));
93}
94
95/** Read interrupt priority level.
96 *
97 * @return Current interrupt priority level.
98 */
99ipl_t interrupts_read(void)
100{
101 return cp0_status_read();
102}
103
104/** Check interrupts state.
105 *
106 * @return True if interrupts are disabled.
107 *
108 */
109bool interrupts_disabled(void)
110{
111 return !(cp0_status_read() & cp0_status_ie_enabled_bit);
112}
113
114/** Start hardware clock
115 *
116 */
117static void timer_start(void)
118{
119 lastcount = cp0_count_read();
120 nextcount = cp0_compare_value + cp0_count_read();
121 cp0_compare_write(nextcount);
122}
123
124static irq_ownership_t timer_claim(irq_t *irq)
125{
126 return IRQ_ACCEPT;
127}
128
129static void timer_irq_handler(irq_t *irq)
130{
131 if (cp0_count_read() < lastcount)
132 /* Count overflow detected */
133 count_hi++;
134
135 lastcount = cp0_count_read();
136
137 unsigned long drift = cp0_count_read() - nextcount;
138 while (drift > cp0_compare_value) {
139 drift -= cp0_compare_value;
140 CPU->missed_clock_ticks++;
141 }
142
143 nextcount = cp0_count_read() + cp0_compare_value - drift;
144 cp0_compare_write(nextcount);
145
146 /*
147 * We are holding a lock which prevents preemption.
148 * Release the lock, call clock() and reacquire the lock again.
149 */
150 irq_spinlock_unlock(&irq->lock, false);
151 clock();
152 irq_spinlock_lock(&irq->lock, false);
153
154 if (virtual_timer_fnc != NULL)
155 virtual_timer_fnc();
156}
157
158#ifdef MACHINE_msim
159static irq_ownership_t dorder_claim(irq_t *irq)
160{
161 return IRQ_ACCEPT;
162}
163
164static void dorder_irq_handler(irq_t *irq)
165{
166 dorder_ipi_ack(1 << dorder_cpuid());
167}
168#endif
169
170/* Initialize basic tables for exception dispatching */
171void interrupt_init(void)
172{
173 irq_init(IRQ_COUNT, IRQ_COUNT);
174
175 irq_initialize(&timer_irq);
176 timer_irq.inr = TIMER_IRQ;
177 timer_irq.claim = timer_claim;
178 timer_irq.handler = timer_irq_handler;
179 irq_register(&timer_irq);
180
181 timer_start();
182 cp0_unmask_int(TIMER_IRQ);
183
184#ifdef MACHINE_msim
185 irq_initialize(&dorder_irq);
186 dorder_irq.inr = DORDER_IRQ;
187 dorder_irq.claim = dorder_claim;
188 dorder_irq.handler = dorder_irq_handler;
189 irq_register(&dorder_irq);
190
191 cp0_unmask_int(DORDER_IRQ);
192#endif
193}
194
195/** @}
196 */
Note: See TracBrowser for help on using the repository browser.