github.com/jlmucb/cloudproxy@v0.0.0-20170830161738-b5aa0b619bc4/cpvmm/vmm/host/hw/host_pci_configuration.c (about)

     1  /*
     2   * Copyright (c) 2013 Intel Corporation
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *     http://www.apache.org/licenses/LICENSE-2.0
     8   * Unless required by applicable law or agreed to in writing, software
     9   * distributed under the License is distributed on an "AS IS" BASIS,
    10   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    11   * See the License for the specific language governing permissions and
    12   * limitations under the License.
    13   */
    14  
    15  #include "host_pci_configuration.h"
    16  #include "hw_utils.h"
    17  #include "vmm_dbg.h"
    18  #include "libc.h"
    19  #include "file_codes.h"
    20  #define VMM_DEADLOOP()          VMM_DEADLOOP_LOG(HOST_PCI_CONFIGURATION_C)
    21  #define VMM_ASSERT(__condition) VMM_ASSERT_LOG(HOST_PCI_CONFIGURATION_C, __condition)
    22  #ifdef JLMDEBUG
    23  #include "jlmdebug.h"
    24  #endif
    25  
    26  
    27  #define PCI_DEV_INDEX_INVALID   0 // index 0 is not in use. used to specify "invalid" in lookup table
    28  
    29  // bit 7: =0 single function, =1 multi-function
    30  #define PCI_IS_MULTIFUNCTION_DEVICE(header_type) (((header_type) & 0x80) != 0)
    31  #define PCI_IS_PCI_2_PCI_BRIDGE(base_class, sub_class) ((base_class) == PCI_BASE_CLASS_BRIDGE && (sub_class) == 0x04)
    32  #ifdef PCI_SCAN
    33  static HOST_PCI_DEVICE pci_devices[PCI_MAX_NUM_SUPPORTED_DEVICES + 1];
    34  static PCI_DEV_INDEX avail_pci_device_index = 1; // index 0 is not in use. used to specify "invalid" in lookup table
    35  static PCI_DEV_INDEX pci_devices_lookup_table[PCI_MAX_NUM_FUNCTIONS];
    36  static UINT32 num_pci_devices = 0;
    37  
    38  UINT8 pci_read8(UINT8 bus, UINT8 device, UINT8 function, UINT8 reg)
    39  {
    40      PCI_CONFIG_ADDRESS addr;
    41  
    42      addr.Uint32 = 0;
    43      addr.Bits.Bus = bus;
    44      addr.Bits.Device = device;
    45      addr.Bits.Function = function;
    46      addr.Bits.Register = reg;
    47      addr.Bits.Enable = 1;
    48  
    49      hw_write_port_32(PCI_CONFIG_ADDRESS_REGISTER, addr.Uint32 & ~0x3);
    50      return hw_read_port_8(PCI_CONFIG_DATA_REGISTER | (addr.Uint32 & 0x3));
    51  }
    52  
    53  void pci_write8(UINT8 bus, UINT8 device, UINT8 function, UINT8 reg, UINT8 value)
    54  {
    55      PCI_CONFIG_ADDRESS addr;
    56  
    57      addr.Uint32 = 0;
    58      addr.Bits.Bus = bus;
    59      addr.Bits.Device = device;
    60      addr.Bits.Function = function;
    61      addr.Bits.Register = reg;
    62      addr.Bits.Enable = 1;
    63  
    64      hw_write_port_32(PCI_CONFIG_ADDRESS_REGISTER, addr.Uint32 & ~0x3);
    65      hw_write_port_8(PCI_CONFIG_DATA_REGISTER | (addr.Uint32 & 0x3), value);
    66  }
    67  
    68  UINT16 pci_read16(UINT8 bus, UINT8 device, UINT8 function, UINT8 reg)
    69  {
    70      PCI_CONFIG_ADDRESS addr;
    71  
    72      addr.Uint32 = 0;
    73      addr.Bits.Bus = bus;
    74      addr.Bits.Device = device;
    75      addr.Bits.Function = function;
    76      addr.Bits.Register = reg;
    77      addr.Bits.Enable = 1;
    78  
    79      hw_write_port_32(PCI_CONFIG_ADDRESS_REGISTER, addr.Uint32 & ~0x3);
    80      return hw_read_port_16(PCI_CONFIG_DATA_REGISTER | (addr.Uint32 & 0x3));
    81  }
    82  
    83  void pci_write16(UINT8 bus, UINT8 device, UINT8 function, UINT8 reg, UINT16 value)
    84  {
    85      PCI_CONFIG_ADDRESS addr;
    86  
    87      addr.Uint32 = 0;
    88      addr.Bits.Bus = bus;
    89      addr.Bits.Device = device;
    90      addr.Bits.Function = function;
    91      addr.Bits.Register = reg;
    92      addr.Bits.Enable = 1;
    93  
    94      hw_write_port_32(PCI_CONFIG_ADDRESS_REGISTER, addr.Uint32 & ~0x3);
    95      hw_write_port_16(PCI_CONFIG_DATA_REGISTER | (addr.Uint32 & 0x2), value);
    96  }
    97  
    98  UINT32 pci_read32(UINT8 bus, UINT8 device, UINT8 function, UINT8 reg)
    99  {
   100      PCI_CONFIG_ADDRESS addr;
   101  
   102      addr.Uint32 = 0;
   103      addr.Bits.Bus = bus;
   104      addr.Bits.Device = device;
   105      addr.Bits.Function = function;
   106      addr.Bits.Register = reg;
   107      addr.Bits.Enable = 1;
   108  
   109      hw_write_port_32(PCI_CONFIG_ADDRESS_REGISTER, addr.Uint32 & ~0x3);
   110      return hw_read_port_32(PCI_CONFIG_DATA_REGISTER);
   111  }
   112  
   113  void pci_write32(UINT8 bus, UINT8 device, UINT8 function, UINT8 reg, UINT32 value)
   114  {
   115      PCI_CONFIG_ADDRESS addr;
   116  
   117      addr.Uint32 = 0;
   118      addr.Bits.Bus = bus;
   119      addr.Bits.Device = device;
   120      addr.Bits.Function = function;
   121      addr.Bits.Register = reg;
   122      addr.Bits.Enable = 1;
   123  
   124      hw_write_port_32(PCI_CONFIG_ADDRESS_REGISTER, addr.Uint32 & ~0x3);
   125      hw_write_port_32(PCI_CONFIG_DATA_REGISTER, value);
   126  }
   127  
   128  HOST_PCI_DEVICE *get_host_pci_device(UINT8 bus, UINT8 device, UINT8 function)
   129  {
   130      HOST_PCI_DEVICE *pci_dev;
   131      PCI_DEVICE_ADDRESS lookup_table_index = 0;
   132      PCI_DEV_INDEX pci_dev_index = 0;
   133  
   134      if(FALSE == PCI_IS_ADDRESS_VALID(bus, device, function))
   135      {
   136          return NULL;
   137      }
   138      SET_PCI_BUS(lookup_table_index, bus);
   139      SET_PCI_DEVICE(lookup_table_index, device);
   140      SET_PCI_FUNCTION(lookup_table_index, function);
   141      pci_dev_index = pci_devices_lookup_table[lookup_table_index];
   142  
   143      if(PCI_DEV_INDEX_INVALID == pci_dev_index) {
   144          pci_dev = NULL;
   145      }
   146      else {
   147          pci_dev = &pci_devices[pci_dev_index];
   148      }
   149      return pci_dev;
   150  }
   151  
   152  BOOLEAN pci_read_secondary_bus_reg(UINT8 bus, UINT8 device, UINT8 func, OUT UINT8 *secondary_bus)
   153  {
   154      HOST_PCI_DEVICE *pci_bridge = get_host_pci_device(bus, device, func);
   155  
   156      *secondary_bus = 0;
   157      if(NULL == pci_bridge || FALSE == pci_bridge->is_pci_2_pci_bridge
   158         || PCI_CONFIG_HEADER_TYPE_PCI2PCI_BRIDGE != pci_bridge->header_type) {
   159          return FALSE;
   160      }
   161  
   162      *secondary_bus = pci_read8(bus, device, func, PCI_CONFIG_SECONDARY_BUS_OFFSET);
   163      return TRUE;
   164  }
   165  
   166  static UINT8
   167  host_pci_decode_bar(
   168      UINT8  bus,
   169      UINT8  device,
   170      UINT8  function,
   171      UINT8  bar_offset,
   172      PCI_BASE_ADDRESS_REGISTER *bar)
   173  {
   174      UINT32 bar_value_low = pci_read32(bus, device, function, bar_offset);
   175      UINT32 bar_value_high = 0;
   176      UINT64 bar_value = 0;
   177      UINT32 encoded_size_low = 0;
   178      UINT32 encoded_size_high = 0;
   179      UINT64 encoded_size = 0;
   180      UINT64 mask;
   181      UINT32 address_type = PCI_CONFIG_HEADER_BAR_ADDRESS_32;
   182  
   183      VMM_LOG(mask_anonymous, level_trace,"%s %d:%d:%d:%d, bar_value_low=0x%x\r\n",
   184                      __FUNCTION__, bus, device, function, bar_offset, bar_value_low);
   185  
   186      if (bar_value_low > 1) // 0: not used mmio space; 1: not used io space
   187      {
   188          // issue size determination command
   189          pci_write32(bus, device, function, bar_offset, PCI_CONFIG_HEADER_BAR_SIZING_COMMAND);
   190          encoded_size_low = pci_read32(bus, device, function, bar_offset);
   191  
   192          bar->type = bar_value_low & PCI_CONFIG_HEADER_BAR_MEMORY_TYPE_MASK;
   193  
   194          mask = (PCI_BAR_IO_REGION == bar->type) ?
   195            PCI_CONFIG_HEADER_BAR_ADDRESS_MASK_TYPE_IO :
   196            PCI_CONFIG_HEADER_BAR_ADDRESS_MASK_TYPE_MMIO;
   197  
   198          // valid only for mmio
   199          address_type = (UINT32)(bar_value_low & PCI_CONFIG_HEADER_BAR_ADDRESS_TYPE_MASK) >> 1;
   200  
   201          if(bar->type == PCI_BAR_MMIO_REGION && address_type == PCI_CONFIG_HEADER_BAR_ADDRESS_64) {
   202              // issue size determination command
   203              bar_value_high = pci_read32(bus, device, function, bar_offset + 4);
   204              pci_write32(bus, device, function, bar_offset + 4, PCI_CONFIG_HEADER_BAR_SIZING_COMMAND);
   205              encoded_size_high = pci_read32(bus, device, function, bar_offset + 4);
   206              bar_value = (UINT64) bar_value_high << 32 | ((UINT64)bar_value_low & 0x00000000FFFFFFFF);
   207              bar->addr = bar_value & mask;
   208              encoded_size = (UINT64) encoded_size_high << 32 | ((UINT64)encoded_size_low & 0x00000000FFFFFFFF);
   209              encoded_size &= mask;
   210              bar->length = (~encoded_size) + 1;
   211              pci_write32(bus, device, function, bar_offset, bar_value_low); // restore original value
   212              pci_write32(bus, device, function, bar_offset + 4, bar_value_high); // restore original value
   213          }
   214          else {
   215              bar->addr = ((UINT64)bar_value_low & 0x00000000FFFFFFFF) & mask;
   216              encoded_size = 0xFFFFFFFF00000000 | ((UINT64)encoded_size_low & 0x00000000FFFFFFFF);
   217              encoded_size &= mask;
   218              bar->length = (~encoded_size) + 1;
   219              pci_write32(bus, device, function, bar_offset, bar_value_low); // restore original value
   220          }
   221  
   222          if (PCI_BAR_IO_REGION == bar->type) {
   223              bar->length &= 0xFFFF; // IO space in Intel  arch can't exceed 64K bytes
   224          }
   225      }
   226      else {
   227          bar->type = PCI_BAR_UNUSED;
   228      }
   229      return (address_type == PCI_CONFIG_HEADER_BAR_ADDRESS_64) ? 8 : 4;
   230  }
   231  
   232  static void host_pci_decode_pci_bridge(
   233      UINT8  bus,
   234      UINT8  device,
   235      UINT8  function,
   236      PCI_BASE_ADDRESS_REGISTER *bar_mmio,
   237      PCI_BASE_ADDRESS_REGISTER *bar_io)
   238  {
   239      UINT32 memory_base = ((UINT32)pci_read16(bus, device, function, PCI_CONFIG_BRIDGE_MEMORY_BASE) << 16) & 0xFFF00000;
   240      UINT32 memory_limit = ((UINT32)pci_read16(bus, device, function, PCI_CONFIG_BRIDGE_MEMORY_LIMIT) << 16) | 0x000FFFFF;
   241      UINT8 io_base_low = pci_read8(bus, device, function, PCI_CONFIG_BRIDGE_IO_BASE_LOW);
   242      UINT8 io_limit_low = pci_read8(bus, device, function, PCI_CONFIG_BRIDGE_IO_LIMIT_LOW);
   243      UINT16 io_base_high = 0;
   244      UINT16 io_limit_high = 0;
   245      UINT64 io_base;
   246      UINT64 io_limit;
   247  
   248      // mmio
   249      if (memory_limit < memory_base) {
   250          bar_mmio->type = PCI_BAR_UNUSED;
   251      }
   252      else {
   253          bar_mmio->type = PCI_BAR_MMIO_REGION;
   254          bar_mmio->addr = (UINT64)memory_base & 0x00000000FFFFFFFF;
   255          bar_mmio->length = (UINT64)(memory_limit - memory_base +1) & 0x00000000FFFFFFFF;
   256      }
   257  
   258      // io
   259      if (io_base_low == 0 || io_limit_low == 0 || io_limit_low < io_base_low) {
   260          bar_io->type = PCI_BAR_UNUSED;
   261      }
   262      else if ((io_base_low & 0xF) > 1) {
   263          bar_io->type = PCI_BAR_UNUSED;
   264          VMM_LOG(mask_anonymous, level_print_always,"%s Warning: reserved IO address capability in bridge (%d:%d:%d) detected, io_base_low=0x%x\r\n",
   265                      __FUNCTION__, bus, device, function, io_base_low);
   266      }
   267      else {
   268          if ((io_base_low & 0xF) == 1) // 32 bit IO address {
   269              // update the high 16 bits
   270              io_base_high = pci_read16(bus, device, function, PCI_CONFIG_BRIDGE_IO_BASE_HIGH);
   271              io_limit_high = pci_read16(bus, device, function, PCI_CONFIG_BRIDGE_IO_LIMIT_HIGH);
   272          }
   273          io_base = (((UINT64) io_base_high << 16) & 0x00000000FFFF0000) |
   274                        (((UINT64) io_base_low << 8) & 0x000000000000F000);
   275          io_limit = (((UINT64) io_limit_high << 16) & 0x00000000FFFF0000) |
   276                        (((UINT64) io_limit_low << 8) & 0x000000000000F000) |
   277                        0x0000000000000FFF;
   278          bar_io->type = PCI_BAR_IO_REGION;
   279          bar_io->addr = io_base;
   280          bar_io->length = io_limit-io_base+1;
   281      }
   282  }
   283  
   284  static void pci_init_device(PCI_DEVICE_ADDRESS device_addr, 
   285                              PCI_DEVICE_ADDRESS parent_addr, 
   286                              BOOLEAN parent_addr_valid,
   287                              BOOLEAN is_bridge)
   288  {
   289      HOST_PCI_DEVICE *pci_dev;
   290      PCI_DEV_INDEX pci_dev_index = 0;
   291      UINT32 i;
   292      UINT8 bus, device, function;
   293      UINT8 bar_offset;
   294  
   295      // BEFORE_VMLAUNCH
   296      VMM_ASSERT(avail_pci_device_index <= PCI_MAX_NUM_SUPPORTED_DEVICES);
   297  
   298      pci_dev_index = pci_devices_lookup_table[device_addr];
   299  
   300      if(PCI_DEV_INDEX_INVALID != pci_dev_index) {// already initialized
   301          return;
   302      }
   303  
   304      num_pci_devices++;
   305      pci_dev_index = avail_pci_device_index++;
   306      pci_devices_lookup_table[device_addr] = pci_dev_index;
   307  
   308      pci_dev = &pci_devices[pci_dev_index];
   309      pci_dev->address = device_addr;
   310      bus = GET_PCI_BUS(device_addr);
   311      device = GET_PCI_DEVICE(device_addr);
   312      function = GET_PCI_FUNCTION(device_addr);
   313      pci_dev->vendor_id = pci_read16(bus, device, function, PCI_CONFIG_VENDOR_ID_OFFSET);
   314      pci_dev->device_id = pci_read16(bus, device, function, PCI_CONFIG_DEVICE_ID_OFFSET);
   315      pci_dev->revision_id = pci_read8(bus, device, function, PCI_CONFIG_REVISION_ID_OFFSET);
   316      pci_dev->base_class = pci_read8(bus, device, function, PCI_CONFIG_BASE_CLASS_CODE_OFFSET);
   317      pci_dev->sub_class = pci_read8(bus, device, function, PCI_CONFIG_SUB_CLASS_CODE_OFFSET);
   318      pci_dev->programming_interface = pci_read8(bus, device, function, PCI_CONFIG_PROGRAMMING_INTERFACE_OFFSET);
   319      pci_dev->header_type = pci_read8(bus, device, 0, PCI_CONFIG_HEADER_TYPE_OFFSET);
   320      pci_dev->is_multifunction = PCI_IS_MULTIFUNCTION_DEVICE(pci_dev->header_type);
   321      pci_dev->header_type = pci_dev->header_type & ~0x80; // clear multifunction bit
   322      pci_dev->is_pci_2_pci_bridge = PCI_IS_PCI_2_PCI_BRIDGE(pci_dev->base_class, pci_dev->sub_class);
   323      pci_dev->interrupt_pin = pci_read8(bus, device, function, PCI_CONFIG_INTERRUPT_PIN_OFFSET);
   324      pci_dev->interrupt_line = pci_read8(bus, device, function, PCI_CONFIG_INTERRUPT_LINE_OFFSET);
   325      if(parent_addr_valid) {
   326          pci_dev->parent = get_host_pci_device(GET_PCI_BUS(parent_addr), GET_PCI_DEVICE(parent_addr), GET_PCI_FUNCTION(parent_addr));
   327      }
   328      else {
   329          pci_dev->parent = NULL;
   330      }
   331  
   332      if(pci_dev->parent == NULL) {
   333          pci_dev->depth = 1;
   334          pci_dev->path.start_bus = bus;
   335      }
   336      else {
   337          pci_dev->depth = pci_dev->parent->depth + 1;
   338          pci_dev->path.start_bus = pci_dev->parent->path.start_bus;
   339          for(i = 0; i < pci_dev->parent->depth; i++)
   340          {
   341              pci_dev->path.path[i] = pci_dev->parent->path.path[i];
   342          }
   343      }
   344      VMM_ASSERT(pci_dev->depth <= PCI_MAX_PATH);
   345      pci_dev->path.path[pci_dev->depth - 1].device = device;
   346      pci_dev->path.path[pci_dev->depth - 1].function = function;
   347  
   348      bar_offset = PCI_CONFIG_BAR_OFFSET;
   349      if (is_bridge) {
   350          for(i = 0; i < PCI_MAX_BAR_NUMBER_IN_BRIDGE; i++) {
   351              // Assumption: according to PCI bridge spec 1.2, host_pci_decode_bar() will only return 4 (as 32 bit) for bridge
   352              // 64 bit mapping is not supported in bridge
   353              bar_offset = bar_offset + host_pci_decode_bar(bus, device, function, bar_offset, &pci_dev->bars[i]);
   354          }
   355          host_pci_decode_pci_bridge(bus, device, function, &pci_dev->bars[i], &pci_dev->bars[i+1]); // set io range and mmio range
   356          i+=2; // for the io bar and mmio bar set by host_pci_decode_pci_bridge() above
   357          // set rest bars as unused
   358          for (; i < PCI_MAX_BAR_NUMBER; i++)
   359              pci_dev->bars[i].type = PCI_BAR_UNUSED;
   360      }
   361      else {
   362          for(i = 0; i < PCI_MAX_BAR_NUMBER; i++) {
   363              if (bar_offset > PCI_CONFIG_BAR_LAST_OFFSET) // total bar size is 0x10~0x24
   364                  pci_dev->bars[i].type = PCI_BAR_UNUSED;
   365              else
   366                  bar_offset = bar_offset + host_pci_decode_bar(bus, device, function, bar_offset, &pci_dev->bars[i]);
   367          }
   368      }
   369  }
   370  
   371  
   372  static void pci_scan_bus(UINT8 bus, PCI_DEVICE_ADDRESS parent_addr, BOOLEAN parent_addr_valid)
   373  {
   374      UINT8 device = 0;
   375      UINT8 function = 0;
   376      UINT8 header_type = 0;
   377      UINT8 max_functions = 0;
   378      UINT16 vendor_id = 0;
   379      UINT16 device_id = 0;
   380      BOOLEAN is_multifunction = 0;
   381      UINT8 base_class = 0;
   382      UINT8 sub_class = 0;
   383      UINT8 secondary_bus = 0;
   384      PCI_DEVICE_ADDRESS this_device_address = 0;
   385      BOOLEAN is_bridge;
   386  
   387      for(device = 0; device < PCI_MAX_NUM_DEVICES_ON_BUS; device++) {
   388          header_type = pci_read8(bus, device, 0, PCI_CONFIG_HEADER_TYPE_OFFSET);
   389          is_multifunction = PCI_IS_MULTIFUNCTION_DEVICE(header_type); // bit 7: =0 single function, =1 multi-function
   390          max_functions = is_multifunction ? PCI_MAX_NUM_FUNCTIONS_ON_DEVICE: 1;
   391          header_type = header_type & ~0x80; // clear multifunction bit
   392  
   393          for(function = 0; function < max_functions; function++) {
   394              vendor_id = pci_read16(bus, device, function, PCI_CONFIG_VENDOR_ID_OFFSET);
   395              device_id = pci_read16(bus, device, function, PCI_CONFIG_DEVICE_ID_OFFSET);
   396  
   397              if(PCI_INVALID_VENDOR_ID == vendor_id || PCI_INVALID_DEVICE_ID == device_id) {
   398                  continue;
   399              }
   400  
   401              SET_PCI_BUS(this_device_address, bus);
   402              SET_PCI_DEVICE(this_device_address, device);
   403              SET_PCI_FUNCTION(this_device_address, function);
   404  
   405              base_class = pci_read8(bus, device, function, PCI_CONFIG_BASE_CLASS_CODE_OFFSET);
   406              sub_class = pci_read8(bus, device, function, PCI_CONFIG_SUB_CLASS_CODE_OFFSET);
   407  
   408              is_bridge = PCI_IS_PCI_2_PCI_BRIDGE(base_class, sub_class);
   409  
   410              // call device handler
   411              pci_init_device(this_device_address, parent_addr, parent_addr_valid, is_bridge);
   412  
   413              // check if it is needed to go downstream the bridge
   414              if(is_bridge) {
   415                  if (header_type == 1) // PCI Bridge header type. it should be 1. Skip misconfigured devices {
   416                      secondary_bus = pci_read8(bus, device, function, PCI_CONFIG_SECONDARY_BUS_OFFSET);
   417                      pci_scan_bus(secondary_bus, this_device_address, TRUE);
   418                  }
   419              }
   420          }
   421      }
   422  }
   423  
   424  UINT32 host_pci_get_num_devices(void)
   425  {
   426      return num_pci_devices;
   427  }
   428  
   429  static void host_pci_print_bar(PCI_BASE_ADDRESS_REGISTER *bar)
   430  {
   431      static char* bar_type_string = NULL;
   432  
   433      if(PCI_BAR_UNUSED == bar->type) {
   434          //bar_type_string = "unused";
   435          return;
   436      }
   437      else if(PCI_BAR_IO_REGION == bar->type) {
   438          bar_type_string = "io";
   439      }
   440      else if(PCI_BAR_MMIO_REGION == bar->type) {
   441          bar_type_string = "mmio";
   442      }
   443  
   444      VMM_LOG(mask_anonymous, level_trace,"%s addr=%p size=%p; ", bar_type_string, bar->addr, bar->length);
   445  }
   446  
   447  #ifdef VMM_DEBUG_SCREEN
   448  static void host_pci_print_bar_screen(PCI_BASE_ADDRESS_REGISTER *bar)
   449  {
   450      static char* bar_type_string = NULL;
   451  
   452      if(PCI_BAR_UNUSED == bar->type) {
   453          //bar_type_string = "unused";
   454          return;
   455      }
   456      else if(PCI_BAR_IO_REGION == bar->type) {
   457          bar_type_string = "io";
   458      }
   459      else if(PCI_BAR_MMIO_REGION == bar->type) {
   460          bar_type_string = "mmio";
   461      }
   462  
   463      VMM_LOG_SCREEN("%s addr=%p size=%p; ", bar_type_string, bar->addr, bar->length);
   464  }
   465  #endif
   466  
   467  static void host_pci_print(void)
   468  {
   469      UINT32 i = 0, j;
   470      PCI_DEVICE_ADDRESS device_addr;
   471      PCI_DEV_INDEX pci_dev_index = 0;
   472      HOST_PCI_DEVICE *pci_dev;
   473  
   474      VMM_LOG(mask_anonymous, level_trace,"[Bus]    [Dev]    [Func]    [Vendor ID]    [Dev ID]   [PCI-PCI Bridge]\r\n");
   475      //vmm_clear_screen();
   476      for(i = 0; i < PCI_MAX_NUM_FUNCTIONS; i++) {
   477          if(PCI_DEV_INDEX_INVALID == pci_devices_lookup_table[i]) {
   478              continue;
   479          }
   480  
   481          device_addr = (UINT16) i;
   482          pci_dev_index = pci_devices_lookup_table[i];
   483          pci_dev = &pci_devices[pci_dev_index];
   484          
   485          VMM_LOG(mask_anonymous, level_trace,"%5d    %5d    %6d    %#11x    %#8x    ",
   486               GET_PCI_BUS(device_addr), GET_PCI_DEVICE(device_addr), GET_PCI_FUNCTION(device_addr), pci_dev->vendor_id, pci_dev->device_id);
   487  
   488          if(pci_dev->is_pci_2_pci_bridge) {
   489              VMM_LOG(mask_anonymous, level_trace,"%16c    ", 'X');
   490          }
   491          VMM_LOG(mask_anonymous, level_trace,"\r\n BARs: ");
   492          for(j = 0; j < PCI_MAX_BAR_NUMBER; j++) {
   493              host_pci_print_bar(&(pci_dev->bars[j]));
   494          }
   495          VMM_LOG(mask_anonymous, level_trace,"\r\n");
   496      }
   497  }
   498  
   499  void host_pci_initialize(void)
   500  {
   501      UINT16 bus; // use 16 bits instead of 8 to avoid wrap around on bus==256
   502      PCI_DEVICE_ADDRESS addr = {0};
   503  
   504      vmm_zeromem(pci_devices, sizeof(pci_devices));
   505      vmm_zeromem(pci_devices_lookup_table, sizeof(pci_devices_lookup_table));
   506  
   507      VMM_LOG(mask_anonymous, level_trace,"\r\nSTART Host PCI scan\r\n");
   508      for(bus = 0; bus < PCI_MAX_NUM_BUSES; bus++) {
   509          pci_scan_bus((UINT8) bus, addr, FALSE);
   510      }
   511      
   512      host_pci_print();
   513      VMM_LOG(mask_anonymous, level_trace,"\r\nEND Host PCI scan\r\n");
   514  }
   515  #endif //PCI_SCAN