Changeset 82721f5 in mainline


Ignore:
Timestamp:
2013-09-09T19:45:31Z (11 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
c501bc4
Parents:
a1ecb88
Message:

Use only aligned 32-bit accesses to read/write the PCI configuration data register.

  • Some platforms (e.g. Malta) cannot do smaller accesses to offset addresses.
File:
1 edited

Legend:

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

    ra1ecb88 r82721f5  
    233233static void pci_conf_read(pci_fun_t *fun, int reg, uint8_t *buf, size_t len)
    234234{
     235        const uint32_t conf_addr = CONF_ADDR(fun->bus, fun->dev, fun->fn, reg);
    235236        pci_bus_t *bus = pci_bus_from_fun(fun);
     237        uint32_t val;
    236238       
    237239        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        
     240
    242241        pio_write_32(bus->conf_addr_port, host2uint32_t_le(conf_addr));
    243        
     242
     243        /*
     244         * Always read full 32-bits from the PCI conf_data_port register and
     245         * get the desired portion of it afterwards. Some architectures do not
     246         * support shorter PIO reads offset from this register.
     247         */
     248        val = uint32_t_le2host(pio_read_32(bus->conf_data_port));
     249
    244250        switch (len) {
    245251        case 1:
    246                 /* No endianness change for 1 byte */
    247                 buf[0] = pio_read_8(addr);
     252                *buf = (uint8_t) (val >> ((reg & 3) * 8));
    248253                break;
    249254        case 2:
    250                 ((uint16_t *) buf)[0] = uint16_t_le2host(pio_read_16(addr));
     255                *((uint16_t *) buf) = (uint16_t) (val >> ((reg & 3)) * 8);
    251256                break;
    252257        case 4:
    253                 ((uint32_t *) buf)[0] = uint32_t_le2host(pio_read_32(addr));
     258                *((uint32_t *) buf) = (uint32_t) val;
    254259                break;
    255260        }
     
    260265static void pci_conf_write(pci_fun_t *fun, int reg, uint8_t *buf, size_t len)
    261266{
     267        const uint32_t conf_addr = CONF_ADDR(fun->bus, fun->dev, fun->fn, reg);
    262268        pci_bus_t *bus = pci_bus_from_fun(fun);
     269        uint32_t val;
    263270       
    264271        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));
     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                pio_write_32(bus->conf_addr_port, host2uint32_t_le(conf_addr));
     285                val = uint32_t_le2host(pio_read_32(bus->conf_data_port));
     286        }
    270287       
    271288        switch (len) {
    272289        case 1:
    273                 /* No endianness change for 1 byte */
    274                 pio_write_8(addr, buf[0]);
     290                val &= ~(0xffU << ((reg & 3) * 8));
     291                val |= *buf << ((reg & 3) * 8);
    275292                break;
    276293        case 2:
    277                 pio_write_16(addr, host2uint16_t_le(((uint16_t *) buf)[0]));
     294                val &= ~(0xffffU << ((reg & 3) * 8));
     295                val |= *((uint16_t *) buf) << ((reg & 3) * 8);
    278296                break;
    279297        case 4:
    280                 pio_write_32(addr, host2uint32_t_le(((uint32_t *) buf)[0]));
     298                val = *((uint32_t *) buf);
    281299                break;
    282300        }
     301
     302        pio_write_32(bus->conf_addr_port, host2uint32_t_le(conf_addr));
     303        pio_write_32(bus->conf_data_port, host2uint32_t_le(val));
    283304       
    284305        fibril_mutex_unlock(&bus->conf_mutex);
Note: See TracChangeset for help on using the changeset viewer.