Ignore:
File:
1 edited

Legend:

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

    r92d5279 rc90aed4  
    5151#include <ddf/log.h>
    5252#include <ipc/dev_iface.h>
    53 #include <irc.h>
     53#include <ipc/irc.h>
     54#include <ns.h>
     55#include <ipc/services.h>
     56#include <sysinfo.h>
    5457#include <ops/hw_res.h>
    5558#include <device/hw_res.h>
    56 #include <ops/pio_window.h>
    57 #include <device/pio_window.h>
    5859#include <ddi.h>
    5960#include <pci_dev_iface.h>
     
    6364#define NAME "pciintel"
    6465
    65 #define CONF_ADDR_ENABLE        (1 << 31)
    6666#define CONF_ADDR(bus, dev, fn, reg) \
    67         ((bus << 16) | (dev << 11) | (fn << 8) | (reg & ~3))
     67        ((1 << 31) | (bus << 16) | (dev << 11) | (fn << 8) | (reg & ~3))
    6868
    6969/** Obtain PCI function soft-state from DDF function node */
     
    104104        assert(fnode);
    105105        pci_fun_t *dev_data = pci_fun(fnode);
     106       
     107        sysarg_t apic;
     108        sysarg_t i8259;
     109       
     110        async_sess_t *irc_sess = NULL;
     111       
     112        if (((sysinfo_get_value("apic", &apic) == EOK) && (apic))
     113            || ((sysinfo_get_value("i8259", &i8259) == EOK) && (i8259))) {
     114                irc_sess = service_connect_blocking(EXCHANGE_SERIALIZE,
     115                    SERVICE_IRC, 0, 0);
     116        }
     117       
     118        if (!irc_sess)
     119                return false;
    106120       
    107121        size_t i = 0;
     
    109123        for (; i < res->count; i++) {
    110124                if (res->resources[i].type == INTERRUPT) {
    111                         int rc = irc_enable_interrupt(
    112                             res->resources[i].res.interrupt.irq);
    113                        
    114                         if (rc != EOK)
     125                        const int irq = res->resources[i].res.interrupt.irq;
     126                       
     127                        async_exch_t *exch = async_exchange_begin(irc_sess);
     128                        const int rc =
     129                            async_req_1_0(exch, IRC_ENABLE_INTERRUPT, irq);
     130                        async_exchange_end(exch);
     131                       
     132                        if (rc != EOK) {
     133                                async_hangup(irc_sess);
    115134                                return false;
     135                        }
    116136                }
    117137        }
    118138       
     139        async_hangup(irc_sess);
    119140        return true;
    120141}
    121142
    122 static pio_window_t *pciintel_get_pio_window(ddf_fun_t *fnode)
    123 {
    124         pci_fun_t *fun = pci_fun(fnode);
    125        
    126         if (fun == NULL)
    127                 return NULL;
    128         return &fun->pio_window;
    129 }
    130 
    131 
    132 static int config_space_write_32(ddf_fun_t *fun, uint32_t address,
     143static int pci_config_space_write_32(ddf_fun_t *fun, uint32_t address,
    133144    uint32_t data)
    134145{
     
    139150}
    140151
    141 static int config_space_write_16(
     152static int pci_config_space_write_16(
    142153    ddf_fun_t *fun, uint32_t address, uint16_t data)
    143154{
     
    148159}
    149160
    150 static int config_space_write_8(
     161static int pci_config_space_write_8(
    151162    ddf_fun_t *fun, uint32_t address, uint8_t data)
    152163{
     
    157168}
    158169
    159 static int config_space_read_32(
     170static int pci_config_space_read_32(
    160171    ddf_fun_t *fun, uint32_t address, uint32_t *data)
    161172{
     
    166177}
    167178
    168 static int config_space_read_16(
     179static int pci_config_space_read_16(
    169180    ddf_fun_t *fun, uint32_t address, uint16_t *data)
    170181{
     
    175186}
    176187
    177 static int config_space_read_8(
     188static int pci_config_space_read_8(
    178189    ddf_fun_t *fun, uint32_t address, uint8_t *data)
    179190{
     
    189200};
    190201
    191 static pio_window_ops_t pciintel_pio_window_ops = {
    192         .get_pio_window = &pciintel_get_pio_window
    193 };
    194 
    195202static pci_dev_iface_t pci_dev_ops = {
    196         .config_space_read_8 = &config_space_read_8,
    197         .config_space_read_16 = &config_space_read_16,
    198         .config_space_read_32 = &config_space_read_32,
    199         .config_space_write_8 = &config_space_write_8,
    200         .config_space_write_16 = &config_space_write_16,
    201         .config_space_write_32 = &config_space_write_32
     203        .config_space_read_8 = &pci_config_space_read_8,
     204        .config_space_read_16 = &pci_config_space_read_16,
     205        .config_space_read_32 = &pci_config_space_read_32,
     206        .config_space_write_8 = &pci_config_space_write_8,
     207        .config_space_write_16 = &pci_config_space_write_16,
     208        .config_space_write_32 = &pci_config_space_write_32
    202209};
    203210
    204211static ddf_dev_ops_t pci_fun_ops = {
    205212        .interfaces[HW_RES_DEV_IFACE] = &pciintel_hw_res_ops,
    206         .interfaces[PIO_WINDOW_DEV_IFACE] = &pciintel_pio_window_ops,
    207213        .interfaces[PCI_DEV_IFACE] = &pci_dev_ops
    208214};
     
    227233static void pci_conf_read(pci_fun_t *fun, int reg, uint8_t *buf, size_t len)
    228234{
     235        pci_bus_t *bus = pci_bus_from_fun(fun);
     236       
     237        fibril_mutex_lock(&bus->conf_mutex);
     238       
    229239        const uint32_t conf_addr = CONF_ADDR(fun->bus, fun->dev, fun->fn, reg);
    230         pci_bus_t *bus = pci_bus_from_fun(fun);
    231         uint32_t val;
    232        
    233         fibril_mutex_lock(&bus->conf_mutex);
    234 
    235         if (bus->conf_addr_reg) {
    236                 pio_write_32(bus->conf_addr_reg,
    237                     host2uint32_t_le(CONF_ADDR_ENABLE | conf_addr));
    238                 /*
    239                  * Always read full 32-bits from the PCI conf_data_port
    240                  * register and get the desired portion of it afterwards. Some
    241                  * architectures do not support shorter PIO reads offset from
    242                  * this register.
    243                  */
    244                 val = uint32_t_le2host(pio_read_32(bus->conf_data_reg));
    245         } else {
    246                 val = uint32_t_le2host(pio_read_32(
    247                     &bus->conf_space[conf_addr / sizeof(ioport32_t)]));
    248         }
    249 
     240        void *addr = bus->conf_data_port + (reg & 3);
     241       
     242        pio_write_32(bus->conf_addr_port, host2uint32_t_le(conf_addr));
     243       
    250244        switch (len) {
    251245        case 1:
    252                 *buf = (uint8_t) (val >> ((reg & 3) * 8));
     246                /* No endianness change for 1 byte */
     247                buf[0] = pio_read_8(addr);
    253248                break;
    254249        case 2:
    255                 *((uint16_t *) buf) = (uint16_t) (val >> ((reg & 3)) * 8);
     250                ((uint16_t *) buf)[0] = uint16_t_le2host(pio_read_16(addr));
    256251                break;
    257252        case 4:
    258                 *((uint32_t *) buf) = (uint32_t) val;
     253                ((uint32_t *) buf)[0] = uint32_t_le2host(pio_read_32(addr));
    259254                break;
    260255        }
     
    265260static void pci_conf_write(pci_fun_t *fun, int reg, uint8_t *buf, size_t len)
    266261{
     262        pci_bus_t *bus = pci_bus_from_fun(fun);
     263       
     264        fibril_mutex_lock(&bus->conf_mutex);
     265       
    267266        const uint32_t conf_addr = CONF_ADDR(fun->bus, fun->dev, fun->fn, reg);
    268         pci_bus_t *bus = pci_bus_from_fun(fun);
    269         uint32_t val;
    270        
    271         fibril_mutex_lock(&bus->conf_mutex);
    272 
    273         /*
    274          * Prepare to write full 32-bits to the PCI conf_data_port register.
    275          * Some architectures do not support shorter PIO writes offset from this
    276          * register.
    277          */
    278 
    279         if (len < 4) {
    280                 /*
    281                  * We have fewer than full 32-bits, so we need to read the
    282                  * missing bits first.
    283                  */
    284                 if (bus->conf_addr_reg) {
    285                         pio_write_32(bus->conf_addr_reg,
    286                             host2uint32_t_le(CONF_ADDR_ENABLE | conf_addr));
    287                         val = uint32_t_le2host(pio_read_32(bus->conf_data_reg));
    288                 } else {
    289                         val = uint32_t_le2host(pio_read_32(
    290                             &bus->conf_space[conf_addr / sizeof(ioport32_t)]));
    291                 }
    292         }
     267        void *addr = bus->conf_data_port + (reg & 3);
     268       
     269        pio_write_32(bus->conf_addr_port, host2uint32_t_le(conf_addr));
    293270       
    294271        switch (len) {
    295272        case 1:
    296                 val &= ~(0xffU << ((reg & 3) * 8));
    297                 val |= *buf << ((reg & 3) * 8);
     273                /* No endianness change for 1 byte */
     274                pio_write_8(addr, buf[0]);
    298275                break;
    299276        case 2:
    300                 val &= ~(0xffffU << ((reg & 3) * 8));
    301                 val |= *((uint16_t *) buf) << ((reg & 3) * 8);
     277                pio_write_16(addr, host2uint16_t_le(((uint16_t *) buf)[0]));
    302278                break;
    303279        case 4:
    304                 val = *((uint32_t *) buf);
     280                pio_write_32(addr, host2uint32_t_le(((uint32_t *) buf)[0]));
    305281                break;
    306         }
    307 
    308         if (bus->conf_addr_reg) {
    309                 pio_write_32(bus->conf_addr_reg,
    310                     host2uint32_t_le(CONF_ADDR_ENABLE | conf_addr));
    311                 pio_write_32(bus->conf_data_reg, host2uint32_t_le(val));
    312         } else {
    313                 pio_write_32(&bus->conf_space[conf_addr / sizeof(ioport32_t)],
    314                     host2uint32_t_le(val));
    315282        }
    316283       
     
    444411                hw_resources[count].res.io_range.address = range_addr;
    445412                hw_resources[count].res.io_range.size = range_size;
    446                 hw_resources[count].res.io_range.relative = true;
    447413                hw_resources[count].res.io_range.endianness = LITTLE_ENDIAN;
    448414        } else {
     
    450416                hw_resources[count].res.mem_range.address = range_addr;
    451417                hw_resources[count].res.mem_range.size = range_size;
    452                 hw_resources[count].res.mem_range.relative = false;
    453418                hw_resources[count].res.mem_range.endianness = LITTLE_ENDIAN;
    454419        }
     
    468433{
    469434        /* Value of the BAR */
    470         uint32_t val;
    471         uint32_t bar;
    472         uint32_t mask;
    473 
     435        uint32_t val, mask;
    474436        /* IO space address */
    475437        bool io;
     
    509471        /* Get the address mask. */
    510472        pci_conf_write_32(fun, addr, 0xffffffff);
    511         bar = pci_conf_read_32(fun, addr);
    512 
    513         /*
    514          * Unimplemented BARs read back as all 0's.
    515          */
    516         if (!bar)
    517                 return addr + (addrw64 ? 8 : 4);
    518 
    519         mask &= bar;   
    520 
     473        mask &= pci_conf_read_32(fun, addr);
     474       
    521475        /* Restore the original value. */
    522476        pci_conf_write_32(fun, addr, val);
     
    566520{
    567521        uint8_t irq = pci_conf_read_8(fun, PCI_BRIDGE_INT_LINE);
    568         uint8_t pin = pci_conf_read_8(fun, PCI_BRIDGE_INT_PIN);
    569 
    570         if (pin != 0 && irq != 0xff)
     522        if (irq != 0xff)
    571523                pci_add_interrupt(fun, irq);
    572524}
     
    631583                        pci_read_bars(fun);
    632584                        pci_read_interrupt(fun);
    633 
    634                         /* Propagate the PIO window to the function. */
    635                         fun->pio_window = bus->pio_win;
    636585                       
    637586                        ddf_fun_set_ops(fun->fnode, &pci_fun_ops);
     
    639588                        ddf_msg(LVL_DEBUG, "Adding new function %s.",
    640589                            ddf_fun_get_name(fun->fnode));
    641 
     590                       
    642591                        pci_fun_create_match_ids(fun);
    643592                       
     
    664613static int pci_dev_add(ddf_dev_t *dnode)
    665614{
    666         hw_resource_list_t hw_resources;
    667615        pci_bus_t *bus = NULL;
    668616        ddf_fun_t *ctl = NULL;
     
    683631        bus->dnode = dnode;
    684632       
    685         sess = ddf_dev_parent_sess_create(dnode);
     633        sess = ddf_dev_parent_sess_create(dnode, EXCHANGE_SERIALIZE);
    686634        if (sess == NULL) {
    687635                ddf_msg(LVL_ERROR, "pci_dev_add failed to connect to the "
     
    690638                goto fail;
    691639        }
    692 
    693         rc = pio_window_get(sess, &bus->pio_win);
    694         if (rc != EOK) {
    695                 ddf_msg(LVL_ERROR, "pci_dev_add failed to get PIO window "
    696                     "for the device.");
    697                 goto fail;
    698         }
     640       
     641        hw_resource_list_t hw_resources;
    699642       
    700643        rc = hw_res_get_resource_list(sess, &hw_resources);
     
    707650       
    708651       
    709         assert(hw_resources.count >= 1);
    710 
    711         if (hw_resources.count == 1) {
    712                 assert(hw_resources.resources[0].type == MEM_RANGE);
    713 
    714                 ddf_msg(LVL_DEBUG, "conf_addr_space = %" PRIx64 ".",
    715                     hw_resources.resources[0].res.mem_range.address);
    716 
    717                 if (pio_enable_resource(&bus->pio_win,
    718                     &hw_resources.resources[0],
    719                     (void **) &bus->conf_space)) {
    720                         ddf_msg(LVL_ERROR,
    721                             "Failed to map configuration space.");
    722                         rc = EADDRNOTAVAIL;
    723                         goto fail;
    724                 }
    725                
    726         } else {
    727                 assert(hw_resources.resources[0].type == IO_RANGE);
    728                 assert(hw_resources.resources[0].res.io_range.size >= 4);
    729        
    730                 assert(hw_resources.resources[1].type == IO_RANGE);
    731                 assert(hw_resources.resources[1].res.io_range.size >= 4);
    732        
    733                 ddf_msg(LVL_DEBUG, "conf_addr = %" PRIx64 ".",
    734                     hw_resources.resources[0].res.io_range.address);
    735                 ddf_msg(LVL_DEBUG, "data_addr = %" PRIx64 ".",
    736                     hw_resources.resources[1].res.io_range.address);
    737        
    738                 if (pio_enable_resource(&bus->pio_win,
    739                     &hw_resources.resources[0],
    740                     (void **) &bus->conf_addr_reg)) {
    741                         ddf_msg(LVL_ERROR,
    742                             "Failed to enable configuration ports.");
    743                         rc = EADDRNOTAVAIL;
    744                         goto fail;
    745                 }
    746                 if (pio_enable_resource(&bus->pio_win,
    747                     &hw_resources.resources[1],
    748                     (void **) &bus->conf_data_reg)) {
    749                         ddf_msg(LVL_ERROR,
    750                             "Failed to enable configuration ports.");
    751                         rc = EADDRNOTAVAIL;
    752                         goto fail;
    753                 }
     652        assert(hw_resources.count > 1);
     653        assert(hw_resources.resources[0].type == IO_RANGE);
     654        assert(hw_resources.resources[0].res.io_range.size >= 4);
     655       
     656        assert(hw_resources.resources[1].type == IO_RANGE);
     657        assert(hw_resources.resources[1].res.io_range.size >= 4);
     658       
     659        ddf_msg(LVL_DEBUG, "conf_addr = %" PRIx64 ".",
     660            hw_resources.resources[0].res.io_range.address);
     661        ddf_msg(LVL_DEBUG, "data_addr = %" PRIx64 ".",
     662            hw_resources.resources[1].res.io_range.address);
     663       
     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)) {
     671                ddf_msg(LVL_ERROR, "Failed to enable configuration ports.");
     672                rc = EADDRNOTAVAIL;
     673                goto fail;
     674        }
     675        if (pio_enable((void *)(uintptr_t)bus->conf_io_data, 4,
     676            &bus->conf_data_port)) {
     677                ddf_msg(LVL_ERROR, "Failed to enable configuration ports.");
     678                rc = EADDRNOTAVAIL;
     679                goto fail;
    754680        }
    755681       
     
    803729{
    804730        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;
    805733}
    806734
Note: See TracChangeset for help on using the changeset viewer.