Changeset cecb0789 in mainline for kernel/generic/src/ddi/irq.c
- Timestamp:
- 2009-02-21T17:27:59Z (16 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 9688513
- Parents:
- 0cb9fa0
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/src/ddi/irq.c
r0cb9fa0 rcecb0789 70 70 #include <ddi/irq.h> 71 71 #include <adt/hash_table.h> 72 #include <mm/slab.h> 72 73 #include <arch/types.h> 73 74 #include <synch/spinlock.h> 75 #include <memstr.h> 74 76 #include <arch.h> 75 77 … … 78 80 79 81 /** 80 * Spinlock protecting the hash table.82 * Spinlock protecting the kernel IRQ hash table. 81 83 * This lock must be taken only when interrupts are disabled. 82 84 */ 83 SPINLOCK_INITIALIZE(irq_hash_table_lock); 84 static hash_table_t irq_hash_table; 85 static SPINLOCK_INITIALIZE(irq_kernel_hash_table_lock); 86 /** The kernel IRQ hash table. */ 87 static 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 */ 93 SPINLOCK_INITIALIZE(irq_uspace_hash_table_lock); 94 /** The uspace IRQ hash table. */ 95 hash_table_t irq_uspace_hash_table; 85 96 86 97 /** … … 112 123 }; 113 124 125 /** Number of buckets in either of the hash tables. */ 126 static count_t buckets; 127 114 128 /** Initialize IRQ subsystem. 115 129 * … … 119 133 void irq_init(count_t inrs, count_t chains) 120 134 { 135 buckets = chains; 121 136 /* 122 137 * Be smart about the choice of the hash table operations. … … 125 140 * different keys), we can use optimized set of operations. 126 141 */ 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 } 131 153 } 132 154 … … 138 160 void irq_initialize(irq_t *irq) 139 161 { 162 memsetb(irq, 0, sizeof(irq_t)); 140 163 link_initialize(&irq->link); 141 164 spinlock_initialize(&irq->lock, "irq.lock"); 142 irq->preack = false;165 link_initialize(&irq->notif_cfg.link); 143 166 irq->inr = -1; 144 167 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);157 168 } 158 169 … … 161 172 * The irq structure must be filled with information 162 173 * 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. 166 178 */ 167 179 void irq_register(irq_t *irq) 168 180 { 181 spinlock_t *lock = &irq_kernel_hash_table_lock; 182 hash_table_t *table = &irq_kernel_hash_table; 169 183 ipl_t ipl; 170 184 unative_t key[] = { … … 174 188 175 189 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); 179 195 interrupts_restore(ipl); 180 196 } … … 202 218 }; 203 219 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); 207 225 if (lnk) { 208 226 irq_t *irq; 209 227 210 228 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); 213 230 return irq; 214 231 } 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); 246 239 if (lnk) { 247 240 irq_t *irq; 248 241 249 242 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); 252 244 return irq; 253 245 } 254 255 spinlock_unlock(&irq_hash_table_lock); 246 spinlock_unlock(&irq_kernel_hash_table_lock); 256 247 257 248 return NULL; … … 274 265 { 275 266 inr_t inr = (inr_t) key[KEY_INR]; 276 return inr % irq_hash_table.entries;267 return inr % buckets; 277 268 } 278 269 … … 309 300 /* Invoked by irq_dispatch_and_lock(). */ 310 301 rv = ((irq->inr == inr) && 311 (irq->claim(irq ->instance) == IRQ_ACCEPT));302 (irq->claim(irq) == IRQ_ACCEPT)); 312 303 } else { 313 304 /* Invoked by irq_find_and_lock(). */ … … 368 359 if (devno == -1) { 369 360 /* Invoked by irq_dispatch_and_lock() */ 370 rv = (irq->claim(irq ->instance) == IRQ_ACCEPT);361 rv = (irq->claim(irq) == IRQ_ACCEPT); 371 362 } else { 372 363 /* Invoked by irq_find_and_lock() */
Note:
See TracChangeset
for help on using the changeset viewer.