Changeset a996ae31 in mainline


Ignore:
Timestamp:
2012-02-12T14:26:04Z (12 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
d57122c
Parents:
ec12ab8
Message:

Userspace IRQ pseudocode is expected to use physical addresses from now.
The kernel creates kernel mappings for those and adjusts the pseudocode
accordingly.

Files:
11 edited

Legend:

Unmodified
Added
Removed
  • abi/include/ddi/irq.h

    rec12ab8 ra996ae31  
    3535#ifndef ABI_DDI_IRQ_H_
    3636#define ABI_DDI_IRQ_H_
     37
     38typedef struct {
     39        uintptr_t base;
     40        size_t size;
     41} irq_pio_range_t;
    3742
    3843typedef enum {
     
    97102
    98103typedef struct {
     104        size_t rangecount;
     105        irq_pio_range_t *ranges;
    99106        size_t cmdcount;
    100107        irq_cmd_t *cmds;
  • kernel/generic/include/ipc/irq.h

    rec12ab8 ra996ae31  
    3636#define KERN_IPC_IRQ_H_
    3737
    38 /** Maximum length of IPC IRQ program */
     38/** Maximum number of IPC IRQ programmed I/O ranges. */
     39#define IRQ_MAX_RANGE_COUNT     8
     40
     41/** Maximum length of IPC IRQ program. */
    3942#define IRQ_MAX_PROG_SIZE  20
    4043
  • kernel/generic/src/ipc/irq.c

    rec12ab8 ra996ae31  
    7474#include <arch.h>
    7575#include <mm/slab.h>
     76#include <mm/page.h>
     77#include <mm/km.h>
    7678#include <errno.h>
    7779#include <ddi/irq.h>
     
    8183#include <console/console.h>
    8284#include <print.h>
     85#include <macros.h>
     86
     87static void ranges_unmap(irq_pio_range_t *ranges, size_t rangecount)
     88{
     89        size_t i;
     90
     91        for (i = 0; i < rangecount; i++) {
     92                if ((void *) ranges[i].base >= IO_SPACE_BOUNDARY)
     93                        km_unmap(ranges[i].base, ranges[i].size);
     94        }
     95}
     96
     97static int ranges_map_and_apply(irq_pio_range_t *ranges, size_t rangecount,
     98    irq_cmd_t *cmds, size_t cmdcount)
     99{
     100        uintptr_t *pbase;
     101        size_t i, j;
     102
     103        /* Copy the physical base addresses aside. */
     104        pbase = malloc(rangecount * sizeof(uintptr_t), 0);
     105        for (i = 0; i < rangecount; i++)
     106                pbase[i] = ranges[i].base;
     107
     108        /* Map the PIO ranges into the kernel virtual address space. */
     109        for (i = 0; i < rangecount; i++) {
     110                if ((void *) ranges[i].base < IO_SPACE_BOUNDARY)
     111                        continue;
     112                ranges[i].base = km_map(pbase[i], ranges[i].size,
     113                    PAGE_READ | PAGE_WRITE | PAGE_KERNEL | PAGE_NOT_CACHEABLE);
     114                if (!ranges[i].base) {
     115                        ranges_unmap(ranges, i);
     116                        free(pbase);
     117                        return ENOMEM;
     118                }
     119        }
     120
     121        /* Rewrite the pseudocode addresses from physical to kernel virtual. */
     122        for (i = 0; i < cmdcount; i++) {
     123                uintptr_t addr;
     124
     125                /* Process only commands that use an address. */
     126                switch (cmds[i].cmd) {
     127                case CMD_PIO_READ_8:
     128                case CMD_PIO_READ_16:
     129                case CMD_PIO_READ_32:
     130                case CMD_PIO_WRITE_8:
     131                case CMD_PIO_WRITE_16:
     132                case CMD_PIO_WRITE_32:
     133                case CMD_PIO_WRITE_A_8:
     134                case CMD_PIO_WRITE_A_16:
     135                case CMD_PIO_WRITE_A_32:
     136                        break;
     137                default:
     138                        /* Move onto the next command. */
     139                        continue;
     140                }
     141
     142                addr = (uintptr_t) cmds[i].addr;
     143               
     144                /* Process only memory mapped PIO addresses. */
     145                if ((void *) addr < IO_SPACE_BOUNDARY)
     146                        continue;
     147
     148                for (j = 0; j < rangecount; j++) {
     149
     150                        /* Find the matching range. */
     151                        if (!iswithin(pbase[j], ranges[j].size, addr, 1))
     152                                continue;
     153
     154                        /* Switch the command to a kernel virtual address. */
     155                        addr -= pbase[j];
     156                        addr += ranges[j].base;
     157
     158                        cmds[i].addr = (void *) addr;
     159                        break;
     160                }
     161        }
     162
     163        free(pbase);
     164        return EOK;
     165}
    83166
    84167/** Free the top-half pseudocode.
     
    90173{
    91174        if (code) {
     175                ranges_unmap(code->ranges, code->rangecount);
     176                free(code->ranges);
    92177                free(code->cmds);
    93178                free(code);
     
    104189static irq_code_t *code_from_uspace(irq_code_t *ucode)
    105190{
     191        irq_pio_range_t *ranges = NULL;
     192        irq_cmd_t *cmds = NULL;
     193
    106194        irq_code_t *code = malloc(sizeof(*code), 0);
    107195        int rc = copy_from_uspace(code, ucode, sizeof(*code));
    108         if (rc != 0) {
    109                 free(code);
    110                 return NULL;
    111         }
    112        
    113         if (code->cmdcount > IRQ_MAX_PROG_SIZE) {
    114                 free(code);
    115                 return NULL;
    116         }
    117        
    118         irq_cmd_t *ucmds = code->cmds;
    119         code->cmds = malloc(sizeof(code->cmds[0]) * code->cmdcount, 0);
    120         rc = copy_from_uspace(code->cmds, ucmds,
     196        if (rc != EOK)
     197                goto error;
     198       
     199        if ((code->rangecount > IRQ_MAX_RANGE_COUNT) ||
     200            (code->cmdcount > IRQ_MAX_PROG_SIZE))
     201                goto error;
     202       
     203        ranges = malloc(sizeof(code->ranges[0]) * code->rangecount, 0);
     204        rc = copy_from_uspace(ranges, code->ranges,
     205            sizeof(code->ranges[0]) * code->rangecount);
     206        if (rc != EOK)
     207                goto error;
     208
     209        cmds = malloc(sizeof(code->cmds[0]) * code->cmdcount, 0);
     210        rc = copy_from_uspace(cmds, code->cmds,
    121211            sizeof(code->cmds[0]) * code->cmdcount);
    122         if (rc != 0) {
    123                 free(code->cmds);
    124                 free(code);
    125                 return NULL;
    126         }
    127        
     212        if (rc != EOK)
     213                goto error;
     214
     215        rc = ranges_map_and_apply(ranges, code->rangecount, cmds,
     216            code->cmdcount);
     217        if (rc != EOK)
     218                goto error;
     219
     220        code->ranges = ranges;
     221        code->cmds = cmds;
     222
    128223        return code;
     224
     225error:
     226        if (cmds)
     227                free(cmds);
     228        if (ranges)
     229                free(ranges);
     230        free(code);
     231        return NULL;
    129232}
    130233
     
    366469        for (size_t i = 0; i < code->cmdcount; i++) {
    367470                uint32_t dstval;
    368                 void *va;
    369                 uint8_t val8;
    370                 uint16_t val16;
    371                 uint32_t val32;
    372471               
    373472                uintptr_t srcarg = code->cmds[i].srcarg;
  • kernel/generic/src/syscall/copy.c

    rec12ab8 ra996ae31  
    5656 * @param size Size of the data to be copied.
    5757 *
    58  * @return 0 on success or error code from @ref errno.h.
     58 * @return EOK on success or error code from @ref errno.h.
    5959 */
    6060int copy_from_uspace(void *dst, const void *uspace_src, size_t size)
     
    9494
    9595        interrupts_restore(ipl);
    96         return !rc ? EPERM : 0;
     96        return !rc ? EPERM : EOK;
    9797}
    9898
  • uspace/lib/drv/generic/driver.c

    rec12ab8 ra996ae31  
    8080
    8181static irq_code_t default_pseudocode = {
     82        0,
     83        NULL,
    8284        sizeof(default_cmds) / sizeof(irq_cmd_t),
    8385        default_cmds
  • uspace/srv/hid/input/port/gxemul.c

    rec12ab8 ra996ae31  
    6969
    7070static irq_code_t gxemul_kbd = {
     71        0,      // FIXME
     72        NULL,   // FIXME
    7173        sizeof(gxemul_cmds) / sizeof(irq_cmd_t),
    7274        gxemul_cmds
  • uspace/srv/hid/input/port/msim.c

    rec12ab8 ra996ae31  
    6969
    7070static irq_code_t msim_kbd = {
     71        0,      // FIXME
     72        NULL,   // FIXME
    7173        sizeof(msim_cmds) / sizeof(irq_cmd_t),
    7274        msim_cmds
  • uspace/srv/hid/input/port/ns16550.c

    rec12ab8 ra996ae31  
    9898
    9999irq_code_t ns16550_kbd = {
     100        0,
     101        NULL,
    100102        sizeof(ns16550_cmds) / sizeof(irq_cmd_t),
    101103        ns16550_cmds
  • uspace/srv/hid/input/port/pl050.c

    rec12ab8 ra996ae31  
    9191
    9292static irq_code_t pl050_kbd = {
     93        0,      // FIXME
     94        NULL,   // FIXME
    9395        sizeof(pl050_cmds) / sizeof(irq_cmd_t),
    9496        pl050_cmds
  • uspace/srv/hid/s3c24xx_ts/s3c24xx_ts.c

    rec12ab8 ra996ae31  
    6262
    6363static irq_code_t ts_irq_code = {
     64        0,
     65        NULL,
    6466        sizeof(ts_irq_cmds) / sizeof(irq_cmd_t),
    6567        ts_irq_cmds
  • uspace/srv/hw/char/s3c24xx_uart/s3c24xx_uart.c

    rec12ab8 ra996ae31  
    6060
    6161static irq_code_t uart_irq_code = {
     62        0,
     63        NULL,
    6264        sizeof(uart_irq_cmds) / sizeof(irq_cmd_t),
    6365        uart_irq_cmds
Note: See TracChangeset for help on using the changeset viewer.