Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/bus/pci/pciintel/pci.c

    rc90aed4 r46eb2c4  
    5757#include <ops/hw_res.h>
    5858#include <device/hw_res.h>
     59#include <ops/pio_window.h>
     60#include <device/pio_window.h>
    5961#include <ddi.h>
    6062#include <pci_dev_iface.h>
     
    141143}
    142144
     145static pio_window_t *pciintel_get_pio_window(ddf_fun_t *fnode)
     146{
     147        pci_fun_t *fun = pci_fun(fnode);
     148       
     149        if (fun == NULL)
     150                return NULL;
     151        return &fun->pio_window;
     152}
     153
     154
    143155static int pci_config_space_write_32(ddf_fun_t *fun, uint32_t address,
    144156    uint32_t data)
     
    198210        .get_resource_list = &pciintel_get_resources,
    199211        .enable_interrupt = &pciintel_enable_interrupt,
     212};
     213
     214static pio_window_ops_t pciintel_pio_window_ops = {
     215        .get_pio_window = &pciintel_get_pio_window
    200216};
    201217
     
    211227static ddf_dev_ops_t pci_fun_ops = {
    212228        .interfaces[HW_RES_DEV_IFACE] = &pciintel_hw_res_ops,
     229        .interfaces[PIO_WINDOW_DEV_IFACE] = &pciintel_pio_window_ops,
    213230        .interfaces[PCI_DEV_IFACE] = &pci_dev_ops
    214231};
     
    233250static void pci_conf_read(pci_fun_t *fun, int reg, uint8_t *buf, size_t len)
    234251{
     252        const uint32_t conf_addr = CONF_ADDR(fun->bus, fun->dev, fun->fn, reg);
    235253        pci_bus_t *bus = pci_bus_from_fun(fun);
     254        uint32_t val;
    236255       
    237256        fibril_mutex_lock(&bus->conf_mutex);
    238        
    239         const uint32_t conf_addr = CONF_ADDR(fun->bus, fun->dev, fun->fn, reg);
    240         void *addr = bus->conf_data_port + (reg & 3);
    241        
    242         pio_write_32(bus->conf_addr_port, host2uint32_t_le(conf_addr));
    243        
     257
     258        pio_write_32(bus->conf_addr_reg, host2uint32_t_le(conf_addr));
     259
     260        /*
     261         * Always read full 32-bits from the PCI conf_data_port register and
     262         * get the desired portion of it afterwards. Some architectures do not
     263         * support shorter PIO reads offset from this register.
     264         */
     265        val = uint32_t_le2host(pio_read_32(bus->conf_data_reg));
     266
    244267        switch (len) {
    245268        case 1:
    246                 /* No endianness change for 1 byte */
    247                 buf[0] = pio_read_8(addr);
     269                *buf = (uint8_t) (val >> ((reg & 3) * 8));
    248270                break;
    249271        case 2:
    250                 ((uint16_t *) buf)[0] = uint16_t_le2host(pio_read_16(addr));
     272                *((uint16_t *) buf) = (uint16_t) (val >> ((reg & 3)) * 8);
    251273                break;
    252274        case 4:
    253                 ((uint32_t *) buf)[0] = uint32_t_le2host(pio_read_32(addr));
     275                *((uint32_t *) buf) = (uint32_t) val;
    254276                break;
    255277        }
     
    260282static void pci_conf_write(pci_fun_t *fun, int reg, uint8_t *buf, size_t len)
    261283{
     284        const uint32_t conf_addr = CONF_ADDR(fun->bus, fun->dev, fun->fn, reg);
    262285        pci_bus_t *bus = pci_bus_from_fun(fun);
     286        uint32_t val;
    263287       
    264288        fibril_mutex_lock(&bus->conf_mutex);
    265        
    266         const uint32_t conf_addr = CONF_ADDR(fun->bus, fun->dev, fun->fn, reg);
    267         void *addr = bus->conf_data_port + (reg & 3);
    268        
    269         pio_write_32(bus->conf_addr_port, host2uint32_t_le(conf_addr));
     289
     290        /*
     291         * Prepare to write full 32-bits to the PCI conf_data_port register.
     292         * Some architectures do not support shorter PIO writes offset from this
     293         * register.
     294         */
     295
     296        if (len < 4) {
     297                /*
     298                 * We have fewer than full 32-bits, so we need to read the
     299                 * missing bits first.
     300                 */
     301                pio_write_32(bus->conf_addr_reg, host2uint32_t_le(conf_addr));
     302                val = uint32_t_le2host(pio_read_32(bus->conf_data_reg));
     303        }
    270304       
    271305        switch (len) {
    272306        case 1:
    273                 /* No endianness change for 1 byte */
    274                 pio_write_8(addr, buf[0]);
     307                val &= ~(0xffU << ((reg & 3) * 8));
     308                val |= *buf << ((reg & 3) * 8);
    275309                break;
    276310        case 2:
    277                 pio_write_16(addr, host2uint16_t_le(((uint16_t *) buf)[0]));
     311                val &= ~(0xffffU << ((reg & 3) * 8));
     312                val |= *((uint16_t *) buf) << ((reg & 3) * 8);
    278313                break;
    279314        case 4:
    280                 pio_write_32(addr, host2uint32_t_le(((uint32_t *) buf)[0]));
     315                val = *((uint32_t *) buf);
    281316                break;
    282317        }
     318
     319        pio_write_32(bus->conf_addr_reg, host2uint32_t_le(conf_addr));
     320        pio_write_32(bus->conf_data_reg, host2uint32_t_le(val));
    283321       
    284322        fibril_mutex_unlock(&bus->conf_mutex);
     
    411449                hw_resources[count].res.io_range.address = range_addr;
    412450                hw_resources[count].res.io_range.size = range_size;
     451                hw_resources[count].res.io_range.relative = true;
    413452                hw_resources[count].res.io_range.endianness = LITTLE_ENDIAN;
    414453        } else {
     
    416455                hw_resources[count].res.mem_range.address = range_addr;
    417456                hw_resources[count].res.mem_range.size = range_size;
     457                hw_resources[count].res.mem_range.relative = false;
    418458                hw_resources[count].res.mem_range.endianness = LITTLE_ENDIAN;
    419459        }
     
    433473{
    434474        /* Value of the BAR */
    435         uint32_t val, mask;
     475        uint32_t val;
     476        uint32_t bar;
     477        uint32_t mask;
     478
    436479        /* IO space address */
    437480        bool io;
     
    471514        /* Get the address mask. */
    472515        pci_conf_write_32(fun, addr, 0xffffffff);
    473         mask &= pci_conf_read_32(fun, addr);
    474        
     516        bar = pci_conf_read_32(fun, addr);
     517
     518        /*
     519         * Unimplemented BARs read back as all 0's.
     520         */
     521        if (!bar)
     522                return addr + (addrw64 ? 8 : 4);
     523
     524        mask &= bar;   
     525
    475526        /* Restore the original value. */
    476527        pci_conf_write_32(fun, addr, val);
     
    520571{
    521572        uint8_t irq = pci_conf_read_8(fun, PCI_BRIDGE_INT_LINE);
    522         if (irq != 0xff)
     573        uint8_t pin = pci_conf_read_8(fun, PCI_BRIDGE_INT_PIN);
     574
     575        if (pin != 0 && irq != 0xff)
    523576                pci_add_interrupt(fun, irq);
    524577}
     
    583636                        pci_read_bars(fun);
    584637                        pci_read_interrupt(fun);
     638
     639                        /* Propagate the PIO window to the function. */
     640                        fun->pio_window = bus->pio_win;
    585641                       
    586642                        ddf_fun_set_ops(fun->fnode, &pci_fun_ops);
     
    613669static int pci_dev_add(ddf_dev_t *dnode)
    614670{
     671        hw_resource_list_t hw_resources;
    615672        pci_bus_t *bus = NULL;
    616673        ddf_fun_t *ctl = NULL;
     
    638695                goto fail;
    639696        }
    640        
    641         hw_resource_list_t hw_resources;
     697
     698        rc = pio_window_get(sess, &bus->pio_win);
     699        if (rc != EOK) {
     700                ddf_msg(LVL_ERROR, "pci_dev_add failed to get PIO window "
     701                    "for the device.");
     702                goto fail;
     703        }
    642704       
    643705        rc = hw_res_get_resource_list(sess, &hw_resources);
     
    662724            hw_resources.resources[1].res.io_range.address);
    663725       
    664         bus->conf_io_addr =
    665             (uint32_t) hw_resources.resources[0].res.io_range.address;
    666         bus->conf_io_data =
    667             (uint32_t) hw_resources.resources[1].res.io_range.address;
    668        
    669         if (pio_enable((void *)(uintptr_t)bus->conf_io_addr, 4,
    670             &bus->conf_addr_port)) {
     726        if (pio_enable_resource(&bus->pio_win, &hw_resources.resources[0],
     727            (void **) &bus->conf_addr_reg)) {
    671728                ddf_msg(LVL_ERROR, "Failed to enable configuration ports.");
    672729                rc = EADDRNOTAVAIL;
    673730                goto fail;
    674731        }
    675         if (pio_enable((void *)(uintptr_t)bus->conf_io_data, 4,
    676             &bus->conf_data_port)) {
     732        if (pio_enable_resource(&bus->pio_win, &hw_resources.resources[1],
     733            (void **) &bus->conf_data_reg)) {
    677734                ddf_msg(LVL_ERROR, "Failed to enable configuration ports.");
    678735                rc = EADDRNOTAVAIL;
     
    729786{
    730787        ddf_log_init(NAME);
    731         pci_fun_ops.interfaces[HW_RES_DEV_IFACE] = &pciintel_hw_res_ops;
    732         pci_fun_ops.interfaces[PCI_DEV_IFACE] = &pci_dev_ops;
    733788}
    734789
Note: See TracChangeset for help on using the changeset viewer.