Ignore:
Timestamp:
2013-09-12T22:05:13Z (11 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
4285851
Parents:
695b6ff (diff), 7de1988c (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:

Support for PIO window-relative and absolute HW resource ranges.

The goal of this merge is to allow bus drivers to pass resources with IO
and memory ranges to the child drivers either in the PIO window-relative
form or system bus absolute form. Using the PIO window and the
relative/absolute attribute of a range, each driver can now reconstruct
both forms. Helper functions are provided to automate these
transformations as much as possible.

Changes in this merge in a greater detail:

  • Support for PIO_WINDOW_DEV_IFACE in isa so that it can provide the PIO window to its children.
  • Add 'relative' member to both hw_resource_t.res.mem_range and hw_resource_t.res.io_range so that the drivers can actually tell whether a range is absolute (eg. it was absolutized by its parent).
  • Add pio_enable_resource() to allow drivers to enable PIO without the need to actually care about what kind of range the resource contains. This is used by pci now.
  • Automate things even more for drivers that use hw_res_get_list_parsed(). The parsed HW resources compute both forms (relative/absolute) and offer it to the driver which is using them. Such a driver then uses whatever form is more fit for it and its purposes.
  • Drivers using the parsed resources can use pio_enable_range() to enable PIO and RNGABS*()/RNGREL()/RNGSZ courtesy macros for easier access to the actual range address/size are provided.
  • Device drivers affected by these API changes were converted.
  • uhcirh now requires uhci to provide PIO_WINDOW_DEV_IFACE; however, the uhcirh driver is removed in the feature USB branch so there was no point in implementing this feature and UHCI USB is thus temporarily broken.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/c/generic/device/hw_res_parsed.c

    r695b6ff rddd0499d  
    8080}
    8181
     82static uint64_t absolutize(uint64_t addr, bool relative, uint64_t base)
     83{
     84        if (!relative)
     85                return addr;
     86        else
     87                return addr + base;
     88}
     89
     90static uint64_t relativize(uint64_t addr, bool relative, uint64_t base)
     91{
     92        if (relative)
     93                return addr;
     94        else
     95                return addr - base;
     96}
     97
    8298static void hw_res_parse_add_io_range(hw_res_list_parsed_t *out,
    83     const hw_resource_t *res, int flags)
    84 {
     99    const pio_window_t *win, const hw_resource_t *res, int flags)
     100{
     101        endianness_t endianness;
     102        uint64_t absolute;
     103        uint64_t relative;
     104        size_t size;
     105
    85106        assert(res && (res->type == IO_RANGE));
    86107       
    87         uint64_t address = res->res.io_range.address;
    88         endianness_t endianness = res->res.io_range.endianness;
    89         size_t size = res->res.io_range.size;
     108        absolute = absolutize(res->res.io_range.address,
     109            res->res.io_range.relative, win->io.base);
     110        relative = relativize(res->res.io_range.address,
     111            res->res.io_range.relative, win->io.base);
     112        size = res->res.io_range.size;
     113        endianness = res->res.io_range.endianness;
    90114       
    91115        if ((size == 0) && (!(flags & HW_RES_KEEP_ZERO_AREA)))
     
    97121        if (!keep_duplicit) {
    98122                for (size_t i = 0; i < count; i++) {
    99                         uint64_t s_address = out->io_ranges.ranges[i].address;
    100                         size_t s_size = out->io_ranges.ranges[i].size;
     123                        uint64_t s_address;
     124                        size_t s_size;
     125
     126                        s_address = RNGABS(out->io_ranges.ranges[i]);
     127                        s_size = RNGSZ(out->io_ranges.ranges[i]);
    101128                       
    102                         if ((address == s_address) && (size == s_size))
    103                                 return;
    104                 }
    105         }
    106        
    107         out->io_ranges.ranges[count].address = address;
     129                        if ((absolute == s_address) && (size == s_size))
     130                                return;
     131                }
     132        }
     133       
     134        RNGABS(out->io_ranges.ranges[count]) = absolute;
     135        RNGREL(out->io_ranges.ranges[count]) = relative;
     136        RNGSZ(out->io_ranges.ranges[count]) = size;
    108137        out->io_ranges.ranges[count].endianness = endianness;
    109         out->io_ranges.ranges[count].size = size;
    110138        out->io_ranges.count++;
    111139}
    112140
    113141static void hw_res_parse_add_mem_range(hw_res_list_parsed_t *out,
    114     const hw_resource_t *res, int flags)
    115 {
     142    const pio_window_t *win, const hw_resource_t *res, int flags)
     143{
     144        endianness_t endianness;
     145        uint64_t absolute;
     146        uint64_t relative;
     147        size_t size;
     148       
    116149        assert(res && (res->type == MEM_RANGE));
    117150       
    118         uint64_t address = res->res.mem_range.address;
    119         endianness_t endianness = res->res.mem_range.endianness;
    120         size_t size = res->res.mem_range.size;
     151        absolute = absolutize(res->res.mem_range.address,
     152            res->res.mem_range.relative, win->mem.base);
     153        relative = relativize(res->res.mem_range.address,
     154            res->res.mem_range.relative, win->mem.base);
     155        size = res->res.mem_range.size;
     156        endianness = res->res.mem_range.endianness;
    121157       
    122158        if ((size == 0) && (!(flags & HW_RES_KEEP_ZERO_AREA)))
     
    128164        if (!keep_duplicit) {
    129165                for (size_t i = 0; i < count; ++i) {
    130                         uint64_t s_address = out->mem_ranges.ranges[i].address;
    131                         size_t s_size = out->mem_ranges.ranges[i].size;
     166                        uint64_t s_address;
     167                        size_t s_size;
     168
     169                        s_address = RNGABS(out->mem_ranges.ranges[i]);;
     170                        s_size = RNGSZ(out->mem_ranges.ranges[i]);
    132171                       
    133                         if ((address == s_address) && (size == s_size))
    134                                 return;
    135                 }
    136         }
    137        
    138         out->mem_ranges.ranges[count].address = address;
     172                        if ((absolute == s_address) && (size == s_size))
     173                                return;
     174                }
     175        }
     176       
     177        RNGABS(out->mem_ranges.ranges[count]) = absolute;
     178        RNGREL(out->mem_ranges.ranges[count]) = relative;
     179        RNGSZ(out->mem_ranges.ranges[count]) = size;
    139180        out->mem_ranges.ranges[count].endianness = endianness;
    140         out->mem_ranges.ranges[count].size = size;
    141181        out->mem_ranges.count++;
    142182}
     
    144184/** Parse list of hardware resources
    145185 *
    146  * @param      hw_resources Original structure resource
    147  * @param[out] out          Output parsed resources
    148  * @param      flags        Flags of the parsing.
    149  *                          HW_RES_KEEP_ZERO_AREA for keeping
    150  *                          zero-size areas, HW_RES_KEEP_DUPLICITIES
    151  *                          for keep duplicit areas
     186 * @param      win          PIO window.
     187 * @param      res          Original structure resource.
     188 * @param[out] out          Output parsed resources.
     189 * @param      flags        Flags of the parsing:
     190 *                          HW_RES_KEEP_ZERO_AREA for keeping zero-size areas,
     191 *                          HW_RES_KEEP_DUPLICITIES to keep duplicit areas.
    152192 *
    153193 * @return EOK if succeed, error code otherwise.
    154194 *
    155195 */
    156 int hw_res_list_parse(const hw_resource_list_t *hw_resources,
    157     hw_res_list_parsed_t *out, int flags)
    158 {
    159         if ((!hw_resources) || (!out))
     196int hw_res_list_parse(const pio_window_t *win,
     197    const hw_resource_list_t *res, hw_res_list_parsed_t *out, int flags)
     198{
     199        if (!res || !out)
    160200                return EINVAL;
    161201       
    162         size_t res_count = hw_resources->count;
     202        size_t res_count = res->count;
    163203        hw_res_list_parsed_clean(out);
    164204       
     
    174214       
    175215        for (size_t i = 0; i < res_count; ++i) {
    176                 const hw_resource_t *resource = &(hw_resources->resources[i]);
     216                const hw_resource_t *resource = &res->resources[i];
    177217               
    178218                switch (resource->type) {
     
    181221                        break;
    182222                case IO_RANGE:
    183                         hw_res_parse_add_io_range(out, resource, flags);
     223                        hw_res_parse_add_io_range(out, win, resource, flags);
    184224                        break;
    185225                case MEM_RANGE:
    186                         hw_res_parse_add_mem_range(out, resource, flags);
     226                        hw_res_parse_add_mem_range(out, win, resource, flags);
    187227                        break;
    188228                case DMA_CHANNEL_8:
     
    216256    hw_res_list_parsed_t *hw_res_parsed, int flags)
    217257{
     258        pio_window_t pio_window;
     259        int rc;
     260
    218261        if (!hw_res_parsed)
    219262                return EBADMEM;
     
    222265        hw_res_list_parsed_clean(hw_res_parsed);
    223266        memset(&hw_resources, 0, sizeof(hw_resource_list_t));
    224        
    225         int rc = hw_res_get_resource_list(sess, &hw_resources);
     267
     268        rc = pio_window_get(sess, &pio_window);
     269        if (rc != EOK)
     270                return rc;
     271       
     272        rc = hw_res_get_resource_list(sess, &hw_resources);
    226273        if (rc != EOK)
    227274                return rc;
    228        
    229         rc = hw_res_list_parse(&hw_resources, hw_res_parsed, flags);
     275
     276        rc = hw_res_list_parse(&pio_window, &hw_resources, hw_res_parsed,
     277            flags);
    230278        hw_res_clean_resource_list(&hw_resources);
    231279       
Note: See TracChangeset for help on using the changeset viewer.