source: mainline/arch/mips32/src/drivers/arc.c@ 25d7709

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

Nicer ia32 interrupt handlers and structures holding interrupted context data.
Unify the name holding interrupted context data on all architectures to be istate.

  • Property mode set to 100644
File size: 8.8 KB
Line 
1/*
2 * Copyright (C) 2005 Ondrej Palkovsky
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#include <arch/drivers/arc.h>
30#include <arch/mm/page.h>
31#include <print.h>
32#include <arch.h>
33#include <arch/byteorder.h>
34#include <arch/mm/frame.h>
35#include <mm/frame.h>
36#include <interrupt.h>
37#include <align.h>
38#include <console/console.h>
39#include <console/kconsole.h>
40#include <console/cmd.h>
41#include <mm/slab.h>
42
43/* This is a good joke, SGI HAS different types than NT bioses... */
44/* Here is the SGI type */
45static char *basetypes[] = {
46 "ExceptionBlock",
47 "SystemParameterBlock",
48 "FreeContiguous",
49 "FreeMemory",
50 "BadMemory",
51 "LoadedProgram",
52 "FirmwareTemporary",
53 "FirmwarePermanent"
54};
55
56static char *ctypes[] = {
57 "ARC_type",
58 "CPU_type",
59 "FPU_type",
60 "PrimaryICache",
61 "PrimaryDCache",
62 "SecondaryICache",
63 "SecondaryDCache",
64 "SecondaryCache",
65 "Memory",
66 "EISAAdapter",
67 "TCAdapter",
68 "SCSIAdapter",
69 "DTIAdapter",
70 "MultiFunctionAdapter",
71 "DiskController",
72 "TapeController",
73 "CDROMController",
74 "WORMController",
75 "SerialController",
76 "NetworkController",
77 "DisplayController",
78 "ParallelController",
79 "PointerController",
80 "KeyboardController",
81 "AudioController",
82 "OtherController",
83 "DiskPeripheral",
84 "FloppyDiskPeripheral",
85 "TapePeripheral",
86 "ModemPeripheral",
87 "MonitorPeripheral",
88 "PrinterPeripheral",
89 "PointerPeripheral",
90 "KeyboardPeripheral",
91 "TerminalPeripheral",
92 "OtherPeripheral",
93 "LinePeripheral",
94 "NetworkPeripheral"
95 "OtherPeripheral",
96 "XTalkAdapter",
97 "PCIAdapter",
98 "GIOAdapter",
99 "TPUAdapter",
100 "Anonymous"
101};
102
103static arc_sbp *sbp = (arc_sbp *)PA2KA(0x1000);
104static arc_func_vector_t *arc_entry;
105
106
107static void arc_putchar(char ch);
108
109/** Return true if ARC is available */
110int arc_enabled(void)
111{
112 return sbp != NULL;
113}
114
115
116/** Print configuration data that ARC reports about component */
117static void arc_print_confdata(arc_component *c)
118{
119 cm_resource_list *configdata;
120 int i;
121
122 if (!c->configdatasize)
123 return; /* No configuration data */
124
125 configdata = malloc(c->configdatasize, 0);
126
127 if (arc_entry->getconfigurationdata(configdata, c)) {
128 free(configdata);
129 return;
130 }
131 /* Does not seem to return meaningful data, don't use now */
132 free(configdata);
133 return;
134
135 for (i=0; i < configdata->count; i++) {
136 switch (configdata->descr[i].type) {
137 case CmResourceTypePort:
138 printf("Port: %P-size:%d ",
139 (__address)configdata->descr[i].u.port.start,
140 configdata->descr[i].u.port.length);
141 break;
142 case CmResourceTypeInterrupt:
143 printf("Irq: level(%d) vector(%d) ",
144 configdata->descr[i].u.interrupt.level,
145 configdata->descr[i].u.interrupt.vector);
146 break;
147 case CmResourceTypeMemory:
148 printf("Memory: %P-size:%d ",
149 (__address)configdata->descr[i].u.port.start,
150 configdata->descr[i].u.port.length);
151 break;
152 default:
153 break;
154 }
155 }
156
157 free(configdata);
158}
159
160/** Print information about component */
161static void arc_print_component(arc_component *c)
162{
163 int i;
164
165 printf("%s: ",ctypes[c->type]);
166 for (i=0;i < c->identifier_len;i++)
167 printf("%c",c->identifier[i]);
168
169 printf(" ");
170 arc_print_confdata(c);
171 printf("\n");
172}
173
174/**
175 * Read from ARC bios configuration data and print it
176 */
177static int cmd_arc_print_devices(cmd_arg_t *argv)
178{
179 arc_component *c,*next;
180
181 c = arc_entry->getchild(NULL);
182 while (c) {
183 arc_print_component(c);
184 next = arc_entry->getchild(c);
185 while (!next) {
186 next = arc_entry->getpeer(c);
187 if (!next)
188 c = arc_entry->getparent(c);
189 if (!c)
190 return 0;
191 }
192 c = next;
193 }
194 return 1;
195}
196static cmd_info_t devlist_info = {
197 .name = "arcdevlist",
198 .description = "Print arc device list",
199 .func = cmd_arc_print_devices,
200 .argc = 0
201};
202
203
204/** Read from arc bios memory map and print it
205 *
206 */
207static int cmd_arc_print_memmap(cmd_arg_t *argv)
208{
209 arc_memdescriptor_t *desc;
210
211 printf("Memory map:\n");
212
213 desc = arc_entry->getmemorydescriptor(NULL);
214 while (desc) {
215 printf("%s: %d(%P) (size: %dKB)\n",basetypes[desc->type],
216 desc->basepage * ARC_FRAME,
217 desc->basepage * ARC_FRAME,
218 desc->basecount*ARC_FRAME/1024);
219 desc = arc_entry->getmemorydescriptor(desc);
220 }
221 return 1;
222}
223static cmd_info_t memmap_info = {
224 .name = "arcmemmap",
225 .description = "Print arc memory map",
226 .func = cmd_arc_print_memmap,
227 .argc = 0
228};
229
230/** Print charactor to console */
231static void arc_putchar(char ch)
232{
233 __u32 cnt;
234 ipl_t ipl;
235
236 /* TODO: Should be spinlock? */
237 ipl = interrupts_disable();
238 arc_entry->write(1, &ch, 1, &cnt);
239 interrupts_restore(ipl);
240
241}
242
243static int cmd_reboot(cmd_arg_t *argv)
244{
245 arc_entry->reboot();
246 return 0;
247}
248static cmd_info_t reboot_info = {
249 .name = "reboot",
250 .description = "Reboot computer",
251 .func = cmd_reboot,
252 .argc = 0
253};
254
255/** Initialize ARC structure
256 *
257 * @return 0 - ARC OK, -1 - ARC does not exist
258 */
259int arc_init(void)
260{
261 if (sbp->signature != ARC_MAGIC) {
262 sbp = NULL;
263 return -1;
264 }
265 arc_entry = sbp->firmwarevector;
266
267 arc_putchar('A');
268 arc_putchar('R');
269 arc_putchar('C');
270 arc_putchar('\n');
271
272 /* Add command for resetting the computer */
273 cmd_initialize(&reboot_info);
274 cmd_register(&reboot_info);
275 cmd_initialize(&memmap_info);
276 cmd_register(&memmap_info);
277 cmd_initialize(&devlist_info);
278 cmd_register(&devlist_info);
279
280 return 0;
281}
282
283static bool kbd_polling_enabled;
284static chardev_t console;
285
286/** Try to get character, return character or -1 if not available */
287static void arc_keyboard_poll(void)
288{
289 char ch;
290 __u32 count;
291 long result;
292
293 if (! kbd_polling_enabled)
294 return;
295
296 if (arc_entry->getreadstatus(0))
297 return;
298 result = arc_entry->read(0, &ch, 1, &count);
299 if (result || count!=1) {
300 return;
301 }
302 if (ch == '\r')
303 ch = '\n';
304 if (ch == 0x7f)
305 ch = '\b';
306
307 chardev_push_character(&console, ch);
308}
309
310static char arc_read(chardev_t *dev)
311{
312 char ch;
313 __u32 count;
314 long result;
315
316 result = arc_entry->read(0, &ch, 1, &count);
317 if (result || count!=1) {
318 printf("Error reading from ARC keyboard.\n");
319 cpu_halt();
320 }
321 if (ch == '\r')
322 return '\n';
323 if (ch == 0x7f)
324 return '\b';
325 return ch;
326}
327
328static void arc_write(chardev_t *dev, const char ch)
329{
330 arc_putchar(ch);
331}
332
333static void arc_enable(chardev_t *dev)
334{
335 kbd_polling_enabled = true;
336}
337
338static void arc_disable(chardev_t *dev)
339{
340 kbd_polling_enabled = false;
341}
342
343static chardev_operations_t arc_ops = {
344 .resume = arc_enable,
345 .suspend = arc_disable,
346 .write = arc_write,
347 .read = arc_read
348};
349
350iroutine old_timer;
351/** Do polling on timer interrupt */
352static void timer_replace(int n, istate_t *istate)
353{
354 arc_keyboard_poll();
355 old_timer(n, istate);
356 arc_keyboard_poll();
357}
358
359void arc_console(void)
360{
361 kbd_polling_enabled = true;
362
363 chardev_initialize("arc_console", &console, &arc_ops);
364 old_timer = int_register(TIMER_IRQ, "arc_kb_poll", timer_replace);
365 stdin = &console;
366 stdout = &console;
367}
368
369/* Initialize frame zones from ARC firmware.
370 * In the future we may use even the FirmwareTemporary regions,
371 * currently we use the FreeMemory (what about the LoadedProgram?)
372 */
373void arc_frame_init(void)
374{
375 arc_memdescriptor_t *desc;
376 int total = 0;
377 __address base;
378 size_t basesize;
379
380 desc = arc_entry->getmemorydescriptor(NULL);
381 while (desc) {
382 if (desc->type == FreeMemory ||
383 desc->type == FreeContiguous) {
384 base = desc->basepage*ARC_FRAME;
385 basesize = desc->basecount*ARC_FRAME;
386
387 if (base % FRAME_SIZE ) {
388 basesize -= FRAME_SIZE - (base % FRAME_SIZE);
389 base = ALIGN_UP(base, FRAME_SIZE);
390 }
391 basesize = ALIGN_DOWN(basesize, FRAME_SIZE);
392
393 total += basesize;
394
395 zone_create(ADDR2PFN(base), SIZE2FRAMES(basesize),
396 ADDR2PFN(base), 0);
397 }
398 desc = arc_entry->getmemorydescriptor(desc);
399 }
400
401 config.memory_size = total;
402}
403
Note: See TracBrowser for help on using the repository browser.