source: mainline/uspace/drv/intctl/i8259/i8259.c@ 984a9ba

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 984a9ba was 984a9ba, checked in by Martin Decky <martin@…>, 7 years ago

do not expose the call capability handler from the async framework

Keep the call capability handler encapsulated within the async framework
and do not expose it explicitly via its API. Use the pointer to
ipc_call_t as the sole object identifying an IPC call in the code that
uses the async framework.

This plugs a major leak in the abstraction and also simplifies both the
async framework (slightly) and all IPC servers.

  • Property mode set to 100644
File size: 4.7 KB
Line 
1/*
2 * Copyright (c) 2011 Martin Decky
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup i8259
30 * @{
31 */
32
33/**
34 * @file i8259.c
35 * @brief i8259 driver.
36 */
37
38#include <ipc/irc.h>
39#include <loc.h>
40#include <sysinfo.h>
41#include <as.h>
42#include <ddf/log.h>
43#include <ddi.h>
44#include <align.h>
45#include <stdbool.h>
46#include <errno.h>
47#include <str_error.h>
48#include <async.h>
49#include <stdio.h>
50
51#include "i8259.h"
52
53#define NAME "i8259"
54
55#define IO_RANGE0_SIZE 2
56#define IO_RANGE1_SIZE 2
57
58#define PIC_PIC0PORT1 0
59#define PIC_PIC0PORT2 1
60
61#define PIC_PIC1PORT1 0
62#define PIC_PIC1PORT2 1
63
64#define PIC_MAX_IRQ 15
65
66static errno_t pic_enable_irq(i8259_t *i8259, sysarg_t irq)
67{
68 if (irq > PIC_MAX_IRQ)
69 return ENOENT;
70
71 uint16_t irqmask = 1 << irq;
72 uint8_t val;
73
74 if (irqmask & 0xff) {
75 val = pio_read_8(i8259->regs0 + PIC_PIC0PORT2);
76 pio_write_8(i8259->regs0 + PIC_PIC0PORT2,
77 (uint8_t) (val & (~(irqmask & 0xff))));
78 }
79
80 if (irqmask >> 8) {
81 val = pio_read_8(i8259->regs1 + PIC_PIC1PORT2);
82 pio_write_8(i8259->regs1 + PIC_PIC1PORT2,
83 (uint8_t) (val & (~(irqmask >> 8))));
84 }
85
86 return EOK;
87}
88
89/** Handle one connection to i8259.
90 *
91 * @param icall Call data of the request that opened the connection.
92 * @param arg Local argument.
93 *
94 */
95static void i8259_connection(ipc_call_t *icall, void *arg)
96{
97 ipc_call_t call;
98 i8259_t *i8259 = NULL /* XXX */;
99
100 /*
101 * Answer the first IPC_M_CONNECT_ME_TO call.
102 */
103 async_answer_0(icall, EOK);
104
105 i8259 = (i8259_t *) ddf_dev_data_get(ddf_fun_get_dev((ddf_fun_t *) arg));
106
107 while (true) {
108 async_get_call(&call);
109
110 if (!IPC_GET_IMETHOD(call)) {
111 /* The other side has hung up. */
112 async_answer_0(&call, EOK);
113 return;
114 }
115
116 switch (IPC_GET_IMETHOD(call)) {
117 case IRC_ENABLE_INTERRUPT:
118 async_answer_0(&call, pic_enable_irq(i8259,
119 IPC_GET_ARG1(call)));
120 break;
121 case IRC_DISABLE_INTERRUPT:
122 /* XXX TODO */
123 async_answer_0(&call, EOK);
124 break;
125 case IRC_CLEAR_INTERRUPT:
126 /* Noop */
127 async_answer_0(&call, EOK);
128 break;
129 default:
130 async_answer_0(&call, EINVAL);
131 break;
132 }
133 }
134}
135
136/** Add i8259 device. */
137errno_t i8259_add(i8259_t *i8259, i8259_res_t *res)
138{
139 sysarg_t have_i8259;
140 ioport8_t *regs0;
141 ioport8_t *regs1;
142 ddf_fun_t *fun_a = NULL;
143 errno_t rc;
144
145 if ((sysinfo_get_value("i8259", &have_i8259) != EOK) || (!have_i8259)) {
146 printf("%s: No i8259 found\n", NAME);
147 return ENOTSUP;
148 }
149
150 if ((pio_enable((void *) res->base0, IO_RANGE0_SIZE,
151 (void **) &regs0) != EOK) ||
152 (pio_enable((void *) res->base1, IO_RANGE1_SIZE,
153 (void **) &regs1) != EOK)) {
154 printf("%s: i8259 not accessible\n", NAME);
155 return EIO;
156 }
157
158 i8259->regs0 = regs0;
159 i8259->regs1 = regs1;
160
161 fun_a = ddf_fun_create(i8259->dev, fun_exposed, "a");
162 if (fun_a == NULL) {
163 ddf_msg(LVL_ERROR, "Failed creating function 'a'.");
164 rc = ENOMEM;
165 goto error;
166 }
167
168 ddf_fun_set_conn_handler(fun_a, i8259_connection);
169
170 rc = ddf_fun_bind(fun_a);
171 if (rc != EOK) {
172 ddf_msg(LVL_ERROR, "Failed binding function 'a': %s", str_error(rc));
173 goto error;
174 }
175
176 rc = ddf_fun_add_to_category(fun_a, "irc");
177 if (rc != EOK)
178 goto error;
179
180 return EOK;
181error:
182 if (fun_a != NULL)
183 ddf_fun_destroy(fun_a);
184 return rc;
185}
186
187/** Remove i8259 device */
188errno_t i8259_remove(i8259_t *i8259)
189{
190 return ENOTSUP;
191}
192
193/** i8259 device gone */
194errno_t i8259_gone(i8259_t *i8259)
195{
196 return ENOTSUP;
197}
198
199/**
200 * @}
201 */
Note: See TracBrowser for help on using the repository browser.