Changeset cecb0789 in mainline
- 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
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/arch/ia32/src/ia32.c
r0cb9fa0 rcecb0789 167 167 #endif 168 168 169 i8042_grab();170 169 } 171 170 … … 175 174 void arch_release_console(void) 176 175 { 177 i8042_release();178 176 } 179 177 -
kernel/genarch/src/kbd/i8042.c
r0cb9fa0 rcecb0789 95 95 static irq_t i8042_mouse_irq; 96 96 97 void i8042_grab(void)98 {99 ipl_t ipl = interrupts_disable();100 101 spinlock_lock(&i8042_kbd_irq.lock);102 i8042_kbd_irq.notif_cfg.notify = false;103 spinlock_unlock(&i8042_kbd_irq.lock);104 105 spinlock_lock(&i8042_mouse_irq.lock);106 i8042_mouse_irq.notif_cfg.notify = false;107 spinlock_unlock(&i8042_mouse_irq.lock);108 109 interrupts_restore(ipl);110 }111 112 void i8042_release(void)113 {114 ipl_t ipl = interrupts_disable();115 116 spinlock_lock(&i8042_kbd_irq.lock);117 if (i8042_kbd_irq.notif_cfg.answerbox)118 i8042_kbd_irq.notif_cfg.notify = true;119 spinlock_unlock(&i8042_kbd_irq.lock);120 121 spinlock_lock(&i8042_mouse_irq.lock);122 if (i8042_mouse_irq.notif_cfg.answerbox)123 i8042_mouse_irq.notif_cfg.notify = true;124 spinlock_unlock(&i8042_mouse_irq.lock);125 126 interrupts_restore(ipl);127 }128 129 97 static irq_ownership_t i8042_claim(irq_t *irq) 130 98 { … … 139 107 static void i8042_irq_handler(irq_t *irq) 140 108 { 141 if (irq->notif_cfg.notify && irq->notif_cfg.answerbox) {142 /*143 * This will hopefully go to the IRQ dispatcher code soon.144 */145 ipc_irq_send_notif(irq);146 return;147 }148 149 109 i8042_instance_t *instance = irq->instance; 150 110 i8042_t *dev = instance->i8042; … … 214 174 sysinfo_set_item_val("mouse.devno", NULL, mouse_devno); 215 175 sysinfo_set_item_val("mouse.inr", NULL, mouse_inr); 216 217 i8042_grab();218 176 } 219 177 -
kernel/generic/include/ddi/irq.h
r0cb9fa0 rcecb0789 37 37 38 38 typedef enum { 39 CMD_ MEM_READ_1 = 0,40 CMD_ MEM_READ_2,41 CMD_ MEM_READ_4,42 CMD_ MEM_READ_8,43 CMD_ MEM_WRITE_1,44 CMD_ MEM_WRITE_2,45 CMD_ MEM_WRITE_4,46 CMD_ MEM_WRITE_8,47 CMD_ PORT_READ_1,48 CMD_ PORT_WRITE_1,39 CMD_PIO_READ_8 = 1, 40 CMD_PIO_READ_16, 41 CMD_PIO_READ_32, 42 CMD_PIO_WRITE_8, 43 CMD_PIO_WRITE_16, 44 CMD_PIO_WRITE_32, 45 CMD_BTEST, 46 CMD_PREDICATE, 47 CMD_ACCEPT, 48 CMD_DECLINE, 49 49 CMD_LAST 50 50 } irq_cmd_type; … … 53 53 irq_cmd_type cmd; 54 54 void *addr; 55 unsigned long long value; 56 int dstarg; 55 unsigned long long value; 56 unsigned int srcarg; 57 unsigned int dstarg; 57 58 } irq_cmd_t; 58 59 … … 66 67 #include <arch/types.h> 67 68 #include <adt/list.h> 69 #include <adt/hash_table.h> 68 70 #include <synch/spinlock.h> 69 71 #include <proc/task.h> 72 #include <ipc/ipc.h> 70 73 71 74 typedef enum { … … 97 100 /** Method to be used for the notification. */ 98 101 unative_t method; 102 /** Arguments that will be sent if the IRQ is claimed. */ 103 unative_t scratch[IPC_CALL_LEN]; 99 104 /** Top-half pseudocode. */ 100 105 irq_code_t *code; … … 155 160 } irq_t; 156 161 162 SPINLOCK_EXTERN(irq_uspace_hash_table_lock); 163 extern hash_table_t irq_uspace_hash_table; 164 157 165 extern void irq_init(count_t, count_t); 158 166 extern void irq_initialize(irq_t *); 159 167 extern void irq_register(irq_t *); 160 168 extern irq_t *irq_dispatch_and_lock(inr_t); 161 extern irq_t *irq_find_and_lock(inr_t, devno_t);162 169 163 170 #endif -
kernel/generic/include/ipc/irq.h
r0cb9fa0 rcecb0789 37 37 38 38 /** Maximum length of IPC IRQ program */ 39 #define IRQ_MAX_PROG_SIZE 1039 #define IRQ_MAX_PROG_SIZE 20 40 40 41 41 #include <ipc/ipc.h> … … 44 44 #include <adt/list.h> 45 45 46 extern int ipc_irq_register(answerbox_t *box, inr_t inr, devno_t devno, 47 unative_t method, irq_code_t *ucode); 48 extern void ipc_irq_send_notif(irq_t *irq); 49 extern void ipc_irq_unregister(answerbox_t *box, inr_t inr, devno_t devno); 50 extern void ipc_irq_cleanup(answerbox_t *box); 46 extern int ipc_irq_register(answerbox_t *, inr_t, devno_t, unative_t, 47 irq_code_t *); 48 49 extern irq_ownership_t ipc_irq_top_half_claim(irq_t *); 50 extern void ipc_irq_top_half_handler(irq_t *); 51 52 extern int ipc_irq_unregister(answerbox_t *, inr_t, devno_t); 53 extern void ipc_irq_cleanup(answerbox_t *); 51 54 52 55 /* … … 67 70 ipc_irq_send_msg((irq), (a1), (a2), (a3), (a4), (a5)) 68 71 69 extern void ipc_irq_send_msg(irq_t * irq, unative_t a1, unative_t a2,70 unative_t a3, unative_t a4, unative_t a5);72 extern void ipc_irq_send_msg(irq_t *, unative_t, unative_t, unative_t, unative_t, 73 unative_t); 71 74 72 75 #endif -
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() */ -
kernel/generic/src/ipc/irq.c
r0cb9fa0 rcecb0789 45 45 * - ARG2: payload modified by a 'top-half' handler 46 46 * - ARG3: payload modified by a 'top-half' handler 47 * - ARG4: payload modified by a 'top-half' handler 48 * - ARG5: payload modified by a 'top-half' handler 47 49 * - in_phone_hash: interrupt counter (may be needed to assure correct order 48 50 * in multithreaded drivers) 51 * 52 * Note on synchronization for ipc_irq_register(), ipc_irq_unregister(), 53 * ipc_irq_cleanup() and IRQ handlers: 54 * 55 * By always taking all of the uspace IRQ hash table lock, IRQ structure lock 56 * and answerbox lock, we can rule out race conditions between the 57 * registration functions and also the cleanup function. Thus the observer can 58 * either see the IRQ structure present in both the hash table and the 59 * answerbox list or absent in both. Views in which the IRQ structure would be 60 * linked in the hash table but not in the answerbox list, or vice versa, are 61 * not possible. 62 * 63 * By always taking the hash table lock and the IRQ structure lock, we can 64 * rule out a scenario in which we would free up an IRQ structure, which is 65 * still referenced by, for example, an IRQ handler. The locking scheme forces 66 * us to lock the IRQ structure only after any progressing IRQs on that 67 * structure are finished. Because we hold the hash table lock, we prevent new 68 * IRQs from taking new references to the IRQ structure. 49 69 */ 50 70 … … 59 79 #include <print.h> 60 80 61 /** Execute code associated with IRQ notification. 62 * 63 * @param call Notification call. 64 * @param code Top-half pseudocode. 65 */ 66 static void code_execute(call_t *call, irq_code_t *code) 67 { 68 unsigned int i; 69 unative_t dstval = 0; 70 71 if (!code) 72 return; 73 74 for (i = 0; i < code->cmdcount; i++) { 75 switch (code->cmds[i].cmd) { 76 case CMD_MEM_READ_1: 77 dstval = *((uint8_t *) code->cmds[i].addr); 78 break; 79 case CMD_MEM_READ_2: 80 dstval = *((uint16_t *) code->cmds[i].addr); 81 break; 82 case CMD_MEM_READ_4: 83 dstval = *((uint32_t *) code->cmds[i].addr); 84 break; 85 case CMD_MEM_READ_8: 86 dstval = *((uint64_t *) code->cmds[i].addr); 87 break; 88 case CMD_MEM_WRITE_1: 89 *((uint8_t *) code->cmds[i].addr) = code->cmds[i].value; 90 break; 91 case CMD_MEM_WRITE_2: 92 *((uint16_t *) code->cmds[i].addr) = 93 code->cmds[i].value; 94 break; 95 case CMD_MEM_WRITE_4: 96 *((uint32_t *) code->cmds[i].addr) = 97 code->cmds[i].value; 98 break; 99 case CMD_MEM_WRITE_8: 100 *((uint64_t *) code->cmds[i].addr) = 101 code->cmds[i].value; 102 break; 103 case CMD_PORT_READ_1: 104 dstval = pio_read_8((ioport8_t *) code->cmds[i].addr); 105 break; 106 case CMD_PORT_WRITE_1: 107 pio_write_8((ioport8_t *) code->cmds[i].addr, code->cmds[i].value); 108 break; 109 default: 110 break; 111 } 112 if (code->cmds[i].dstarg && code->cmds[i].dstarg < 113 IPC_CALL_LEN) { 114 call->data.args[code->cmds[i].dstarg] = dstval; 115 } 116 } 117 } 118 119 /** Free top-half pseudocode. 81 /** Free the top-half pseudocode. 120 82 * 121 83 * @param code Pointer to the top-half pseudocode. … … 129 91 } 130 92 131 /** Copy t op-half pseudocode from userspace into the kernel.93 /** Copy the top-half pseudocode from userspace into the kernel. 132 94 * 133 95 * @param ucode Userspace address of the top-half pseudocode. … … 165 127 } 166 128 167 /** Unregister task from IRQ notification.168 *169 * @param box Answerbox associated with the notification.170 * @param inr IRQ number.171 * @param devno Device number.172 */173 void ipc_irq_unregister(answerbox_t *box, inr_t inr, devno_t devno)174 {175 ipl_t ipl;176 irq_t *irq;177 178 ipl = interrupts_disable();179 irq = irq_find_and_lock(inr, devno);180 if (irq) {181 if (irq->notif_cfg.answerbox == box) {182 code_free(irq->notif_cfg.code);183 irq->notif_cfg.notify = false;184 irq->notif_cfg.answerbox = NULL;185 irq->notif_cfg.code = NULL;186 irq->notif_cfg.method = 0;187 irq->notif_cfg.counter = 0;188 189 spinlock_lock(&box->irq_lock);190 list_remove(&irq->notif_cfg.link);191 spinlock_unlock(&box->irq_lock);192 193 spinlock_unlock(&irq->lock);194 }195 }196 interrupts_restore(ipl);197 }198 199 129 /** Register an answerbox as a receiving end for IRQ notifications. 200 130 * … … 213 143 irq_code_t *code; 214 144 irq_t *irq; 145 unative_t key[] = { 146 (unative_t) inr, 147 (unative_t) devno 148 }; 215 149 216 150 if (ucode) { … … 222 156 } 223 157 224 ipl = interrupts_disable(); 225 irq = irq_find_and_lock(inr, devno); 226 if (!irq) { 227 interrupts_restore(ipl); 228 code_free(code); 229 return ENOENT; 230 } 231 232 if (irq->notif_cfg.answerbox) { 233 spinlock_unlock(&irq->lock); 234 interrupts_restore(ipl); 235 code_free(code); 236 return EEXISTS; 237 } 238 158 /* 159 * Allocate and populate the IRQ structure. 160 */ 161 irq = malloc(sizeof(irq_t), 0); 162 irq_initialize(irq); 163 irq->devno = devno; 164 irq->inr = inr; 165 irq->claim = ipc_irq_top_half_claim; 166 irq->handler = ipc_irq_top_half_handler; 239 167 irq->notif_cfg.notify = true; 240 168 irq->notif_cfg.answerbox = box; … … 243 171 irq->notif_cfg.counter = 0; 244 172 173 /* 174 * Enlist the IRQ structure in the uspace IRQ hash table and the 175 * answerbox's list. 176 */ 177 ipl = interrupts_disable(); 178 spinlock_lock(&irq_uspace_hash_table_lock); 179 spinlock_lock(&irq->lock); 245 180 spinlock_lock(&box->irq_lock); 181 if (hash_table_find(&irq_uspace_hash_table, key)) { 182 code_free(code); 183 spinlock_unlock(&box->irq_lock); 184 spinlock_unlock(&irq->lock); 185 spinlock_unlock(&irq_uspace_hash_table_lock); 186 free(irq); 187 interrupts_restore(ipl); 188 return EEXISTS; 189 } 190 hash_table_insert(&irq_uspace_hash_table, key, &irq->link); 246 191 list_append(&irq->notif_cfg.link, &box->irq_head); 247 192 spinlock_unlock(&box->irq_lock); 248 249 193 spinlock_unlock(&irq->lock); 194 spinlock_unlock(&irq_uspace_hash_table_lock); 195 250 196 interrupts_restore(ipl); 251 252 return 0; 197 return EOK; 198 } 199 200 /** Unregister task from IRQ notification. 201 * 202 * @param box Answerbox associated with the notification. 203 * @param inr IRQ number. 204 * @param devno Device number. 205 */ 206 int ipc_irq_unregister(answerbox_t *box, inr_t inr, devno_t devno) 207 { 208 ipl_t ipl; 209 unative_t key[] = { 210 (unative_t) inr, 211 (unative_t) devno 212 }; 213 link_t *lnk; 214 irq_t *irq; 215 216 ipl = interrupts_disable(); 217 spinlock_lock(&irq_uspace_hash_table_lock); 218 lnk = hash_table_find(&irq_uspace_hash_table, key); 219 if (!lnk) { 220 spinlock_unlock(&irq_uspace_hash_table_lock); 221 interrupts_restore(ipl); 222 return ENOENT; 223 } 224 irq = hash_table_get_instance(lnk, irq_t, link); 225 spinlock_lock(&irq->lock); 226 spinlock_lock(&box->irq_lock); 227 228 ASSERT(irq->notif_cfg.answerbox == box); 229 230 /* Free up the pseudo code and associated structures. */ 231 code_free(irq->notif_cfg.code); 232 233 /* Remove the IRQ from the answerbox's list. */ 234 list_remove(&irq->notif_cfg.link); 235 236 /* Remove the IRQ from the uspace IRQ hash table. */ 237 hash_table_remove(&irq_uspace_hash_table, key, 2); 238 239 spinlock_unlock(&irq_uspace_hash_table_lock); 240 spinlock_unlock(&irq->lock); 241 spinlock_unlock(&box->irq_lock); 242 243 /* Free up the IRQ structure. */ 244 free(irq); 245 246 interrupts_restore(ipl); 247 return EOK; 248 } 249 250 251 /** Disconnect all IRQ notifications from an answerbox. 252 * 253 * This function is effective because the answerbox contains 254 * list of all irq_t structures that are registered to 255 * send notifications to it. 256 * 257 * @param box Answerbox for which we want to carry out the cleanup. 258 */ 259 void ipc_irq_cleanup(answerbox_t *box) 260 { 261 ipl_t ipl; 262 263 loop: 264 ipl = interrupts_disable(); 265 spinlock_lock(&irq_uspace_hash_table_lock); 266 spinlock_lock(&box->irq_lock); 267 268 while (box->irq_head.next != &box->irq_head) { 269 link_t *cur = box->irq_head.next; 270 irq_t *irq; 271 DEADLOCK_PROBE_INIT(p_irqlock); 272 unative_t key[2]; 273 274 irq = list_get_instance(cur, irq_t, notif_cfg.link); 275 if (!spinlock_trylock(&irq->lock)) { 276 /* 277 * Avoid deadlock by trying again. 278 */ 279 spinlock_unlock(&box->irq_lock); 280 spinlock_unlock(&irq_uspace_hash_table_lock); 281 interrupts_restore(ipl); 282 DEADLOCK_PROBE(p_irqlock, DEADLOCK_THRESHOLD); 283 goto loop; 284 } 285 key[0] = irq->inr; 286 key[1] = irq->devno; 287 288 289 ASSERT(irq->notif_cfg.answerbox == box); 290 291 /* Unlist from the answerbox. */ 292 list_remove(&irq->notif_cfg.link); 293 294 /* Remove from the hash table. */ 295 hash_table_remove(&irq_uspace_hash_table, key, 2); 296 297 /* Free up the pseudo code and associated structures. */ 298 code_free(irq->notif_cfg.code); 299 300 spinlock_unlock(&irq->lock); 301 free(irq); 302 } 303 304 spinlock_unlock(&box->irq_lock); 305 spinlock_unlock(&irq_uspace_hash_table_lock); 306 interrupts_restore(ipl); 253 307 } 254 308 … … 267 321 268 322 waitq_wakeup(&irq->notif_cfg.answerbox->wq, WAKEUP_FIRST); 323 } 324 325 /** Apply the top-half pseudo code to find out whether to accept the IRQ or not. 326 * 327 * @param irq IRQ structure. 328 * 329 * @return IRQ_ACCEPT if the interrupt is accepted by the 330 * pseudocode. IRQ_DECLINE otherwise. 331 */ 332 irq_ownership_t ipc_irq_top_half_claim(irq_t *irq) 333 { 334 unsigned int i; 335 unative_t dstval; 336 irq_code_t *code = irq->notif_cfg.code; 337 unative_t *scratch = irq->notif_cfg.scratch; 338 339 340 if (!irq->notif_cfg.notify) 341 return IRQ_DECLINE; 342 343 if (!code) 344 return IRQ_DECLINE; 345 346 for (i = 0; i < code->cmdcount; i++) { 347 unsigned int srcarg = code->cmds[i].srcarg; 348 unsigned int dstarg = code->cmds[i].dstarg; 349 350 if (srcarg >= IPC_CALL_LEN) 351 break; 352 if (dstarg >= IPC_CALL_LEN) 353 break; 354 355 switch (code->cmds[i].cmd) { 356 case CMD_PIO_READ_8: 357 dstval = pio_read_8((ioport8_t *) code->cmds[i].addr); 358 if (dstarg) 359 scratch[dstarg] = dstval; 360 break; 361 case CMD_PIO_READ_16: 362 dstval = pio_read_16((ioport16_t *) code->cmds[i].addr); 363 if (dstarg) 364 scratch[dstarg] = dstval; 365 break; 366 case CMD_PIO_READ_32: 367 dstval = pio_read_32((ioport32_t *) code->cmds[i].addr); 368 if (dstarg) 369 scratch[dstarg] = dstval; 370 break; 371 case CMD_PIO_WRITE_8: 372 pio_write_8((ioport8_t *) code->cmds[i].addr, 373 (uint8_t) code->cmds[i].value); 374 break; 375 case CMD_PIO_WRITE_16: 376 pio_write_16((ioport16_t *) code->cmds[i].addr, 377 (uint16_t) code->cmds[i].value); 378 break; 379 case CMD_PIO_WRITE_32: 380 pio_write_32((ioport32_t *) code->cmds[i].addr, 381 (uint32_t) code->cmds[i].value); 382 break; 383 case CMD_BTEST: 384 if (srcarg && dstarg) { 385 dstval = scratch[srcarg] & code->cmds[i].value; 386 scratch[dstarg] = dstval; 387 } 388 break; 389 case CMD_PREDICATE: 390 if (srcarg && !scratch[srcarg]) { 391 i += code->cmds[i].value; 392 continue; 393 } 394 break; 395 case CMD_ACCEPT: 396 return IRQ_ACCEPT; 397 break; 398 case CMD_DECLINE: 399 default: 400 return IRQ_DECLINE; 401 } 402 } 403 404 return IRQ_DECLINE; 405 } 406 407 408 /* IRQ top-half handler. 409 * 410 * We expect interrupts to be disabled and the irq->lock already held. 411 * 412 * @param irq IRQ structure. 413 */ 414 void ipc_irq_top_half_handler(irq_t *irq) 415 { 416 ASSERT(irq); 417 418 if (irq->notif_cfg.answerbox) { 419 call_t *call; 420 421 call = ipc_call_alloc(FRAME_ATOMIC); 422 if (!call) 423 return; 424 425 call->flags |= IPC_CALL_NOTIF; 426 /* Put a counter to the message */ 427 call->priv = ++irq->notif_cfg.counter; 428 429 /* Set up args */ 430 IPC_SET_METHOD(call->data, irq->notif_cfg.method); 431 IPC_SET_ARG1(call->data, irq->notif_cfg.scratch[1]); 432 IPC_SET_ARG2(call->data, irq->notif_cfg.scratch[2]); 433 IPC_SET_ARG3(call->data, irq->notif_cfg.scratch[3]); 434 IPC_SET_ARG4(call->data, irq->notif_cfg.scratch[4]); 435 IPC_SET_ARG5(call->data, irq->notif_cfg.scratch[5]); 436 437 send_call(irq, call); 438 } 269 439 } 270 440 … … 292 462 } 293 463 call->flags |= IPC_CALL_NOTIF; 464 /* Put a counter to the message */ 465 call->priv = ++irq->notif_cfg.counter; 466 294 467 IPC_SET_METHOD(call->data, irq->notif_cfg.method); 295 468 IPC_SET_ARG1(call->data, a1); … … 298 471 IPC_SET_ARG4(call->data, a4); 299 472 IPC_SET_ARG5(call->data, a5); 300 /* Put a counter to the message */301 call->priv = ++irq->notif_cfg.counter;302 473 303 474 send_call(irq, call); … … 306 477 } 307 478 308 /** Notify a task that an IRQ had occurred.309 *310 * We expect interrupts to be disabled and the irq->lock already held.311 *312 * @param irq IRQ structure.313 */314 void ipc_irq_send_notif(irq_t *irq)315 {316 call_t *call;317 318 ASSERT(irq);319 320 if (irq->notif_cfg.answerbox) {321 call = ipc_call_alloc(FRAME_ATOMIC);322 if (!call) {323 return;324 }325 call->flags |= IPC_CALL_NOTIF;326 /* Put a counter to the message */327 call->priv = ++irq->notif_cfg.counter;328 /* Set up args */329 IPC_SET_METHOD(call->data, irq->notif_cfg.method);330 331 /* Execute code to handle irq */332 code_execute(call, irq->notif_cfg.code);333 334 send_call(irq, call);335 }336 }337 338 /** Disconnect all IRQ notifications from an answerbox.339 *340 * This function is effective because the answerbox contains341 * list of all irq_t structures that are registered to342 * send notifications to it.343 *344 * @param box Answerbox for which we want to carry out the cleanup.345 */346 void ipc_irq_cleanup(answerbox_t *box)347 {348 ipl_t ipl;349 350 loop:351 ipl = interrupts_disable();352 spinlock_lock(&box->irq_lock);353 354 while (box->irq_head.next != &box->irq_head) {355 link_t *cur = box->irq_head.next;356 irq_t *irq;357 DEADLOCK_PROBE_INIT(p_irqlock);358 359 irq = list_get_instance(cur, irq_t, notif_cfg.link);360 if (!spinlock_trylock(&irq->lock)) {361 /*362 * Avoid deadlock by trying again.363 */364 spinlock_unlock(&box->irq_lock);365 interrupts_restore(ipl);366 DEADLOCK_PROBE(p_irqlock, DEADLOCK_THRESHOLD);367 goto loop;368 }369 370 ASSERT(irq->notif_cfg.answerbox == box);371 372 list_remove(&irq->notif_cfg.link);373 374 /*375 * Don't forget to free any top-half pseudocode.376 */377 code_free(irq->notif_cfg.code);378 379 irq->notif_cfg.notify = false;380 irq->notif_cfg.answerbox = NULL;381 irq->notif_cfg.code = NULL;382 irq->notif_cfg.method = 0;383 irq->notif_cfg.counter = 0;384 385 spinlock_unlock(&irq->lock);386 }387 388 spinlock_unlock(&box->irq_lock);389 interrupts_restore(ipl);390 }391 392 479 /** @} 393 480 */ -
uspace/srv/kbd/port/i8042.c
r0cb9fa0 rcecb0789 64 64 #define MOUSE_ACK 0xfa 65 65 66 static irq_cmd_t i8042_cmds[2] = { 67 { CMD_PORT_READ_1, (void *) 0x64, 0, 1 }, 68 { CMD_PORT_READ_1, (void *) 0x60, 0, 2 } 66 static irq_cmd_t i8042_cmds[] = { 67 { 68 .cmd = CMD_PIO_READ_8, 69 .addr = (void *) 0x64, 70 .dstarg = 1 71 }, 72 { 73 .cmd = CMD_BTEST, 74 .value = i8042_OUTPUT_FULL, 75 .srcarg = 1, 76 .dstarg = 3 77 }, 78 { 79 .cmd = CMD_PREDICATE, 80 .value = 2, 81 .srcarg = 3 82 }, 83 { 84 .cmd = CMD_PIO_READ_8, 85 .addr = (void *) 0x60, 86 .dstarg = 2 87 }, 88 { 89 .cmd = CMD_ACCEPT 90 } 69 91 }; 70 92 71 93 static irq_code_t i8042_kbd = { 72 2,94 sizeof(i8042_cmds) / sizeof(irq_cmd_t), 73 95 i8042_cmds 74 96 };
Note:
See TracChangeset
for help on using the changeset viewer.