arc.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2005 Ondrej Palkovsky
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  *
00009  * - Redistributions of source code must retain the above copyright
00010  *   notice, this list of conditions and the following disclaimer.
00011  * - Redistributions in binary form must reproduce the above copyright
00012  *   notice, this list of conditions and the following disclaimer in the
00013  *   documentation and/or other materials provided with the distribution.
00014  * - The name of the author may not be used to endorse or promote products
00015  *   derived from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00018  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00019  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00020  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
00021  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00022  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00023  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00024  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00025  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00026  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00027  */
00028 
00035 #include <arch/drivers/arc.h>
00036 #include <arch/mm/page.h>
00037 #include <print.h>
00038 #include <arch.h>
00039 #include <arch/byteorder.h>
00040 #include <arch/mm/frame.h>
00041 #include <mm/frame.h>
00042 #include <interrupt.h>
00043 #include <align.h>
00044 #include <console/console.h>
00045 #include <console/kconsole.h>
00046 #include <console/cmd.h>
00047 #include <mm/slab.h>
00048 
00049 /* This is a good joke, SGI HAS different types than NT bioses... */
00050 /* Here is the SGI type */
00051 static char *basetypes[] = {
00052         "ExceptionBlock",
00053         "SystemParameterBlock",
00054         "FreeContiguous",
00055         "FreeMemory",
00056         "BadMemory",
00057         "LoadedProgram",
00058         "FirmwareTemporary",
00059         "FirmwarePermanent"
00060 };
00061 
00062 static char *ctypes[] = {
00063         "ARC_type",
00064         "CPU_type",
00065         "FPU_type",
00066         "PrimaryICache",
00067         "PrimaryDCache",
00068         "SecondaryICache",
00069         "SecondaryDCache",
00070         "SecondaryCache",
00071         "Memory",
00072         "EISAAdapter",
00073         "TCAdapter",
00074         "SCSIAdapter",
00075         "DTIAdapter",
00076         "MultiFunctionAdapter",
00077         "DiskController",
00078         "TapeController",
00079         "CDROMController",
00080         "WORMController",
00081         "SerialController",
00082         "NetworkController",
00083         "DisplayController",
00084         "ParallelController",
00085         "PointerController",
00086         "KeyboardController",
00087         "AudioController",
00088         "OtherController",
00089         "DiskPeripheral",
00090         "FloppyDiskPeripheral",
00091         "TapePeripheral",
00092         "ModemPeripheral",
00093         "MonitorPeripheral",
00094         "PrinterPeripheral",
00095         "PointerPeripheral",
00096         "KeyboardPeripheral",
00097         "TerminalPeripheral",
00098         "OtherPeripheral",
00099         "LinePeripheral",
00100         "NetworkPeripheral"
00101         "OtherPeripheral",
00102         "XTalkAdapter",
00103         "PCIAdapter",
00104         "GIOAdapter",
00105         "TPUAdapter",
00106         "Anonymous"
00107 };
00108 
00109 static arc_sbp *sbp = (arc_sbp *)PA2KA(0x1000);
00110 static arc_func_vector_t *arc_entry; 
00111 
00112 
00113 static void arc_putchar(char ch);
00114 
00116 int arc_enabled(void)
00117 {
00118         return sbp != NULL;
00119 }
00120 
00121 
00123 static void arc_print_confdata(arc_component *c)
00124 {
00125         cm_resource_list *configdata;
00126         int i;
00127 
00128         if (!c->configdatasize)
00129                 return; /* No configuration data */
00130 
00131         configdata = malloc(c->configdatasize, 0);
00132 
00133         if (arc_entry->getconfigurationdata(configdata, c)) {
00134                 free(configdata);
00135                 return;
00136         }
00137         /* Does not seem to return meaningful data, don't use now */
00138         free(configdata);
00139         return;
00140         
00141         for (i=0; i < configdata->count; i++) {
00142                 switch (configdata->descr[i].type) {
00143                 case CmResourceTypePort:
00144                         printf("Port: %p-size:%d ",
00145                                (__address)configdata->descr[i].u.port.start,
00146                                configdata->descr[i].u.port.length);
00147                         break;
00148                 case CmResourceTypeInterrupt:
00149                         printf("Irq: level(%d) vector(%d) ",
00150                                configdata->descr[i].u.interrupt.level,
00151                                configdata->descr[i].u.interrupt.vector);
00152                         break;
00153                 case CmResourceTypeMemory:
00154                         printf("Memory: %p-size:%d ",
00155                                (__address)configdata->descr[i].u.port.start,
00156                                configdata->descr[i].u.port.length);
00157                         break;
00158                 default:
00159                         break;
00160                 }
00161         }
00162 
00163         free(configdata);
00164 }
00165 
00167 static void arc_print_component(arc_component *c)
00168 {
00169         int i;
00170 
00171         printf("%s: ",ctypes[c->type]);
00172         for (i=0;i < c->identifier_len;i++)
00173                 printf("%c",c->identifier[i]);
00174 
00175         printf(" ");
00176         arc_print_confdata(c);
00177         printf("\n");
00178 }
00179 
00183 static int cmd_arc_print_devices(cmd_arg_t *argv)
00184 {
00185         arc_component *c,*next;
00186 
00187         c = arc_entry->getchild(NULL);
00188         while (c) {
00189                 arc_print_component(c);
00190                 next = arc_entry->getchild(c);
00191                 while (!next) {
00192                         next = arc_entry->getpeer(c);
00193                         if (!next)
00194                                 c = arc_entry->getparent(c);
00195                         if (!c)
00196                                 return 0;
00197                 }
00198                 c = next;
00199         }
00200         return 1;
00201 }
00202 static cmd_info_t devlist_info = {
00203         .name = "arcdevlist",
00204         .description = "Print arc device list",
00205         .func = cmd_arc_print_devices,
00206         .argc = 0
00207 };
00208 
00209 
00213 static int cmd_arc_print_memmap(cmd_arg_t *argv)
00214 {
00215         arc_memdescriptor_t *desc;
00216 
00217         printf("Memory map:\n");
00218 
00219         desc = arc_entry->getmemorydescriptor(NULL);
00220         while (desc) {
00221                 printf("%s: %d(%p) (size: %dKB)\n",basetypes[desc->type],
00222                        desc->basepage * ARC_FRAME,
00223                        desc->basepage * ARC_FRAME,
00224                        desc->basecount*ARC_FRAME/1024);
00225                 desc = arc_entry->getmemorydescriptor(desc);
00226         }
00227         return 1;
00228 }
00229 static cmd_info_t memmap_info = {
00230         .name = "arcmemmap",
00231         .description = "Print arc memory map",
00232         .func = cmd_arc_print_memmap,
00233         .argc = 0
00234 };
00235 
00237 static void arc_putchar(char ch)
00238 {
00239         __u32 cnt;
00240         ipl_t ipl;
00241 
00242         /* TODO: Should be spinlock? */
00243         ipl = interrupts_disable();
00244         arc_entry->write(1, &ch, 1, &cnt);
00245         interrupts_restore(ipl);
00246         
00247 }
00248 
00249 static int cmd_reboot(cmd_arg_t *argv)
00250 {
00251         arc_entry->reboot();
00252         return 0;
00253 }
00254 static cmd_info_t reboot_info = {
00255         .name = "reboot",
00256         .description = "Reboot computer",
00257         .func = cmd_reboot,
00258         .argc = 0
00259 };
00260 
00265 int arc_init(void)
00266 {
00267         if (sbp->signature != ARC_MAGIC) {
00268                 sbp = NULL;
00269                 return -1;
00270         }
00271         arc_entry = sbp->firmwarevector;
00272 
00273         arc_putchar('A');
00274         arc_putchar('R');
00275         arc_putchar('C');
00276         arc_putchar('\n');
00277 
00278         /* Add command for resetting the computer */
00279         cmd_initialize(&reboot_info);
00280         cmd_register(&reboot_info);
00281         cmd_initialize(&memmap_info);
00282         cmd_register(&memmap_info);
00283         cmd_initialize(&devlist_info);
00284         cmd_register(&devlist_info);
00285 
00286         return 0;
00287 }
00288 
00289 static bool kbd_polling_enabled;
00290 static chardev_t console;
00291 
00293 static void arc_keyboard_poll(void)
00294 {
00295         char ch;
00296         __u32 count;
00297         long result;
00298         
00299         if (! kbd_polling_enabled)
00300                 return;
00301 
00302         if (arc_entry->getreadstatus(0))
00303                 return;
00304         result = arc_entry->read(0, &ch, 1, &count);
00305         if (result || count!=1) {
00306                 return;
00307         }
00308         if (ch == '\r')
00309                 ch = '\n';
00310         if (ch == 0x7f)
00311                 ch = '\b';
00312         
00313         chardev_push_character(&console, ch);
00314 }
00315 
00316 static char arc_read(chardev_t *dev)
00317 {
00318         char ch;
00319         __u32 count;
00320         long result;
00321 
00322         result = arc_entry->read(0, &ch, 1, &count);
00323         if (result || count!=1) {
00324                 printf("Error reading from ARC keyboard.\n");
00325                 cpu_halt();
00326         }
00327         if (ch == '\r')
00328                 return '\n';
00329         if (ch == 0x7f)
00330                 return '\b';
00331         return ch;
00332 }
00333 
00334 static void arc_write(chardev_t *dev, const char ch)
00335 {
00336         arc_putchar(ch);
00337 }
00338 
00339 static void arc_enable(chardev_t *dev)
00340 {
00341         kbd_polling_enabled = true;
00342 }
00343 
00344 static void arc_disable(chardev_t *dev)
00345 {
00346         kbd_polling_enabled = false;
00347 }
00348 
00349 static chardev_operations_t arc_ops = {
00350         .resume = arc_enable,
00351         .suspend = arc_disable,
00352         .write = arc_write,
00353         .read = arc_read
00354 };
00355 
00356 iroutine old_timer;
00358 static void timer_replace(int n, istate_t *istate)
00359 {
00360         arc_keyboard_poll();
00361         old_timer(n, istate);
00362         arc_keyboard_poll();
00363 }
00364 
00365 void arc_console(void)
00366 {
00367         kbd_polling_enabled = true;
00368         
00369         chardev_initialize("arc_console", &console, &arc_ops);
00370         old_timer = int_register(TIMER_IRQ, "arc_kb_poll", timer_replace);
00371         stdin = &console;
00372         stdout = &console;
00373 }
00374 
00375 /* Initialize frame zones from ARC firmware. 
00376  * In the future we may use even the FirmwareTemporary regions,
00377  * currently we use the FreeMemory (what about the LoadedProgram?)
00378  */
00379 void arc_frame_init(void)
00380 {
00381         arc_memdescriptor_t *desc;
00382         int total = 0;
00383         __address base;
00384         size_t basesize;
00385 
00386         desc = arc_entry->getmemorydescriptor(NULL);
00387         while (desc) {
00388                 if (desc->type == FreeMemory ||
00389                     desc->type == FreeContiguous) {
00390                         base = desc->basepage*ARC_FRAME;
00391                         basesize = desc->basecount*ARC_FRAME;
00392 
00393                         if (base % FRAME_SIZE ) {
00394                                 basesize -= FRAME_SIZE - (base % FRAME_SIZE);
00395                                 base = ALIGN_UP(base, FRAME_SIZE);
00396                         }
00397                         basesize = ALIGN_DOWN(basesize, FRAME_SIZE);
00398 
00399                         total += basesize;
00400                         
00401                         zone_create(ADDR2PFN(base), SIZE2FRAMES(basesize),
00402                                     ADDR2PFN(base), 0);
00403                 }
00404                 desc = arc_entry->getmemorydescriptor(desc);
00405         }
00406 
00407         config.memory_size = total;
00408 }
00409 
00410 

Generated on Sun Jun 18 17:01:57 2006 for HelenOS Kernel (mips32) by  doxygen 1.4.6