00001
00009 #include <l4/util/util.h>
00010 #include <l4/sys/syscalls.h>
00011 #include <l4/util/irq.h>
00012 #include <l4/omega0/client.h>
00013 #include <l4/rmgr/librmgr.h>
00014 #include <l4/sys/ipc.h>
00015
00016 static void irq_mask(int irq);
00017 static void irq_unmask(int irq);
00018 static void irq_ack(int irq);
00019
00020 static unsigned int masked=0;
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 int omega0_attach(omega0_irqdesc_t desc){
00032 l4_threadid_t irq_th;
00033 l4_umword_t dummy;
00034 l4_msgdope_t result;
00035 int error, handle, irq=desc.s.num-1;
00036 static int old_irq = -1;
00037
00038
00039 if(old_irq!=-1){
00040 if(old_irq!=irq) return -1;
00041 handle = irq+1;
00042 return 0;
00043 }
00044
00045 if(rmgr_get_irq(irq)) return -2;
00046 l4_make_taskid_from_irq(irq, &irq_th);
00047
00048 error = l4_ipc_receive(irq_th, 0, &dummy, &dummy,
00049 L4_IPC_BOTH_TIMEOUT_0, &result);
00050
00051 if(error!=L4_IPC_RETIMEOUT) return -3;
00052 handle = irq+1;
00053 old_irq = irq;
00054 irq_mask(irq);
00055 return handle;
00056 }
00057
00058 int omega0_detach(omega0_irqdesc_t desc){
00059 return 0;
00060 }
00061
00062 int omega0_request(int handle, omega0_request_t request){
00063 l4_threadid_t irq_th;
00064 int err, irq = request.s.param-1;
00065 l4_umword_t dummy;
00066 l4_msgdope_t result;
00067
00068 if(request.s.consume){
00069 irq_unmask(irq);
00070 }
00071 if(request.s.unmask){
00072 irq_unmask(irq);
00073 }
00074 if(request.s.wait){
00075
00076 if(masked & (1<<(irq))){
00077 irq_unmask(irq);
00078 }
00079 l4_make_taskid_from_irq(handle-1, &irq_th);
00080 err = l4_ipc_receive(irq_th, L4_IPC_SHORT_MSG, &dummy, &dummy,
00081 L4_IPC_NEVER, &result);
00082 irq_mask(handle-1);
00083 irq_ack(handle-1);
00084 if(err) return err;
00085 }
00086 return 0;
00087 }
00088
00089
00090
00091
00092
00093
00094 static void irq_mask(int irq){
00095 l4util_cli();
00096 if(irq<8){
00097 l4util_out8(l4util_in8(0x21) | (1<<irq), 0x21);
00098 } else {
00099 l4util_out8(l4util_in8(0xa1) | (1<<(irq-8)), 0xa1);
00100 }
00101 masked |= 1<<irq;
00102 l4util_sti();
00103 }
00104
00105 void irq_unmask(int irq){
00106 l4util_cli();
00107 if(irq<8){
00108 l4util_out8(l4util_in8(0x21) & ~(1<<irq), 0x21);
00109 } else {
00110 l4util_out8(l4util_in8(0xa1) & ~(1<<(irq-8)), 0xa1);
00111 }
00112 masked &= ~(1<<irq);
00113 l4util_sti();
00114 }
00115
00116 static void irq_ack(int irq){
00117 l4util_cli();
00118 if (irq > 7){
00119 l4util_out8(0x60|(irq&7), 0xA0);
00120 l4util_out8(0x0B, 0xA0);
00121 if (l4util_in8(0xA0) == 0) l4util_out8(0x62, 0x20);
00122 }else{
00123 l4util_out8(0x60|irq, 0x20);
00124 }
00125 l4util_sti();
00126 }