Subversion Repositories HelenOS

Rev

Rev 1965 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  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 */
  45. static char *basetypes[] = {
  46.     "ExceptionBlock",
  47.     "SystemParameterBlock",
  48.     "FreeContiguous",
  49.     "FreeMemory",
  50.     "BadMemory",
  51.     "LoadedProgram",
  52.     "FirmwareTemporary",
  53.     "FirmwarePermanent"
  54. };
  55.  
  56. static 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.  
  103. static arc_sbp *sbp = (arc_sbp *)PA2KA(0x1000);
  104. static arc_func_vector_t *arc_entry;
  105.  
  106.  
  107. static void arc_putchar(char ch);
  108.  
  109. /** Return true if ARC is available */
  110. int arc_enabled(void)
  111. {
  112.     return sbp != NULL;
  113. }
  114.  
  115.  
  116. /** Print configuration data that ARC reports about component */
  117. static 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 */
  161. static 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.  */
  177. static 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. }
  196. static 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.  */
  207. static 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. }
  223. static 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 */
  231. static 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.  
  243. static int cmd_reboot(cmd_arg_t *argv)
  244. {
  245.     arc_entry->reboot();
  246.     return 0;
  247. }
  248. static 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.  */
  259. int 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.  
  283. static bool kbd_polling_enabled;
  284. static chardev_t console;
  285.  
  286. /** Try to get character, return character or -1 if not available */
  287. static 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.  
  310. static 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.  
  328. static void arc_write(chardev_t *dev, const char ch)
  329. {
  330.     arc_putchar(ch);
  331. }
  332.  
  333. static void arc_enable(chardev_t *dev)
  334. {
  335.     kbd_polling_enabled = true;
  336. }
  337.  
  338. static void arc_disable(chardev_t *dev)
  339. {
  340.     kbd_polling_enabled = false;
  341. }
  342.  
  343. static chardev_operations_t arc_ops = {
  344.     .resume = arc_enable,
  345.     .suspend = arc_disable,
  346.     .write = arc_write,
  347.     .read = arc_read
  348. };
  349.  
  350. iroutine old_timer;
  351. /** Do polling on timer interrupt */
  352. static void timer_replace(int n, istate_t *istate)
  353. {
  354.     arc_keyboard_poll();
  355.     old_timer(n, istate);
  356.     arc_keyboard_poll();
  357. }
  358.  
  359. void 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.  */
  373. void 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.  
  404.