Ignore:
File:
1 edited

Legend:

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

    r267f235 rebc9c2c  
    4141#include <stdio.h>
    4242#include <errno.h>
    43 #include <bool.h>
     43#include <stdbool.h>
    4444#include <fibril_synch.h>
    4545#include <str.h>
     
    5151#include <ddf/log.h>
    5252#include <ipc/dev_iface.h>
    53 #include <ipc/irc.h>
    54 #include <ns.h>
    55 #include <ipc/services.h>
    56 #include <sysinfo.h>
     53#include <irc.h>
    5754#include <ops/hw_res.h>
    5855#include <device/hw_res.h>
     56#include <ops/pio_window.h>
     57#include <device/pio_window.h>
    5958#include <ddi.h>
    60 #include <libarch/ddi.h>
    6159#include <pci_dev_iface.h>
    6260
     
    105103        assert(fnode);
    106104        pci_fun_t *dev_data = pci_fun(fnode);
    107        
    108         sysarg_t apic;
    109         sysarg_t i8259;
    110        
    111         async_sess_t *irc_sess = NULL;
    112        
    113         if (((sysinfo_get_value("apic", &apic) == EOK) && (apic))
    114             || ((sysinfo_get_value("i8259", &i8259) == EOK) && (i8259))) {
    115                 irc_sess = service_connect_blocking(EXCHANGE_SERIALIZE,
    116                     SERVICE_IRC, 0, 0);
    117         }
    118        
    119         if (!irc_sess)
    120                 return false;
    121105       
    122106        size_t i = 0;
     
    124108        for (; i < res->count; i++) {
    125109                if (res->resources[i].type == INTERRUPT) {
    126                         const int irq = res->resources[i].res.interrupt.irq;
    127                        
    128                         async_exch_t *exch = async_exchange_begin(irc_sess);
    129                         const int rc =
    130                             async_req_1_0(exch, IRC_ENABLE_INTERRUPT, irq);
    131                         async_exchange_end(exch);
    132                        
    133                         if (rc != EOK) {
    134                                 async_hangup(irc_sess);
     110                        int rc = irc_enable_interrupt(
     111                            res->resources[i].res.interrupt.irq);
     112                       
     113                        if (rc != EOK)
    135114                                return false;
    136                         }
    137115                }
    138116        }
    139117       
    140         async_hangup(irc_sess);
    141118        return true;
    142119}
    143120
    144 static int pci_config_space_write_32(ddf_fun_t *fun, uint32_t address,
     121static pio_window_t *pciintel_get_pio_window(ddf_fun_t *fnode)
     122{
     123        pci_fun_t *fun = pci_fun(fnode);
     124       
     125        if (fun == NULL)
     126                return NULL;
     127        return &fun->pio_window;
     128}
     129
     130
     131static int config_space_write_32(ddf_fun_t *fun, uint32_t address,
    145132    uint32_t data)
    146133{
     
    151138}
    152139
    153 static int pci_config_space_write_16(
     140static int config_space_write_16(
    154141    ddf_fun_t *fun, uint32_t address, uint16_t data)
    155142{
     
    160147}
    161148
    162 static int pci_config_space_write_8(
     149static int config_space_write_8(
    163150    ddf_fun_t *fun, uint32_t address, uint8_t data)
    164151{
     
    169156}
    170157
    171 static int pci_config_space_read_32(
     158static int config_space_read_32(
    172159    ddf_fun_t *fun, uint32_t address, uint32_t *data)
    173160{
     
    178165}
    179166
    180 static int pci_config_space_read_16(
     167static int config_space_read_16(
    181168    ddf_fun_t *fun, uint32_t address, uint16_t *data)
    182169{
     
    187174}
    188175
    189 static int pci_config_space_read_8(
     176static int config_space_read_8(
    190177    ddf_fun_t *fun, uint32_t address, uint8_t *data)
    191178{
     
    201188};
    202189
     190static pio_window_ops_t pciintel_pio_window_ops = {
     191        .get_pio_window = &pciintel_get_pio_window
     192};
     193
    203194static pci_dev_iface_t pci_dev_ops = {
    204         .config_space_read_8 = &pci_config_space_read_8,
    205         .config_space_read_16 = &pci_config_space_read_16,
    206         .config_space_read_32 = &pci_config_space_read_32,
    207         .config_space_write_8 = &pci_config_space_write_8,
    208         .config_space_write_16 = &pci_config_space_write_16,
    209         .config_space_write_32 = &pci_config_space_write_32
     195        .config_space_read_8 = &config_space_read_8,
     196        .config_space_read_16 = &config_space_read_16,
     197        .config_space_read_32 = &config_space_read_32,
     198        .config_space_write_8 = &config_space_write_8,
     199        .config_space_write_16 = &config_space_write_16,
     200        .config_space_write_32 = &config_space_write_32
    210201};
    211202
    212203static ddf_dev_ops_t pci_fun_ops = {
    213204        .interfaces[HW_RES_DEV_IFACE] = &pciintel_hw_res_ops,
     205        .interfaces[PIO_WINDOW_DEV_IFACE] = &pciintel_pio_window_ops,
    214206        .interfaces[PCI_DEV_IFACE] = &pci_dev_ops
    215207};
     
    234226static void pci_conf_read(pci_fun_t *fun, int reg, uint8_t *buf, size_t len)
    235227{
     228        const uint32_t conf_addr = CONF_ADDR(fun->bus, fun->dev, fun->fn, reg);
    236229        pci_bus_t *bus = pci_bus_from_fun(fun);
     230        uint32_t val;
    237231       
    238232        fibril_mutex_lock(&bus->conf_mutex);
    239        
    240         const uint32_t conf_addr = CONF_ADDR(fun->bus, fun->dev, fun->fn, reg);
    241         void *addr = bus->conf_data_port + (reg & 3);
    242        
    243         pio_write_32(bus->conf_addr_port, host2uint32_t_le(conf_addr));
    244        
     233
     234        pio_write_32(bus->conf_addr_reg, host2uint32_t_le(conf_addr));
     235
     236        /*
     237         * Always read full 32-bits from the PCI conf_data_port register and
     238         * get the desired portion of it afterwards. Some architectures do not
     239         * support shorter PIO reads offset from this register.
     240         */
     241        val = uint32_t_le2host(pio_read_32(bus->conf_data_reg));
     242
    245243        switch (len) {
    246244        case 1:
    247                 /* No endianness change for 1 byte */
    248                 buf[0] = pio_read_8(addr);
     245                *buf = (uint8_t) (val >> ((reg & 3) * 8));
    249246                break;
    250247        case 2:
    251                 ((uint16_t *) buf)[0] = uint16_t_le2host(pio_read_16(addr));
     248                *((uint16_t *) buf) = (uint16_t) (val >> ((reg & 3)) * 8);
    252249                break;
    253250        case 4:
    254                 ((uint32_t *) buf)[0] = uint32_t_le2host(pio_read_32(addr));
     251                *((uint32_t *) buf) = (uint32_t) val;
    255252                break;
    256253        }
     
    261258static void pci_conf_write(pci_fun_t *fun, int reg, uint8_t *buf, size_t len)
    262259{
     260        const uint32_t conf_addr = CONF_ADDR(fun->bus, fun->dev, fun->fn, reg);
    263261        pci_bus_t *bus = pci_bus_from_fun(fun);
     262        uint32_t val = 0; // Prevent -Werror=maybe-uninitialized
    264263       
    265264        fibril_mutex_lock(&bus->conf_mutex);
    266        
    267         const uint32_t conf_addr = CONF_ADDR(fun->bus, fun->dev, fun->fn, reg);
    268         void *addr = bus->conf_data_port + (reg & 3);
    269        
    270         pio_write_32(bus->conf_addr_port, host2uint32_t_le(conf_addr));
     265
     266        /*
     267         * Prepare to write full 32-bits to the PCI conf_data_port register.
     268         * Some architectures do not support shorter PIO writes offset from this
     269         * register.
     270         */
     271
     272        if (len < 4) {
     273                /*
     274                 * We have fewer than full 32-bits, so we need to read the
     275                 * missing bits first.
     276                 */
     277                pio_write_32(bus->conf_addr_reg, host2uint32_t_le(conf_addr));
     278                val = uint32_t_le2host(pio_read_32(bus->conf_data_reg));
     279        }
    271280       
    272281        switch (len) {
    273282        case 1:
    274                 /* No endianness change for 1 byte */
    275                 pio_write_8(addr, buf[0]);
     283                val &= ~(0xffU << ((reg & 3) * 8));
     284                val |= *buf << ((reg & 3) * 8);
    276285                break;
    277286        case 2:
    278                 pio_write_16(addr, host2uint16_t_le(((uint16_t *) buf)[0]));
     287                val &= ~(0xffffU << ((reg & 3) * 8));
     288                val |= *((uint16_t *) buf) << ((reg & 3) * 8);
    279289                break;
    280290        case 4:
    281                 pio_write_32(addr, host2uint32_t_le(((uint32_t *) buf)[0]));
     291                val = *((uint32_t *) buf);
    282292                break;
    283293        }
     294
     295        pio_write_32(bus->conf_addr_reg, host2uint32_t_le(conf_addr));
     296        pio_write_32(bus->conf_data_reg, host2uint32_t_le(val));
    284297       
    285298        fibril_mutex_unlock(&bus->conf_mutex);
     
    328341
    329342        /* Vendor ID & Device ID, length(incl \0) 22 */
    330         rc = snprintf(match_id_str, ID_MAX_STR_LEN, "pci/ven=%04x&dev=%04x",
    331             fun->vendor_id, fun->device_id);
     343        rc = snprintf(match_id_str, ID_MAX_STR_LEN, "pci/ven=%04"
     344            PRIx16 "&dev=%04" PRIx16, fun->vendor_id, fun->device_id);
    332345        if (rc < 0) {
    333346                ddf_msg(LVL_ERROR, "Failed creating match ID str: %s",
     
    412425                hw_resources[count].res.io_range.address = range_addr;
    413426                hw_resources[count].res.io_range.size = range_size;
     427                hw_resources[count].res.io_range.relative = true;
    414428                hw_resources[count].res.io_range.endianness = LITTLE_ENDIAN;
    415429        } else {
     
    417431                hw_resources[count].res.mem_range.address = range_addr;
    418432                hw_resources[count].res.mem_range.size = range_size;
     433                hw_resources[count].res.mem_range.relative = false;
    419434                hw_resources[count].res.mem_range.endianness = LITTLE_ENDIAN;
    420435        }
     
    434449{
    435450        /* Value of the BAR */
    436         uint32_t val, mask;
     451        uint32_t val;
     452        uint32_t bar;
     453        uint32_t mask;
     454
    437455        /* IO space address */
    438456        bool io;
     
    472490        /* Get the address mask. */
    473491        pci_conf_write_32(fun, addr, 0xffffffff);
    474         mask &= pci_conf_read_32(fun, addr);
    475        
     492        bar = pci_conf_read_32(fun, addr);
     493
     494        /*
     495         * Unimplemented BARs read back as all 0's.
     496         */
     497        if (!bar)
     498                return addr + (addrw64 ? 8 : 4);
     499
     500        mask &= bar;   
     501
    476502        /* Restore the original value. */
    477503        pci_conf_write_32(fun, addr, val);
     
    521547{
    522548        uint8_t irq = pci_conf_read_8(fun, PCI_BRIDGE_INT_LINE);
    523         if (irq != 0xff)
     549        uint8_t pin = pci_conf_read_8(fun, PCI_BRIDGE_INT_PIN);
     550
     551        if (pin != 0 && irq != 0xff)
    524552                pci_add_interrupt(fun, irq);
    525553}
     
    584612                        pci_read_bars(fun);
    585613                        pci_read_interrupt(fun);
     614
     615                        /* Propagate the PIO window to the function. */
     616                        fun->pio_window = bus->pio_win;
    586617                       
    587618                        ddf_fun_set_ops(fun->fnode, &pci_fun_ops);
     
    614645static int pci_dev_add(ddf_dev_t *dnode)
    615646{
     647        hw_resource_list_t hw_resources;
    616648        pci_bus_t *bus = NULL;
    617649        ddf_fun_t *ctl = NULL;
     
    639671                goto fail;
    640672        }
    641        
    642         hw_resource_list_t hw_resources;
     673
     674        rc = pio_window_get(sess, &bus->pio_win);
     675        if (rc != EOK) {
     676                ddf_msg(LVL_ERROR, "pci_dev_add failed to get PIO window "
     677                    "for the device.");
     678                goto fail;
     679        }
    643680       
    644681        rc = hw_res_get_resource_list(sess, &hw_resources);
     
    663700            hw_resources.resources[1].res.io_range.address);
    664701       
    665         bus->conf_io_addr =
    666             (uint32_t) hw_resources.resources[0].res.io_range.address;
    667         bus->conf_io_data =
    668             (uint32_t) hw_resources.resources[1].res.io_range.address;
    669        
    670         if (pio_enable((void *)(uintptr_t)bus->conf_io_addr, 4,
    671             &bus->conf_addr_port)) {
     702        if (pio_enable_resource(&bus->pio_win, &hw_resources.resources[0],
     703            (void **) &bus->conf_addr_reg)) {
    672704                ddf_msg(LVL_ERROR, "Failed to enable configuration ports.");
    673705                rc = EADDRNOTAVAIL;
    674706                goto fail;
    675707        }
    676         if (pio_enable((void *)(uintptr_t)bus->conf_io_data, 4,
    677             &bus->conf_data_port)) {
     708        if (pio_enable_resource(&bus->pio_win, &hw_resources.resources[1],
     709            (void **) &bus->conf_data_reg)) {
    678710                ddf_msg(LVL_ERROR, "Failed to enable configuration ports.");
    679711                rc = EADDRNOTAVAIL;
     
    730762{
    731763        ddf_log_init(NAME);
    732         pci_fun_ops.interfaces[HW_RES_DEV_IFACE] = &pciintel_hw_res_ops;
    733         pci_fun_ops.interfaces[PCI_DEV_IFACE] = &pci_dev_ops;
    734764}
    735765
     
    759789        fun->vendor_id = pci_conf_read_16(fun, PCI_VENDOR_ID);
    760790        fun->device_id = pci_conf_read_16(fun, PCI_DEVICE_ID);
     791       
     792        /* Explicitly enable PCI bus mastering */
     793        fun->command = pci_conf_read_16(fun, PCI_COMMAND) |
     794            PCI_COMMAND_MASTER;
     795        pci_conf_write_16(fun, PCI_COMMAND, fun->command);
     796       
    761797        fun->class_code = pci_conf_read_8(fun, PCI_BASE_CLASS);
    762798        fun->subclass_code = pci_conf_read_8(fun, PCI_SUB_CLASS);
Note: See TracChangeset for help on using the changeset viewer.