Subversion Repositories HelenOS

Rev

Rev 1984 | Rev 2089 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright (c) 2006 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 sparc64
  30.  * @{
  31.  */
  32. /**
  33.  * @file
  34.  * @brief   PCI driver.
  35.  */
  36.  
  37. #include <arch/drivers/pci.h>
  38. #include <genarch/ofw/ofw_tree.h>
  39. #include <arch/trap/interrupt.h>
  40. #include <arch/mm/page.h>
  41. #include <mm/slab.h>
  42. #include <arch/types.h>
  43. #include <typedefs.h>
  44. #include <debug.h>
  45. #include <print.h>
  46. #include <func.h>
  47. #include <arch/asm.h>
  48.  
  49. #define PCI_SABRE_REGS_REG  0
  50.  
  51. #define PCI_SABRE_IMAP_BASE 0x200
  52. #define PCI_SABRE_ICLR_BASE 0x300
  53.  
  54. #define PCI_PSYCHO_REGS_REG 2  
  55.  
  56. #define PCI_PSYCHO_IMAP_BASE    0x200
  57. #define PCI_PSYCHO_ICLR_BASE    0x300  
  58.  
  59. static pci_t *pci_sabre_init(ofw_tree_node_t *node);
  60. static void pci_sabre_enable_interrupt(pci_t *pci, int inr);
  61. static void pci_sabre_clear_interrupt(pci_t *pci, int inr);
  62.  
  63. static pci_t *pci_psycho_init(ofw_tree_node_t *node);
  64. static void pci_psycho_enable_interrupt(pci_t *pci, int inr);
  65. static void pci_psycho_clear_interrupt(pci_t *pci, int inr);
  66.  
  67. /** PCI operations for Sabre model. */
  68. static pci_operations_t pci_sabre_ops = {
  69.     .enable_interrupt = pci_sabre_enable_interrupt,
  70.     .clear_interrupt = pci_sabre_clear_interrupt
  71. };
  72. /** PCI operations for Psycho model. */
  73. static pci_operations_t pci_psycho_ops = {
  74.     .enable_interrupt = pci_psycho_enable_interrupt,
  75.     .clear_interrupt = pci_psycho_clear_interrupt
  76. };
  77.  
  78. /** Initialize PCI controller (model Sabre).
  79.  *
  80.  * @param node OpenFirmware device tree node of the Sabre.
  81.  *
  82.  * @return Address of the initialized PCI structure.
  83.  */
  84. pci_t *pci_sabre_init(ofw_tree_node_t *node)
  85. {
  86.     pci_t *pci;
  87.     ofw_tree_property_t *prop;
  88.  
  89.     /*
  90.      * Get registers.
  91.      */
  92.     prop = ofw_tree_getprop(node, "reg");
  93.     if (!prop || !prop->value)
  94.         return NULL;
  95.  
  96.     ofw_upa_reg_t *reg = prop->value;
  97.     count_t regs = prop->size / sizeof(ofw_upa_reg_t);
  98.  
  99.     if (regs < PCI_SABRE_REGS_REG + 1)
  100.         return NULL;
  101.  
  102.     uintptr_t paddr;
  103.     if (!ofw_upa_apply_ranges(node->parent, &reg[PCI_SABRE_REGS_REG], &paddr))
  104.         return NULL;
  105.  
  106.     pci = (pci_t *) malloc(sizeof(pci_t), FRAME_ATOMIC);
  107.     if (!pci)
  108.         return NULL;
  109.  
  110.     pci->model = PCI_SABRE;
  111.     pci->op = &pci_sabre_ops;
  112.     pci->reg = (uint64_t *) hw_map(paddr, reg[PCI_SABRE_REGS_REG].size);
  113.  
  114.     return pci;
  115. }
  116.  
  117.  
  118. /** Initialize the Psycho PCI controller.
  119.  *
  120.  * @param node OpenFirmware device tree node of the Psycho.
  121.  *
  122.  * @return Address of the initialized PCI structure.
  123.  */
  124. pci_t *pci_psycho_init(ofw_tree_node_t *node)
  125. {
  126.     pci_t *pci;
  127.     ofw_tree_property_t *prop;
  128.  
  129.     /*
  130.      * Get registers.
  131.      */
  132.     prop = ofw_tree_getprop(node, "reg");
  133.     if (!prop || !prop->value)
  134.         return NULL;
  135.  
  136.     ofw_upa_reg_t *reg = prop->value;
  137.     count_t regs = prop->size / sizeof(ofw_upa_reg_t);
  138.  
  139.     if (regs < PCI_PSYCHO_REGS_REG + 1)
  140.         return NULL;
  141.  
  142.     uintptr_t paddr;
  143.     if (!ofw_upa_apply_ranges(node->parent, &reg[PCI_PSYCHO_REGS_REG], &paddr))
  144.         return NULL;
  145.  
  146.     pci = (pci_t *) malloc(sizeof(pci_t), FRAME_ATOMIC);
  147.     if (!pci)
  148.         return NULL;
  149.  
  150.     pci->model = PCI_PSYCHO;
  151.     pci->op = &pci_psycho_ops;
  152.     pci->reg = (uint64_t *) hw_map(paddr, reg[PCI_PSYCHO_REGS_REG].size);
  153.  
  154.     return pci;
  155. }
  156.  
  157. void pci_sabre_enable_interrupt(pci_t *pci, int inr)
  158. {
  159.     pci->reg[PCI_SABRE_IMAP_BASE + (inr & INO_MASK)] |= IMAP_V_MASK;
  160. }
  161.  
  162. void pci_sabre_clear_interrupt(pci_t *pci, int inr)
  163. {
  164.     pci->reg[PCI_SABRE_ICLR_BASE + (inr & INO_MASK)] = 0;
  165. }
  166.  
  167. void pci_psycho_enable_interrupt(pci_t *pci, int inr)
  168. {
  169.     pci->reg[PCI_PSYCHO_IMAP_BASE + (inr & INO_MASK)] |= IMAP_V_MASK;
  170. }
  171.  
  172. void pci_psycho_clear_interrupt(pci_t *pci, int inr)
  173. {
  174.     pci->reg[PCI_PSYCHO_ICLR_BASE + (inr & INO_MASK)] = 0;
  175. }
  176.  
  177. /** Initialize PCI controller. */
  178. pci_t *pci_init(ofw_tree_node_t *node)
  179. {
  180.     ofw_tree_property_t *prop;
  181.  
  182.     /*
  183.      * First, verify this is a PCI node.
  184.      */
  185.     ASSERT(strcmp(ofw_tree_node_name(node), "pci") == 0);
  186.  
  187.     /*
  188.      * Determine PCI controller model.
  189.      */
  190.     prop = ofw_tree_getprop(node, "model");
  191.     if (!prop || !prop->value)
  192.         return NULL;
  193.    
  194.     if (strcmp(prop->value, "SUNW,sabre") == 0) {
  195.         /*
  196.          * PCI controller Sabre.
  197.          * This model is found on UltraSPARC IIi based machines.
  198.          */
  199.         return pci_sabre_init(node);
  200.     } else if (strcmp(prop->value, "SUNW,psycho") == 0) {
  201.         /*
  202.          * PCI controller Psycho.
  203.          * Used on UltraSPARC II based processors, for instance,
  204.          * on Ultra 60.
  205.          */
  206.         return pci_psycho_init(node);
  207.     } else {
  208.         /*
  209.          * Unsupported model.
  210.          */
  211.         printf("Unsupported PCI controller model (%s).\n", prop->value);
  212.     }
  213.  
  214.     return NULL;
  215. }
  216.  
  217. void pci_enable_interrupt(pci_t *pci, int inr)
  218. {
  219.     ASSERT(pci->model);
  220.     ASSERT(pci->op && pci->op->enable_interrupt);
  221.     pci->op->enable_interrupt(pci, inr);
  222. }
  223.  
  224. void pci_clear_interrupt(pci_t *pci, int inr)
  225. {
  226.     ASSERT(pci->model);
  227.     ASSERT(pci->op && pci->op->clear_interrupt);
  228.     pci->op->clear_interrupt(pci, inr);
  229. }
  230.  
  231. /** @}
  232.  */
  233.