00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00038 #include <ipc/services.h>
00039 #include <ipc/irc.h>
00040 #include <ipc/ns.h>
00041 #include <sysinfo.h>
00042 #include <as.h>
00043 #include <ddi.h>
00044 #include <libarch/ddi.h>
00045 #include <align.h>
00046 #include <bool.h>
00047 #include <errno.h>
00048 #include <async.h>
00049 #include <align.h>
00050 #include <async.h>
00051 #include <stdio.h>
00052 #include <ipc/devmap.h>
00053
00054 #define NAME "i8259"
00055
00056 #define IO_RANGE0_START ((ioport8_t *) 0x0020U)
00057 #define IO_RANGE0_SIZE 2
00058
00059 #define IO_RANGE1_START ((ioport8_t *) 0x00a0U)
00060 #define IO_RANGE1_SIZE 2
00061
00062 static ioport8_t *io_range0;
00063 static ioport8_t *io_range1;
00064
00065 #define PIC_PIC0PORT1 0
00066 #define PIC_PIC0PORT2 1
00067
00068 #define PIC_PIC1PORT1 0
00069 #define PIC_PIC1PORT2 1
00070
00071 #define PIC_MAX_IRQ 15
00072
00073 static int pic_enable_irq(sysarg_t irq)
00074 {
00075 if (irq > PIC_MAX_IRQ)
00076 return ENOENT;
00077
00078 uint16_t irqmask = 1 << irq;
00079 uint8_t val;
00080
00081 if (irqmask & 0xff) {
00082 val = pio_read_8(io_range0 + PIC_PIC0PORT2);
00083 pio_write_8(io_range0 + PIC_PIC0PORT2,
00084 (uint8_t) (val & (~(irqmask & 0xff))));
00085 }
00086
00087 if (irqmask >> 8) {
00088 val = pio_read_8(io_range1 + PIC_PIC1PORT2);
00089 pio_write_8(io_range1 + PIC_PIC1PORT2,
00090 (uint8_t) (val & (~(irqmask >> 8))));
00091 }
00092
00093 return EOK;
00094 }
00095
00102 static void i8259_connection(ipc_callid_t iid, ipc_call_t *icall)
00103 {
00104 ipc_callid_t callid;
00105 ipc_call_t call;
00106
00107
00108
00109
00110 async_answer_0(iid, EOK);
00111
00112 while (true) {
00113 callid = async_get_call(&call);
00114
00115 switch (IPC_GET_IMETHOD(call)) {
00116 case IRC_ENABLE_INTERRUPT:
00117 async_answer_0(callid, pic_enable_irq(IPC_GET_ARG1(call)));
00118 break;
00119 case IRC_CLEAR_INTERRUPT:
00120
00121 async_answer_0(callid, EOK);
00122 break;
00123 case IPC_M_PHONE_HUNGUP:
00124
00125 async_answer_0(callid, EOK);
00126 return;
00127 default:
00128 async_answer_0(callid, EINVAL);
00129 break;
00130 }
00131 }
00132 }
00133
00137 static bool i8259_init(void)
00138 {
00139 sysarg_t i8259;
00140
00141 if ((sysinfo_get_value("i8259", &i8259) != EOK) || (!i8259)) {
00142 printf(NAME ": No i8259 found\n");
00143 return false;
00144 }
00145
00146 if ((pio_enable((void *) IO_RANGE0_START, IO_RANGE0_SIZE,
00147 (void **) &io_range0) != EOK) ||
00148 (pio_enable((void *) IO_RANGE1_START, IO_RANGE1_SIZE,
00149 (void **) &io_range1) != EOK)) {
00150 printf(NAME ": i8259 not accessible\n");
00151 return false;
00152 }
00153
00154 async_set_client_connection(i8259_connection);
00155 service_register(SERVICE_IRC);
00156
00157 return true;
00158 }
00159
00160 int main(int argc, char **argv)
00161 {
00162 printf(NAME ": HelenOS i8259 driver\n");
00163
00164 if (!i8259_init())
00165 return -1;
00166
00167 printf(NAME ": Accepting connections\n");
00168 async_manager();
00169
00170
00171 return 0;
00172 }
00173