Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
script3r
GitHub Repository: script3r/os161
Path: blob/master/kern/arch/sys161/dev/lamebus_machdep.c
2127 views
1
/*
2
* Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009
3
* The President and Fellows of Harvard College.
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
* 1. Redistributions of source code must retain the above copyright
9
* notice, this list of conditions and the following disclaimer.
10
* 2. Redistributions in binary form must reproduce the above copyright
11
* notice, this list of conditions and the following disclaimer in the
12
* documentation and/or other materials provided with the distribution.
13
* 3. Neither the name of the University nor the names of its contributors
14
* may be used to endorse or promote products derived from this software
15
* without specific prior written permission.
16
*
17
* THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
18
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
* ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
21
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27
* SUCH DAMAGE.
28
*/
29
30
#include <types.h>
31
#include <kern/unistd.h>
32
#include <lib.h>
33
#include <mips/trapframe.h>
34
#include <cpu.h>
35
#include <spl.h>
36
#include <clock.h>
37
#include <thread.h>
38
#include <current.h>
39
#include <synch.h>
40
#include <mainbus.h>
41
#include <sys161/bus.h>
42
#include <lamebus/lamebus.h>
43
#include "autoconf.h"
44
45
/*
46
* CPU frequency used by the on-chip timer.
47
*
48
* Note that we really ought to measure the CPU frequency against the
49
* real-time clock instead of compiling it in like this.
50
*/
51
#define CPU_FREQUENCY 25000000 /* 25 MHz */
52
53
/*
54
* Access to the on-chip timer.
55
*
56
* The c0_count register increments on every cycle; when the value
57
* matches the c0_compare register, the timer interrupt line is
58
* asserted. Writing to c0_compare again clears the interrupt.
59
*/
60
static
61
void
62
mips_timer_set(uint32_t count)
63
{
64
/*
65
* $11 == c0_compare; we can't use the symbolic name inside
66
* the asm string.
67
*/
68
__asm volatile(
69
".set push;" /* save assembler mode */
70
".set mips32;" /* allow MIPS32 registers */
71
"mtc0 %0, $11;" /* do it */
72
".set pop" /* restore assembler mode */
73
:: "r" (count));
74
}
75
76
/*
77
* LAMEbus data for the system. (We have only one LAMEbus per system.)
78
* This does not need to be locked, because it's constant once
79
* initialized, and initialized before we start other threads or CPUs.
80
*/
81
static struct lamebus_softc *lamebus;
82
83
void
84
mainbus_bootstrap(void)
85
{
86
/* Interrupts should be off (and have been off since startup) */
87
KASSERT(curthread->t_curspl > 0);
88
89
/* Initialize the system LAMEbus data */
90
lamebus = lamebus_init();
91
92
/* Probe CPUs (should these be done as device attachments instead?) */
93
lamebus_find_cpus(lamebus);
94
95
/*
96
* Print the device name for the main bus.
97
*/
98
kprintf("lamebus0 (system main bus)\n");
99
100
/*
101
* Now we can take interrupts without croaking, so turn them on.
102
* Some device probes might require being able to get interrupts.
103
*/
104
105
spl0();
106
107
/*
108
* Now probe all the devices attached to the bus.
109
* (This amounts to all devices.)
110
*/
111
autoconf_lamebus(lamebus, 0);
112
113
/*
114
* Configure the MIPS on-chip timer to interrupt HZ times a second.
115
*/
116
mips_timer_set(CPU_FREQUENCY / HZ);
117
}
118
119
/*
120
* Start all secondary CPUs.
121
*/
122
void
123
mainbus_start_cpus(void)
124
{
125
lamebus_start_cpus(lamebus);
126
}
127
128
/*
129
* Function to generate the memory address (in the uncached segment)
130
* for the specified offset into the specified slot's region of the
131
* LAMEbus.
132
*/
133
void *
134
lamebus_map_area(struct lamebus_softc *bus, int slot, uint32_t offset)
135
{
136
uint32_t address;
137
138
(void)bus; // not needed
139
140
KASSERT(slot >= 0 && slot < LB_NSLOTS);
141
142
address = LB_BASEADDR + slot*LB_SLOT_SIZE + offset;
143
return (void *)address;
144
}
145
146
/*
147
* Read a 32-bit register from a LAMEbus device.
148
*/
149
uint32_t
150
lamebus_read_register(struct lamebus_softc *bus, int slot, uint32_t offset)
151
{
152
uint32_t *ptr = lamebus_map_area(bus, slot, offset);
153
154
return *ptr;
155
}
156
157
/*
158
* Write a 32-bit register of a LAMEbus device.
159
*/
160
void
161
lamebus_write_register(struct lamebus_softc *bus, int slot,
162
uint32_t offset, uint32_t val)
163
{
164
uint32_t *ptr = lamebus_map_area(bus, slot, offset);
165
166
*ptr = val;
167
}
168
169
170
/*
171
* Power off the system.
172
*/
173
void
174
mainbus_poweroff(void)
175
{
176
/*
177
*
178
* Note that lamebus_write_register() doesn't actually access
179
* the bus argument, so this will still work if we get here
180
* before the bus is initialized.
181
*/
182
lamebus_poweroff(lamebus);
183
}
184
185
/*
186
* Reboot the system.
187
*/
188
void
189
mainbus_reboot(void)
190
{
191
/*
192
* The MIPS doesn't appear to have any on-chip reset.
193
* LAMEbus doesn't have a reset control, so we just
194
* power off instead of rebooting. This would not be
195
* so great in a real system, but it's fine for what
196
* we're doing.
197
*/
198
kprintf("Cannot reboot - powering off instead, sorry.\n");
199
mainbus_poweroff();
200
}
201
202
/*
203
* Halt the system.
204
* On some systems, this would return to the boot monitor. But we don't
205
* have one.
206
*/
207
void
208
mainbus_halt(void)
209
{
210
cpu_halt();
211
}
212
213
/*
214
* Called to reset the system from panic().
215
*
216
* By the time we get here, the system may well be sufficiently hosed
217
* as to panic recursively if we do much of anything. So just power off.
218
* (We'd reboot, but System/161 doesn't do that.)
219
*/
220
void
221
mainbus_panic(void)
222
{
223
mainbus_poweroff();
224
}
225
226
/*
227
* Function to get the size of installed physical RAM from the LAMEbus
228
* controller.
229
*/
230
uint32_t
231
mainbus_ramsize(void)
232
{
233
return lamebus_ramsize();
234
}
235
236
/*
237
* Send IPI.
238
*/
239
void
240
mainbus_send_ipi(struct cpu *target)
241
{
242
lamebus_assert_ipi(lamebus, target);
243
}
244
245
/*
246
* Interrupt dispatcher.
247
*/
248
249
/* Wiring of LAMEbus interrupts to bits in the cause register */
250
#define LAMEBUS_IRQ_BIT 0x00000400 /* all system bus slots */
251
#define LAMEBUS_IPI_BIT 0x00000800 /* inter-processor interrupt */
252
#define MIPS_TIMER_BIT 0x00008000 /* on-chip timer */
253
254
void
255
mainbus_interrupt(struct trapframe *tf)
256
{
257
uint32_t cause;
258
259
/* interrupts should be off */
260
KASSERT(curthread->t_curspl > 0);
261
262
cause = tf->tf_cause;
263
if (cause & LAMEBUS_IRQ_BIT) {
264
lamebus_interrupt(lamebus);
265
}
266
else if (cause & LAMEBUS_IPI_BIT) {
267
interprocessor_interrupt();
268
lamebus_clear_ipi(lamebus, curcpu);
269
}
270
else if (cause & MIPS_TIMER_BIT) {
271
/* Reset the timer (this clears the interrupt) */
272
mips_timer_set(CPU_FREQUENCY / HZ);
273
/* and call hardclock */
274
hardclock();
275
}
276
else {
277
panic("Unknown interrupt; cause register is %08x\n", cause);
278
}
279
}
280
281