Changeset cecb0789 in mainline for kernel/generic/src/ddi/irq.c


Ignore:
Timestamp:
2009-02-21T17:27:59Z (16 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
9688513
Parents:
0cb9fa0
Message:

This is the evil commit. In particular, it does:

  • introduces more powerful pseudo code for userspace IRQ top-half handlers
  • changes the internals of IRQ dispatching
  • simplifies the kernel's i8042 driver
  • adapts the uspace i8042 driver to make use of the new pseudocode
  • breaks all other architectures except ia32
  • breaks almost all existing drivers
  • breaks switching between uspace and kernel drivers
File:
1 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/src/ddi/irq.c

    r0cb9fa0 rcecb0789  
    7070#include <ddi/irq.h>
    7171#include <adt/hash_table.h>
     72#include <mm/slab.h>
    7273#include <arch/types.h>
    7374#include <synch/spinlock.h>
     75#include <memstr.h>
    7476#include <arch.h>
    7577
     
    7880
    7981/**
    80  * Spinlock protecting the hash table.
     82 * Spinlock protecting the kernel IRQ hash table.
    8183 * This lock must be taken only when interrupts are disabled.
    8284 */
    83 SPINLOCK_INITIALIZE(irq_hash_table_lock);
    84 static hash_table_t irq_hash_table;
     85static SPINLOCK_INITIALIZE(irq_kernel_hash_table_lock);
     86/** The kernel IRQ hash table. */
     87static hash_table_t irq_kernel_hash_table;
     88
     89/**
     90 * Spinlock protecting the uspace IRQ hash table.
     91 * This lock must be taken only when interrupts are disabled.
     92 */
     93SPINLOCK_INITIALIZE(irq_uspace_hash_table_lock);
     94/** The uspace IRQ hash table. */
     95hash_table_t irq_uspace_hash_table;
    8596
    8697/**
     
    112123};
    113124
     125/** Number of buckets in either of the hash tables. */
     126static count_t buckets;
     127
    114128/** Initialize IRQ subsystem.
    115129 *
     
    119133void irq_init(count_t inrs, count_t chains)
    120134{
     135        buckets = chains;
    121136        /*
    122137         * Be smart about the choice of the hash table operations.
     
    125140         * different keys), we can use optimized set of operations.
    126141         */
    127         if (inrs == chains)
    128                 hash_table_create(&irq_hash_table, chains, 2, &irq_lin_ops);
    129         else
    130                 hash_table_create(&irq_hash_table, chains, 2, &irq_ht_ops);
     142        if (inrs == chains) {
     143                hash_table_create(&irq_uspace_hash_table, chains, 2,
     144                    &irq_lin_ops);
     145                hash_table_create(&irq_kernel_hash_table, chains, 2,
     146                    &irq_lin_ops);
     147        } else {
     148                hash_table_create(&irq_uspace_hash_table, chains, 2,
     149                    &irq_ht_ops);
     150                hash_table_create(&irq_kernel_hash_table, chains, 2,
     151                    &irq_ht_ops);
     152        }
    131153}
    132154
     
    138160void irq_initialize(irq_t *irq)
    139161{
     162        memsetb(irq, 0, sizeof(irq_t));
    140163        link_initialize(&irq->link);
    141164        spinlock_initialize(&irq->lock, "irq.lock");
    142         irq->preack = false;
     165        link_initialize(&irq->notif_cfg.link);
    143166        irq->inr = -1;
    144167        irq->devno = -1;
    145         irq->trigger = (irq_trigger_t) 0;
    146         irq->claim = NULL;
    147         irq->handler = NULL;
    148         irq->instance = NULL;
    149         irq->cir = NULL;
    150         irq->cir_arg = NULL;
    151         irq->notif_cfg.notify = false;
    152         irq->notif_cfg.answerbox = NULL;
    153         irq->notif_cfg.code = NULL;
    154         irq->notif_cfg.method = 0;
    155         irq->notif_cfg.counter = 0;
    156         link_initialize(&irq->notif_cfg.link);
    157168}
    158169
     
    161172 * The irq structure must be filled with information
    162173 * about the interrupt source and with the claim()
    163  * function pointer and irq_handler() function pointer.
    164  *
    165  * @param irq IRQ structure belonging to a device.
     174 * function pointer and handler() function pointer.
     175 *
     176 * @param irq           IRQ structure belonging to a device.
     177 * @return              True on success, false on failure.
    166178 */
    167179void irq_register(irq_t *irq)
    168180{
     181        spinlock_t *lock = &irq_kernel_hash_table_lock;
     182        hash_table_t *table = &irq_kernel_hash_table;
    169183        ipl_t ipl;
    170184        unative_t key[] = {
     
    174188       
    175189        ipl = interrupts_disable();
    176         spinlock_lock(&irq_hash_table_lock);
    177         hash_table_insert(&irq_hash_table, key, &irq->link);
    178         spinlock_unlock(&irq_hash_table_lock);
     190        spinlock_lock(lock);
     191        spinlock_lock(&irq->lock);
     192        hash_table_insert(table, key, &irq->link);
     193        spinlock_unlock(&irq->lock);   
     194        spinlock_unlock(lock);
    179195        interrupts_restore(ipl);
    180196}
     
    202218        };
    203219       
    204         spinlock_lock(&irq_hash_table_lock);
    205 
    206         lnk = hash_table_find(&irq_hash_table, key);
     220        /*
     221         * Try uspace handlers first.
     222         */
     223        spinlock_lock(&irq_uspace_hash_table_lock);
     224        lnk = hash_table_find(&irq_uspace_hash_table, key);
    207225        if (lnk) {
    208226                irq_t *irq;
    209227               
    210228                irq = hash_table_get_instance(lnk, irq_t, link);
    211 
    212                 spinlock_unlock(&irq_hash_table_lock);
     229                spinlock_unlock(&irq_uspace_hash_table_lock);
    213230                return irq;
    214231        }
    215        
    216         spinlock_unlock(&irq_hash_table_lock);
    217 
    218         return NULL;   
    219 }
    220 
    221 /** Find the IRQ structure corresponding to inr and devno.
    222  *
    223  * This functions attempts to lookup the IRQ structure
    224  * corresponding to its arguments. On success, this
    225  * function returns with interrups disabled, holding
    226  * the lock of the respective IRQ structure.
    227  *
    228  * This function assumes interrupts are already disabled.
    229  *
    230  * @param inr INR being looked up.
    231  * @param devno Devno being looked up.
    232  *
    233  * @return Locked IRQ structure on success or NULL on failure.
    234  */
    235 irq_t *irq_find_and_lock(inr_t inr, devno_t devno)
    236 {
    237         link_t *lnk;
    238         unative_t keys[] = {
    239                 (unative_t) inr,
    240                 (unative_t) devno
    241         };
    242        
    243         spinlock_lock(&irq_hash_table_lock);
    244 
    245         lnk = hash_table_find(&irq_hash_table, keys);
     232        spinlock_unlock(&irq_uspace_hash_table_lock);
     233
     234        /*
     235         * Fallback to kernel handlers.
     236         */
     237        spinlock_lock(&irq_kernel_hash_table_lock);
     238        lnk = hash_table_find(&irq_kernel_hash_table, key);
    246239        if (lnk) {
    247240                irq_t *irq;
    248241               
    249242                irq = hash_table_get_instance(lnk, irq_t, link);
    250 
    251                 spinlock_unlock(&irq_hash_table_lock);
     243                spinlock_unlock(&irq_kernel_hash_table_lock);
    252244                return irq;
    253245        }
    254        
    255         spinlock_unlock(&irq_hash_table_lock);
     246        spinlock_unlock(&irq_kernel_hash_table_lock);
    256247
    257248        return NULL;   
     
    274265{
    275266        inr_t inr = (inr_t) key[KEY_INR];
    276         return inr % irq_hash_table.entries;
     267        return inr % buckets;
    277268}
    278269
     
    309300                /* Invoked by irq_dispatch_and_lock(). */
    310301                rv = ((irq->inr == inr) &&
    311                     (irq->claim(irq->instance) == IRQ_ACCEPT));
     302                    (irq->claim(irq) == IRQ_ACCEPT));
    312303        } else {
    313304                /* Invoked by irq_find_and_lock(). */
     
    368359        if (devno == -1) {
    369360                /* Invoked by irq_dispatch_and_lock() */
    370                 rv = (irq->claim(irq->instance) == IRQ_ACCEPT);
     361                rv = (irq->claim(irq) == IRQ_ACCEPT);
    371362        } else {
    372363                /* Invoked by irq_find_and_lock() */
Note: See TracChangeset for help on using the changeset viewer.