2 * Copyright (c) 2006 Ondrej Palkovsky
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
29 /** @addtogroup kio KIO
42 #include <str_error.h>
46 #include <fibril_synch.h>
48 #include <adt/prodcons.h>
53 #define LOG_FNAME "/log/kio"
55 /* Producer/consumer buffers */
64 /* Pointer to kio area */
65 static wchar_t *kio
= (wchar_t *) AS_AREA_ANY
;
66 static size_t kio_length
;
68 /* Notification mutex */
69 static FIBRIL_MUTEX_INITIALIZE(mtx
);
73 * Copies the contents of a character buffer to local
74 * producer/consumer queue.
76 * @param length Number of characters to copy.
77 * @param data Pointer to the kernel kio buffer.
80 static void producer(size_t length
, wchar_t *data
)
82 item_t
*item
= (item_t
*) malloc(sizeof(item_t
));
86 size_t sz
= sizeof(wchar_t) * length
;
87 wchar_t *buf
= (wchar_t *) malloc(sz
);
93 memcpy(buf
, data
, sz
);
95 link_initialize(&item
->link
);
96 item
->length
= length
;
98 prodcons_produce(&pc
, &item
->link
);
103 * Waits in an infinite loop for the character data created by
104 * the producer and outputs them to stdout and optionally into
107 * @param data Unused.
109 * @return Always EOK (unreachable).
112 static errno_t
consumer(void *data
)
114 FILE *log
= fopen(LOG_FNAME
, "a");
116 printf("%s: Unable to create log file %s (%s)\n", NAME
, LOG_FNAME
,
120 link_t
*link
= prodcons_consume(&pc
);
121 item_t
*item
= list_get_instance(link
, item_t
, link
);
123 for (size_t i
= 0; i
< item
->length
; i
++)
124 putchar(item
->data
[i
]);
127 for (size_t i
= 0; i
< item
->length
; i
++)
128 fputc(item
->data
[i
], log
);
131 vfs_sync(fileno(log
));
142 /** Kernel notification handler
144 * Receives kernel kio notifications.
146 * @param call IPC call structure
147 * @param arg Local argument
150 static void kio_notification_handler(ipc_call_t
*call
, void *arg
)
153 * Make sure we process only a single notification
154 * at any time to limit the chance of the consumer
157 * Note: Usually the automatic masking of the kio
158 * notifications on the kernel side does the trick
159 * of limiting the chance of accidentally copying
160 * the same data multiple times. However, due to
161 * the non-blocking architecture of kio notifications,
162 * this possibility cannot be generally avoided.
165 fibril_mutex_lock(&mtx
);
167 size_t kio_start
= (size_t) IPC_GET_ARG1(*call
);
168 size_t kio_len
= (size_t) IPC_GET_ARG2(*call
);
169 size_t kio_stored
= (size_t) IPC_GET_ARG3(*call
);
171 size_t offset
= (kio_start
+ kio_len
- kio_stored
) % kio_length
;
173 /* Copy data from the ring buffer */
174 if (offset
+ kio_stored
>= kio_length
) {
175 size_t split
= kio_length
- offset
;
177 producer(split
, kio
+ offset
);
178 producer(kio_stored
- split
, kio
);
180 producer(kio_stored
, kio
+ offset
);
182 async_event_unmask(EVENT_KIO
);
183 fibril_mutex_unlock(&mtx
);
186 int main(int argc
, char *argv
[])
189 errno_t rc
= sysinfo_get_value("kio.pages", &pages
);
191 fprintf(stderr
, "%s: Unable to get number of kio pages\n",
197 rc
= sysinfo_get_value("kio.faddr", &faddr
);
199 fprintf(stderr
, "%s: Unable to get kio physical address\n",
204 size_t size
= pages
* PAGE_SIZE
;
205 kio_length
= size
/ sizeof(wchar_t);
207 rc
= physmem_map(faddr
, pages
, AS_AREA_READ
| AS_AREA_CACHEABLE
,
210 fprintf(stderr
, "%s: Unable to map kio\n", NAME
);
214 prodcons_initialize(&pc
);
215 rc
= async_event_subscribe(EVENT_KIO
, kio_notification_handler
, NULL
);
217 fprintf(stderr
, "%s: Unable to register kio notifications\n",
222 fid_t fid
= fibril_create(consumer
, NULL
);
224 fprintf(stderr
, "%s: Unable to create consumer fibril\n",
229 tinput_t
*input
= tinput_new();
231 fprintf(stderr
, "%s: Could not create input\n", NAME
);
235 fibril_add_ready(fid
);
236 async_event_unmask(EVENT_KIO
);
239 tinput_set_prompt(input
, "kio> ");
242 while ((rc
= tinput_read(input
, &str
)) == EOK
) {
243 if (str_cmp(str
, "") == 0) {
248 kio_command(str
, str_size(str
));