i8259.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2011 Martin Decky
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  *
00009  * - Redistributions of source code must retain the above copyright
00010  *   notice, this list of conditions and the following disclaimer.
00011  * - Redistributions in binary form must reproduce the above copyright
00012  *   notice, this list of conditions and the following disclaimer in the
00013  *   documentation and/or other materials provided with the distribution.
00014  * - The name of the author may not be used to endorse or promote products
00015  *   derived from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00018  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00019  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00020  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
00021  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00022  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00023  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00024  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00025  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00026  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
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          * Answer the first IPC_M_CONNECT_ME_TO call.
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                         /* Noop */
00121                         async_answer_0(callid, EOK);
00122                         break;
00123                 case IPC_M_PHONE_HUNGUP:
00124                         /* The other side has hung up. */
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         /* Never reached */
00171         return 0;
00172 }
00173 

Generated on Thu Jun 2 07:45:50 2011 for HelenOS/USB by  doxygen 1.4.7