Changeset b0f00a9 in mainline for uspace/drv/bus/pci/pciintel/pci.c


Ignore:
Timestamp:
2011-11-06T22:21:05Z (14 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
898e847
Parents:
2bdf8313 (diff), 7b5f4c9 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge mainline changes.

File:
1 moved

Legend:

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

    r2bdf8313 rb0f00a9  
    5252#include <ipc/devman.h>
    5353#include <ipc/dev_iface.h>
     54#include <ipc/irc.h>
     55#include <ns.h>
     56#include <ipc/services.h>
     57#include <sysinfo.h>
    5458#include <ops/hw_res.h>
    5559#include <device/hw_res.h>
    5660#include <ddi.h>
    5761#include <libarch/ddi.h>
     62#include <pci_dev_iface.h>
    5863
    5964#include "pci.h"
     
    7277/** Obtain PCI bus soft-state from function soft-state */
    7378#define PCI_BUS_FROM_FUN(fun) ((fun)->busptr)
     79
     80/** Max is 47, align to something nice. */
     81#define ID_MAX_STR_LEN 50
    7482
    7583static hw_resource_list_t *pciintel_get_resources(ddf_fun_t *fnode)
     
    8492static bool pciintel_enable_interrupt(ddf_fun_t *fnode)
    8593{
    86         /* TODO */
    87        
    88         return false;
     94        /* This is an old ugly way, copied from ne2000 driver */
     95        assert(fnode);
     96        pci_fun_t *dev_data = (pci_fun_t *) fnode->driver_data;
     97       
     98        sysarg_t apic;
     99        sysarg_t i8259;
     100       
     101        async_sess_t *irc_sess = NULL;
     102       
     103        if (((sysinfo_get_value("apic", &apic) == EOK) && (apic))
     104            || ((sysinfo_get_value("i8259", &i8259) == EOK) && (i8259))) {
     105                irc_sess = service_connect_blocking(EXCHANGE_SERIALIZE,
     106                    SERVICE_IRC, 0, 0);
     107        }
     108       
     109        if (!irc_sess)
     110                return false;
     111       
     112        size_t i = 0;
     113        hw_resource_list_t *res = &dev_data->hw_resources;
     114        for (; i < res->count; i++) {
     115                if (res->resources[i].type == INTERRUPT) {
     116                        const int irq = res->resources[i].res.interrupt.irq;
     117                       
     118                        async_exch_t *exch = async_exchange_begin(irc_sess);
     119                        const int rc =
     120                            async_req_1_0(exch, IRC_ENABLE_INTERRUPT, irq);
     121                        async_exchange_end(exch);
     122                       
     123                        if (rc != EOK) {
     124                                async_hangup(irc_sess);
     125                                return false;
     126                        }
     127                }
     128        }
     129       
     130        async_hangup(irc_sess);
     131        return true;
     132}
     133
     134static int pci_config_space_write_32(ddf_fun_t *fun, uint32_t address,
     135    uint32_t data)
     136{
     137        if (address > 252)
     138                return EINVAL;
     139        pci_conf_write_32(PCI_FUN(fun), address, data);
     140        return EOK;
     141}
     142
     143static int pci_config_space_write_16(
     144    ddf_fun_t *fun, uint32_t address, uint16_t data)
     145{
     146        if (address > 254)
     147                return EINVAL;
     148        pci_conf_write_16(PCI_FUN(fun), address, data);
     149        return EOK;
     150}
     151
     152static int pci_config_space_write_8(
     153    ddf_fun_t *fun, uint32_t address, uint8_t data)
     154{
     155        if (address > 255)
     156                return EINVAL;
     157        pci_conf_write_8(PCI_FUN(fun), address, data);
     158        return EOK;
     159}
     160
     161static int pci_config_space_read_32(
     162    ddf_fun_t *fun, uint32_t address, uint32_t *data)
     163{
     164        if (address > 252)
     165                return EINVAL;
     166        *data = pci_conf_read_32(PCI_FUN(fun), address);
     167        return EOK;
     168}
     169
     170static int pci_config_space_read_16(
     171    ddf_fun_t *fun, uint32_t address, uint16_t *data)
     172{
     173        if (address > 254)
     174                return EINVAL;
     175        *data = pci_conf_read_16(PCI_FUN(fun), address);
     176        return EOK;
     177}
     178
     179static int pci_config_space_read_8(
     180    ddf_fun_t *fun, uint32_t address, uint8_t *data)
     181{
     182        if (address > 255)
     183                return EINVAL;
     184        *data = pci_conf_read_8(PCI_FUN(fun), address);
     185        return EOK;
    89186}
    90187
     
    94191};
    95192
    96 static ddf_dev_ops_t pci_fun_ops;
     193static pci_dev_iface_t pci_dev_ops = {
     194        .config_space_read_8 = &pci_config_space_read_8,
     195        .config_space_read_16 = &pci_config_space_read_16,
     196        .config_space_read_32 = &pci_config_space_read_32,
     197        .config_space_write_8 = &pci_config_space_write_8,
     198        .config_space_write_16 = &pci_config_space_write_16,
     199        .config_space_write_32 = &pci_config_space_write_32
     200};
     201
     202static ddf_dev_ops_t pci_fun_ops = {
     203        .interfaces[HW_RES_DEV_IFACE] = &pciintel_hw_res_ops,
     204        .interfaces[PCI_DEV_IFACE] = &pci_dev_ops
     205};
    97206
    98207static int pci_add_device(ddf_dev_t *);
     208static int pci_fun_online(ddf_fun_t *);
     209static int pci_fun_offline(ddf_fun_t *);
    99210
    100211/** PCI bus driver standard operations */
    101212static driver_ops_t pci_ops = {
    102         .add_device = &pci_add_device
     213        .add_device = &pci_add_device,
     214        .fun_online = &pci_fun_online,
     215        .fun_offline = &pci_fun_offline,
    103216};
    104217
     
    109222};
    110223
    111 static pci_bus_t *pci_bus_new(void)
    112 {
    113         pci_bus_t *bus;
    114        
    115         bus = (pci_bus_t *) calloc(1, sizeof(pci_bus_t));
    116         if (bus == NULL)
    117                 return NULL;
    118        
    119         fibril_mutex_initialize(&bus->conf_mutex);
    120         return bus;
    121 }
    122 
    123 static void pci_bus_delete(pci_bus_t *bus)
    124 {
    125         assert(bus != NULL);
    126         free(bus);
    127 }
    128 
    129224static void pci_conf_read(pci_fun_t *fun, int reg, uint8_t *buf, size_t len)
    130225{
     
    133228        fibril_mutex_lock(&bus->conf_mutex);
    134229       
    135         uint32_t conf_addr;
    136         conf_addr = CONF_ADDR(fun->bus, fun->dev, fun->fn, reg);
     230        const uint32_t conf_addr = CONF_ADDR(fun->bus, fun->dev, fun->fn, reg);
    137231        void *addr = bus->conf_data_port + (reg & 3);
    138232       
     
    219313void pci_fun_create_match_ids(pci_fun_t *fun)
    220314{
    221         char *match_id_str;
    222315        int rc;
    223        
    224         asprintf(&match_id_str, "pci/ven=%04x&dev=%04x",
     316        char match_id_str[ID_MAX_STR_LEN];
     317
     318        /* Vendor ID & Device ID, length(incl \0) 22 */
     319        rc = snprintf(match_id_str, ID_MAX_STR_LEN, "pci/ven=%04x&dev=%04x",
    225320            fun->vendor_id, fun->device_id);
    226 
    227         if (match_id_str == NULL) {
    228                 ddf_msg(LVL_ERROR, "Out of memory creating match ID.");
    229                 return;
     321        if (rc < 0) {
     322                ddf_msg(LVL_ERROR, "Failed creating match ID str: %s",
     323                    str_error(rc));
    230324        }
    231325
    232326        rc = ddf_fun_add_match_id(fun->fnode, match_id_str, 90);
    233327        if (rc != EOK) {
    234                 ddf_msg(LVL_ERROR, "Failed adding match ID: %s",
     328                ddf_msg(LVL_ERROR, "Failed adding match ID: %s", str_error(rc));
     329        }
     330
     331        /* Class, subclass, prog IF, revision, length(incl \0) 47 */
     332        rc = snprintf(match_id_str, ID_MAX_STR_LEN,
     333            "pci/class=%02x&subclass=%02x&progif=%02x&revision=%02x",
     334            fun->class_code, fun->subclass_code, fun->prog_if, fun->revision);
     335        if (rc < 0) {
     336                ddf_msg(LVL_ERROR, "Failed creating match ID str: %s",
    235337                    str_error(rc));
    236338        }
    237        
    238         /* TODO add more ids (with subsys ids, using class id etc.) */
     339
     340        rc = ddf_fun_add_match_id(fun->fnode, match_id_str, 70);
     341        if (rc != EOK) {
     342                ddf_msg(LVL_ERROR, "Failed adding match ID: %s", str_error(rc));
     343        }
     344
     345        /* Class, subclass, prog IF, length(incl \0) 35 */
     346        rc = snprintf(match_id_str, ID_MAX_STR_LEN,
     347            "pci/class=%02x&subclass=%02x&progif=%02x",
     348            fun->class_code, fun->subclass_code, fun->prog_if);
     349        if (rc < 0) {
     350                ddf_msg(LVL_ERROR, "Failed creating match ID str: %s",
     351                    str_error(rc));
     352        }
     353
     354        rc = ddf_fun_add_match_id(fun->fnode, match_id_str, 60);
     355        if (rc != EOK) {
     356                ddf_msg(LVL_ERROR, "Failed adding match ID: %s", str_error(rc));
     357        }
     358
     359        /* Class, subclass, length(incl \0) 25 */
     360        rc = snprintf(match_id_str, ID_MAX_STR_LEN,
     361            "pci/class=%02x&subclass=%02x",
     362            fun->class_code, fun->subclass_code);
     363        if (rc < 0) {
     364                ddf_msg(LVL_ERROR, "Failed creating match ID str: %s",
     365                    str_error(rc));
     366        }
     367
     368        rc = ddf_fun_add_match_id(fun->fnode, match_id_str, 50);
     369        if (rc != EOK) {
     370                ddf_msg(LVL_ERROR, "Failed adding match ID: %s", str_error(rc));
     371        }
     372
     373        /* Class, length(incl \0) 13 */
     374        rc = snprintf(match_id_str, ID_MAX_STR_LEN, "pci/class=%02x",
     375            fun->class_code);
     376        if (rc < 0) {
     377                ddf_msg(LVL_ERROR, "Failed creating match ID str: %s",
     378                    str_error(rc));
     379        }
     380
     381        rc = ddf_fun_add_match_id(fun->fnode, match_id_str, 40);
     382        if (rc != EOK) {
     383                ddf_msg(LVL_ERROR, "Failed adding match ID: %s", str_error(rc));
     384        }
     385
     386        /* TODO add subsys ids, but those exist only in header type 0 */
    239387}
    240388
     
    288436        /* Get the value of the BAR. */
    289437        val = pci_conf_read_32(fun, addr);
     438
     439#define IO_MASK  (~0x3)
     440#define MEM_MASK (~0xf)
    290441       
    291442        io = (bool) (val & 1);
    292443        if (io) {
    293444                addrw64 = false;
     445                mask = IO_MASK;
    294446        } else {
     447                mask = MEM_MASK;
    295448                switch ((val >> 1) & 3) {
    296449                case 0:
     
    308461        /* Get the address mask. */
    309462        pci_conf_write_32(fun, addr, 0xffffffff);
    310         mask = pci_conf_read_32(fun, addr);
     463        mask &= pci_conf_read_32(fun, addr);
    311464       
    312465        /* Restore the original value. */
     
    382535                for (fnum = 0; multi && fnum < 8; fnum++) {
    383536                        pci_fun_init(fun, bus_num, dnum, fnum);
    384                         fun->vendor_id = pci_conf_read_16(fun,
    385                             PCI_VENDOR_ID);
    386                         fun->device_id = pci_conf_read_16(fun,
    387                             PCI_DEVICE_ID);
    388537                        if (fun->vendor_id == 0xffff) {
    389538                                /*
     
    412561                       
    413562                        fnode = ddf_fun_create(bus->dnode, fun_inner, fun_name);
     563                        free(fun_name);
    414564                        if (fnode == NULL) {
    415565                                ddf_msg(LVL_ERROR, "Failed creating function.");
     
    417567                        }
    418568                       
    419                         free(fun_name);
    420569                        fun->fnode = fnode;
    421570                       
     
    469618       
    470619        ddf_msg(LVL_DEBUG, "pci_add_device");
    471         dnode->parent_phone = -1;
    472        
    473         bus = pci_bus_new();
     620        dnode->parent_sess = NULL;
     621       
     622        bus = ddf_dev_data_alloc(dnode, sizeof(pci_bus_t));
    474623        if (bus == NULL) {
    475624                ddf_msg(LVL_ERROR, "pci_add_device allocation failed.");
     
    477626                goto fail;
    478627        }
     628        fibril_mutex_initialize(&bus->conf_mutex);
     629
    479630        bus->dnode = dnode;
    480631        dnode->driver_data = bus;
    481632       
    482         dnode->parent_phone = devman_parent_device_connect(dnode->handle,
    483             IPC_FLAG_BLOCKING);
    484         if (dnode->parent_phone < 0) {
     633        dnode->parent_sess = devman_parent_device_connect(EXCHANGE_SERIALIZE,
     634            dnode->handle, IPC_FLAG_BLOCKING);
     635        if (!dnode->parent_sess) {
    485636                ddf_msg(LVL_ERROR, "pci_add_device failed to connect to the "
    486                     "parent's driver.");
    487                 rc = dnode->parent_phone;
     637                    "parent driver.");
     638                rc = ENOENT;
    488639                goto fail;
    489640        }
     
    491642        hw_resource_list_t hw_resources;
    492643       
    493         rc = hw_res_get_resource_list(dnode->parent_phone, &hw_resources);
     644        rc = hw_res_get_resource_list(dnode->parent_sess, &hw_resources);
    494645        if (rc != EOK) {
    495646                ddf_msg(LVL_ERROR, "pci_add_device failed to get hw resources "
     
    542693       
    543694fail:
    544         if (bus != NULL)
    545                 pci_bus_delete(bus);
    546         if (dnode->parent_phone >= 0)
    547                 async_hangup(dnode->parent_phone);
     695        if (dnode->parent_sess)
     696                async_hangup(dnode->parent_sess);
     697       
    548698        if (got_res)
    549699                hw_res_clean_resource_list(&hw_resources);
     700       
    550701        if (ctl != NULL)
    551702                ddf_fun_destroy(ctl);
    552 
     703       
    553704        return rc;
     705}
     706
     707static int pci_fun_online(ddf_fun_t *fun)
     708{
     709        ddf_msg(LVL_DEBUG, "pci_fun_online()");
     710        return ddf_fun_online(fun);
     711}
     712
     713static int pci_fun_offline(ddf_fun_t *fun)
     714{
     715        ddf_msg(LVL_DEBUG, "pci_fun_offline()");
     716        return ddf_fun_offline(fun);
    554717}
    555718
     
    558721        ddf_log_init(NAME, LVL_ERROR);
    559722        pci_fun_ops.interfaces[HW_RES_DEV_IFACE] = &pciintel_hw_res_ops;
     723        pci_fun_ops.interfaces[PCI_DEV_IFACE] = &pci_dev_ops;
    560724}
    561725
     
    577741        fun->dev = dev;
    578742        fun->fn = fn;
     743        fun->vendor_id = pci_conf_read_16(fun, PCI_VENDOR_ID);
     744        fun->device_id = pci_conf_read_16(fun, PCI_DEVICE_ID);
     745        fun->class_code = pci_conf_read_8(fun, PCI_BASE_CLASS);
     746        fun->subclass_code = pci_conf_read_8(fun, PCI_SUB_CLASS);
     747        fun->prog_if = pci_conf_read_8(fun, PCI_PROG_IF);
     748        fun->revision = pci_conf_read_8(fun, PCI_REVISION_ID);
    579749}
    580750
     
    597767bool pci_alloc_resource_list(pci_fun_t *fun)
    598768{
    599         fun->hw_resources.resources =
    600             (hw_resource_t *) malloc(PCI_MAX_HW_RES * sizeof(hw_resource_t));
    601         return fun->hw_resources.resources != NULL;
     769        fun->hw_resources.resources = fun->resources;
     770        return true;
    602771}
    603772
    604773void pci_clean_resource_list(pci_fun_t *fun)
    605774{
    606         if (fun->hw_resources.resources != NULL) {
    607                 free(fun->hw_resources.resources);
    608                 fun->hw_resources.resources = NULL;
    609         }
     775        fun->hw_resources.resources = NULL;
    610776}
    611777
     
    629795size_t pci_bar_mask_to_size(uint32_t mask)
    630796{
    631         return ((mask & 0xfffffff0) ^ 0xffffffff) + 1;
     797        size_t size = mask & ~(mask - 1);
     798        return size;
    632799}
    633800
Note: See TracChangeset for help on using the changeset viewer.