| [6d5e378] | 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 | #include <sys/types.h>
 | 
|---|
 | 30 | #include <errno.h>
 | 
|---|
 | 31 | #include <malloc.h>
 | 
|---|
 | 32 | #include <macros.h>
 | 
|---|
 | 33 | #include <as.h>
 | 
|---|
 | 34 | #include <ipc/output.h>
 | 
|---|
 | 35 | #include "port/ega.h"
 | 
|---|
 | 36 | #include "port/kchar.h"
 | 
|---|
 | 37 | #include "port/niagara.h"
 | 
|---|
 | 38 | #include "port/ski.h"
 | 
|---|
 | 39 | #include "output.h"
 | 
|---|
 | 40 | 
 | 
|---|
 | 41 | #define MAX_COLS  128
 | 
|---|
 | 42 | #define MAX_ROWS  128
 | 
|---|
 | 43 | 
 | 
|---|
 | 44 | typedef struct {
 | 
|---|
 | 45 |         link_t link;
 | 
|---|
 | 46 |         
 | 
|---|
 | 47 |         size_t size;
 | 
|---|
 | 48 |         unsigned int flags;
 | 
|---|
 | 49 |         void *data;
 | 
|---|
 | 50 | } frontbuf_t;
 | 
|---|
 | 51 | 
 | 
|---|
 | 52 | static LIST_INITIALIZE(outdevs);
 | 
|---|
 | 53 | static LIST_INITIALIZE(frontbufs);
 | 
|---|
 | 54 | 
 | 
|---|
 | 55 | outdev_t *outdev_register(outdev_ops_t *ops, void *data)
 | 
|---|
 | 56 | {
 | 
|---|
 | 57 |         assert(ops->get_dimensions);
 | 
|---|
 | 58 |         
 | 
|---|
 | 59 |         outdev_t *dev = (outdev_t *) malloc(sizeof(outdev_t));
 | 
|---|
 | 60 |         if (dev == NULL)
 | 
|---|
 | 61 |                 return NULL;
 | 
|---|
 | 62 |         
 | 
|---|
 | 63 |         link_initialize(&dev->link);
 | 
|---|
 | 64 |         
 | 
|---|
 | 65 |         dev->ops = *ops;
 | 
|---|
 | 66 |         dev->data = data;
 | 
|---|
 | 67 |         
 | 
|---|
 | 68 |         ops->get_dimensions(dev, &dev->cols, &dev->rows);
 | 
|---|
 | 69 |         dev->backbuf = chargrid_create(dev->cols, dev->rows,
 | 
|---|
 | 70 |             CHARGRID_FLAG_NONE);
 | 
|---|
 | 71 |         if (dev->backbuf == NULL) {
 | 
|---|
 | 72 |                 free(dev);
 | 
|---|
 | 73 |                 return NULL;
 | 
|---|
 | 74 |         }
 | 
|---|
 | 75 |         
 | 
|---|
 | 76 |         list_append(&dev->link, &outdevs);
 | 
|---|
 | 77 |         return dev;
 | 
|---|
 | 78 | }
 | 
|---|
 | 79 | 
 | 
|---|
 | 80 | static void srv_yield(ipc_callid_t iid, ipc_call_t *icall)
 | 
|---|
 | 81 | {
 | 
|---|
 | 82 |         int ret = EOK;
 | 
|---|
 | 83 |         
 | 
|---|
| [feeac0d] | 84 |         list_foreach(outdevs, link, outdev_t, dev) {
 | 
|---|
| [6d5e378] | 85 |                 assert(dev->ops.yield);
 | 
|---|
 | 86 |                 
 | 
|---|
 | 87 |                 int rc = dev->ops.yield(dev);
 | 
|---|
 | 88 |                 if (rc != EOK)
 | 
|---|
 | 89 |                         ret = rc;
 | 
|---|
 | 90 |         }
 | 
|---|
 | 91 |         
 | 
|---|
 | 92 |         async_answer_0(iid, ret);
 | 
|---|
 | 93 | }
 | 
|---|
 | 94 | 
 | 
|---|
 | 95 | static void srv_claim(ipc_callid_t iid, ipc_call_t *icall)
 | 
|---|
 | 96 | {
 | 
|---|
 | 97 |         int ret = EOK;
 | 
|---|
 | 98 |         
 | 
|---|
| [feeac0d] | 99 |         list_foreach(outdevs, link, outdev_t, dev) {
 | 
|---|
| [6d5e378] | 100 |                 assert(dev->ops.claim);
 | 
|---|
 | 101 |                 
 | 
|---|
 | 102 |                 int rc = dev->ops.claim(dev);
 | 
|---|
 | 103 |                 if (rc != EOK)
 | 
|---|
 | 104 |                         ret = rc;
 | 
|---|
 | 105 |         }
 | 
|---|
 | 106 |         
 | 
|---|
 | 107 |         async_answer_0(iid, ret);
 | 
|---|
 | 108 | }
 | 
|---|
 | 109 | 
 | 
|---|
 | 110 | static void srv_get_dimensions(ipc_callid_t iid, ipc_call_t *icall)
 | 
|---|
 | 111 | {
 | 
|---|
 | 112 |         sysarg_t cols = MAX_COLS;
 | 
|---|
 | 113 |         sysarg_t rows = MAX_ROWS;
 | 
|---|
 | 114 |         
 | 
|---|
| [feeac0d] | 115 |         list_foreach(outdevs, link, outdev_t, dev) {
 | 
|---|
| [6d5e378] | 116 |                 cols = min(cols, dev->cols);
 | 
|---|
 | 117 |                 rows = min(rows, dev->rows);
 | 
|---|
 | 118 |         }
 | 
|---|
 | 119 |         
 | 
|---|
 | 120 |         async_answer_2(iid, EOK, cols, rows);
 | 
|---|
 | 121 | }
 | 
|---|
 | 122 | 
 | 
|---|
 | 123 | static void srv_get_caps(ipc_callid_t iid, ipc_call_t *icall)
 | 
|---|
 | 124 | {
 | 
|---|
 | 125 |         console_caps_t caps = 0;
 | 
|---|
 | 126 |         
 | 
|---|
| [feeac0d] | 127 |         list_foreach(outdevs, link, outdev_t, dev) {
 | 
|---|
| [6d5e378] | 128 |                 assert(dev->ops.get_caps);
 | 
|---|
 | 129 |                 
 | 
|---|
 | 130 |                 caps |= dev->ops.get_caps(dev);
 | 
|---|
 | 131 |         }
 | 
|---|
 | 132 |         
 | 
|---|
 | 133 |         async_answer_1(iid, EOK, caps);
 | 
|---|
 | 134 | }
 | 
|---|
 | 135 | 
 | 
|---|
 | 136 | static frontbuf_t *resolve_frontbuf(sysarg_t handle, ipc_callid_t iid)
 | 
|---|
 | 137 | {
 | 
|---|
 | 138 |         frontbuf_t *frontbuf = NULL;
 | 
|---|
| [feeac0d] | 139 |         list_foreach(frontbufs, link, frontbuf_t, cur) {
 | 
|---|
| [6d5e378] | 140 |                 if (cur == (frontbuf_t *) handle) {
 | 
|---|
 | 141 |                         frontbuf = cur;
 | 
|---|
 | 142 |                         break;
 | 
|---|
 | 143 |                 }
 | 
|---|
 | 144 |         }
 | 
|---|
 | 145 |         
 | 
|---|
 | 146 |         if (frontbuf == NULL) {
 | 
|---|
 | 147 |                 async_answer_0(iid, ENOENT);
 | 
|---|
 | 148 |                 return NULL;
 | 
|---|
 | 149 |         }
 | 
|---|
 | 150 |         
 | 
|---|
 | 151 |         return frontbuf;
 | 
|---|
 | 152 | }
 | 
|---|
 | 153 | 
 | 
|---|
 | 154 | static void srv_frontbuf_create(ipc_callid_t iid, ipc_call_t *icall)
 | 
|---|
 | 155 | {
 | 
|---|
 | 156 |         frontbuf_t *frontbuf = (frontbuf_t *) malloc(sizeof(frontbuf_t));
 | 
|---|
 | 157 |         if (frontbuf == NULL) {
 | 
|---|
 | 158 |                 async_answer_0(iid, ENOMEM);
 | 
|---|
 | 159 |                 return;
 | 
|---|
 | 160 |         }
 | 
|---|
 | 161 |         
 | 
|---|
 | 162 |         link_initialize(&frontbuf->link);
 | 
|---|
 | 163 |         
 | 
|---|
 | 164 |         ipc_callid_t callid;
 | 
|---|
 | 165 |         if (!async_share_out_receive(&callid, &frontbuf->size,
 | 
|---|
 | 166 |             &frontbuf->flags)) {
 | 
|---|
 | 167 |                 free(frontbuf);
 | 
|---|
 | 168 |                 async_answer_0(iid, EINVAL);
 | 
|---|
 | 169 |                 return;
 | 
|---|
 | 170 |         }
 | 
|---|
 | 171 |         
 | 
|---|
 | 172 |         int rc = async_share_out_finalize(callid, &frontbuf->data);
 | 
|---|
 | 173 |         if ((rc != EOK) || (frontbuf->data == AS_MAP_FAILED)) {
 | 
|---|
 | 174 |                 free(frontbuf);
 | 
|---|
 | 175 |                 async_answer_0(iid, ENOMEM);
 | 
|---|
 | 176 |                 return;
 | 
|---|
 | 177 |         }
 | 
|---|
 | 178 |         
 | 
|---|
 | 179 |         list_append(&frontbuf->link, &frontbufs);
 | 
|---|
 | 180 |         async_answer_1(iid, EOK, (sysarg_t) frontbuf);
 | 
|---|
 | 181 | }
 | 
|---|
 | 182 | 
 | 
|---|
 | 183 | static void srv_frontbuf_destroy(ipc_callid_t iid, ipc_call_t *icall)
 | 
|---|
 | 184 | {
 | 
|---|
 | 185 |         frontbuf_t *frontbuf = resolve_frontbuf(IPC_GET_ARG1(*icall), iid);
 | 
|---|
 | 186 |         if (frontbuf == NULL)
 | 
|---|
 | 187 |                 return;
 | 
|---|
 | 188 |         
 | 
|---|
 | 189 |         list_remove(&frontbuf->link);
 | 
|---|
 | 190 |         as_area_destroy(frontbuf->data);
 | 
|---|
 | 191 |         free(frontbuf);
 | 
|---|
 | 192 |         
 | 
|---|
 | 193 |         async_answer_0(iid, EOK);
 | 
|---|
 | 194 | }
 | 
|---|
 | 195 | 
 | 
|---|
 | 196 | static void srv_cursor_update(ipc_callid_t iid, ipc_call_t *icall)
 | 
|---|
 | 197 | {
 | 
|---|
 | 198 |         frontbuf_t *frontbuf = resolve_frontbuf(IPC_GET_ARG1(*icall), iid);
 | 
|---|
 | 199 |         if (frontbuf == NULL)
 | 
|---|
 | 200 |                 return;
 | 
|---|
 | 201 |         
 | 
|---|
 | 202 |         chargrid_t *buf = (chargrid_t *) frontbuf->data;
 | 
|---|
 | 203 |         bool visible = chargrid_get_cursor_visibility(buf);
 | 
|---|
 | 204 |         
 | 
|---|
 | 205 |         sysarg_t col;
 | 
|---|
 | 206 |         sysarg_t row;
 | 
|---|
 | 207 |         chargrid_get_cursor(buf, &col, &row);
 | 
|---|
 | 208 |         
 | 
|---|
| [feeac0d] | 209 |         list_foreach(outdevs, link, outdev_t, dev) {
 | 
|---|
| [6d5e378] | 210 |                 assert(dev->ops.cursor_update);
 | 
|---|
 | 211 |                 
 | 
|---|
 | 212 |                 sysarg_t prev_col;
 | 
|---|
 | 213 |                 sysarg_t prev_row;
 | 
|---|
 | 214 |                 chargrid_get_cursor(dev->backbuf, &prev_col, &prev_row);
 | 
|---|
 | 215 |                 
 | 
|---|
 | 216 |                 chargrid_set_cursor(dev->backbuf, col, row);
 | 
|---|
 | 217 |                 chargrid_set_cursor_visibility(dev->backbuf, visible);
 | 
|---|
 | 218 |                 
 | 
|---|
 | 219 |                 dev->ops.cursor_update(dev, prev_col, prev_row, col, row,
 | 
|---|
 | 220 |                     visible);
 | 
|---|
 | 221 |         }
 | 
|---|
 | 222 |         
 | 
|---|
 | 223 |         async_answer_0(iid, EOK);
 | 
|---|
 | 224 | }
 | 
|---|
 | 225 | 
 | 
|---|
 | 226 | static void srv_set_style(ipc_callid_t iid, ipc_call_t *icall)
 | 
|---|
 | 227 | {
 | 
|---|
| [feeac0d] | 228 |         list_foreach(outdevs, link, outdev_t, dev) {
 | 
|---|
| [6d5e378] | 229 |                 dev->attrs.type = CHAR_ATTR_STYLE;
 | 
|---|
 | 230 |                 dev->attrs.val.style =
 | 
|---|
 | 231 |                     (console_style_t) IPC_GET_ARG1(*icall);
 | 
|---|
 | 232 |         }
 | 
|---|
 | 233 |         
 | 
|---|
 | 234 |         async_answer_0(iid, EOK);
 | 
|---|
 | 235 | }
 | 
|---|
 | 236 | 
 | 
|---|
 | 237 | static void srv_set_color(ipc_callid_t iid, ipc_call_t *icall)
 | 
|---|
 | 238 | {
 | 
|---|
| [feeac0d] | 239 |         list_foreach(outdevs, link, outdev_t, dev) {
 | 
|---|
| [6d5e378] | 240 |                 dev->attrs.type = CHAR_ATTR_INDEX;
 | 
|---|
 | 241 |                 dev->attrs.val.index.bgcolor =
 | 
|---|
 | 242 |                     (console_color_t) IPC_GET_ARG1(*icall);
 | 
|---|
 | 243 |                 dev->attrs.val.index.fgcolor =
 | 
|---|
 | 244 |                     (console_color_t) IPC_GET_ARG2(*icall);
 | 
|---|
 | 245 |                 dev->attrs.val.index.attr =
 | 
|---|
 | 246 |                     (console_color_attr_t) IPC_GET_ARG3(*icall);
 | 
|---|
 | 247 |         }
 | 
|---|
 | 248 |         
 | 
|---|
 | 249 |         async_answer_0(iid, EOK);
 | 
|---|
 | 250 | }
 | 
|---|
 | 251 | 
 | 
|---|
 | 252 | static void srv_set_rgb_color(ipc_callid_t iid, ipc_call_t *icall)
 | 
|---|
 | 253 | {
 | 
|---|
| [feeac0d] | 254 |         list_foreach(outdevs, link, outdev_t, dev) {
 | 
|---|
| [6d5e378] | 255 |                 dev->attrs.type = CHAR_ATTR_RGB;
 | 
|---|
 | 256 |                 dev->attrs.val.rgb.bgcolor = IPC_GET_ARG1(*icall);
 | 
|---|
 | 257 |                 dev->attrs.val.rgb.fgcolor = IPC_GET_ARG2(*icall);
 | 
|---|
 | 258 |         }
 | 
|---|
 | 259 |         
 | 
|---|
 | 260 |         async_answer_0(iid, EOK);
 | 
|---|
 | 261 | }
 | 
|---|
 | 262 | 
 | 
|---|
 | 263 | static bool srv_update_scroll(outdev_t *dev, chargrid_t *buf)
 | 
|---|
 | 264 | {
 | 
|---|
 | 265 |         assert(dev->ops.char_update);
 | 
|---|
 | 266 |         
 | 
|---|
 | 267 |         sysarg_t top_row = chargrid_get_top_row(buf);
 | 
|---|
 | 268 |         
 | 
|---|
 | 269 |         if (dev->top_row == top_row)
 | 
|---|
 | 270 |                 return false;
 | 
|---|
 | 271 |         
 | 
|---|
 | 272 |         dev->top_row = top_row;
 | 
|---|
 | 273 |         
 | 
|---|
 | 274 |         for (sysarg_t y = 0; y < dev->rows; y++) {
 | 
|---|
 | 275 |                 for (sysarg_t x = 0; x < dev->cols; x++) {
 | 
|---|
 | 276 |                         charfield_t *front_field =
 | 
|---|
 | 277 |                             chargrid_charfield_at(buf, x, y);
 | 
|---|
 | 278 |                         charfield_t *back_field =
 | 
|---|
 | 279 |                             chargrid_charfield_at(dev->backbuf, x, y);
 | 
|---|
 | 280 |                         bool update = false;
 | 
|---|
 | 281 |                         
 | 
|---|
 | 282 |                         if (front_field->ch != back_field->ch) {
 | 
|---|
 | 283 |                                 back_field->ch = front_field->ch;
 | 
|---|
 | 284 |                                 update = true;
 | 
|---|
 | 285 |                         }
 | 
|---|
 | 286 |                         
 | 
|---|
 | 287 |                         if (!attrs_same(front_field->attrs, back_field->attrs)) {
 | 
|---|
 | 288 |                                 back_field->attrs = front_field->attrs;
 | 
|---|
 | 289 |                                 update = true;
 | 
|---|
 | 290 |                         }
 | 
|---|
 | 291 |                         
 | 
|---|
 | 292 |                         front_field->flags &= ~CHAR_FLAG_DIRTY;
 | 
|---|
 | 293 |                         
 | 
|---|
 | 294 |                         if (update)
 | 
|---|
 | 295 |                                 dev->ops.char_update(dev, x, y);
 | 
|---|
 | 296 |                 }
 | 
|---|
 | 297 |         }
 | 
|---|
 | 298 |         
 | 
|---|
 | 299 |         return true;
 | 
|---|
 | 300 | }
 | 
|---|
 | 301 | 
 | 
|---|
 | 302 | static void srv_update(ipc_callid_t iid, ipc_call_t *icall)
 | 
|---|
 | 303 | {
 | 
|---|
 | 304 |         frontbuf_t *frontbuf = resolve_frontbuf(IPC_GET_ARG1(*icall), iid);
 | 
|---|
 | 305 |         if (frontbuf == NULL)
 | 
|---|
 | 306 |                 return;
 | 
|---|
 | 307 |         
 | 
|---|
 | 308 |         chargrid_t *buf = (chargrid_t *) frontbuf->data;
 | 
|---|
 | 309 |         
 | 
|---|
| [feeac0d] | 310 |         list_foreach(outdevs, link, outdev_t, dev) {
 | 
|---|
| [6d5e378] | 311 |                 assert(dev->ops.char_update);
 | 
|---|
 | 312 |                 
 | 
|---|
 | 313 |                 if (srv_update_scroll(dev, buf))
 | 
|---|
 | 314 |                         continue;
 | 
|---|
 | 315 |                 
 | 
|---|
 | 316 |                 for (sysarg_t y = 0; y < dev->rows; y++) {
 | 
|---|
 | 317 |                         for (sysarg_t x = 0; x < dev->cols; x++) {
 | 
|---|
 | 318 |                                 charfield_t *front_field =
 | 
|---|
 | 319 |                                     chargrid_charfield_at(buf, x, y);
 | 
|---|
 | 320 |                                 charfield_t *back_field =
 | 
|---|
 | 321 |                                     chargrid_charfield_at(dev->backbuf, x, y);
 | 
|---|
 | 322 |                                 bool update = false;
 | 
|---|
 | 323 |                                 
 | 
|---|
 | 324 |                                 if ((front_field->flags & CHAR_FLAG_DIRTY) ==
 | 
|---|
 | 325 |                                     CHAR_FLAG_DIRTY) {
 | 
|---|
 | 326 |                                         if (front_field->ch != back_field->ch) {
 | 
|---|
 | 327 |                                                 back_field->ch = front_field->ch;
 | 
|---|
 | 328 |                                                 update = true;
 | 
|---|
 | 329 |                                         }
 | 
|---|
 | 330 |                                         
 | 
|---|
 | 331 |                                         if (!attrs_same(front_field->attrs,
 | 
|---|
 | 332 |                                             back_field->attrs)) {
 | 
|---|
 | 333 |                                                 back_field->attrs = front_field->attrs;
 | 
|---|
 | 334 |                                                 update = true;
 | 
|---|
 | 335 |                                         }
 | 
|---|
 | 336 |                                         
 | 
|---|
 | 337 |                                         front_field->flags &= ~CHAR_FLAG_DIRTY;
 | 
|---|
 | 338 |                                 }
 | 
|---|
 | 339 |                                 
 | 
|---|
 | 340 |                                 if (update)
 | 
|---|
 | 341 |                                         dev->ops.char_update(dev, x, y);
 | 
|---|
 | 342 |                         }
 | 
|---|
 | 343 |                 }
 | 
|---|
 | 344 |         }
 | 
|---|
 | 345 |         
 | 
|---|
 | 346 |         async_answer_0(iid, EOK);
 | 
|---|
 | 347 | }
 | 
|---|
 | 348 | 
 | 
|---|
 | 349 | static void srv_damage(ipc_callid_t iid, ipc_call_t *icall)
 | 
|---|
 | 350 | {
 | 
|---|
 | 351 |         frontbuf_t *frontbuf = resolve_frontbuf(IPC_GET_ARG1(*icall), iid);
 | 
|---|
 | 352 |         if (frontbuf == NULL)
 | 
|---|
 | 353 |                 return;
 | 
|---|
 | 354 |         
 | 
|---|
 | 355 |         chargrid_t *buf = (chargrid_t *) frontbuf->data;
 | 
|---|
 | 356 |         
 | 
|---|
| [feeac0d] | 357 |         list_foreach(outdevs, link, outdev_t, dev) {
 | 
|---|
| [6d5e378] | 358 |                 assert(dev->ops.char_update);
 | 
|---|
 | 359 |                 
 | 
|---|
 | 360 |                 if (srv_update_scroll(dev, buf))
 | 
|---|
 | 361 |                         continue;
 | 
|---|
 | 362 |                 
 | 
|---|
 | 363 |                 sysarg_t col = IPC_GET_ARG2(*icall);
 | 
|---|
 | 364 |                 sysarg_t row = IPC_GET_ARG3(*icall);
 | 
|---|
 | 365 |                 
 | 
|---|
 | 366 |                 sysarg_t cols = IPC_GET_ARG4(*icall);
 | 
|---|
 | 367 |                 sysarg_t rows = IPC_GET_ARG5(*icall);
 | 
|---|
 | 368 |                 
 | 
|---|
 | 369 |                 for (sysarg_t y = 0; y < rows; y++) {
 | 
|---|
 | 370 |                         for (sysarg_t x = 0; x < cols; x++) {
 | 
|---|
 | 371 |                                 charfield_t *front_field =
 | 
|---|
 | 372 |                                     chargrid_charfield_at(buf, col + x, row + y);
 | 
|---|
 | 373 |                                 charfield_t *back_field =
 | 
|---|
 | 374 |                                     chargrid_charfield_at(dev->backbuf, col + x, row + y);
 | 
|---|
 | 375 |                                 
 | 
|---|
 | 376 |                                 back_field->ch = front_field->ch;
 | 
|---|
 | 377 |                                 back_field->attrs = front_field->attrs;
 | 
|---|
 | 378 |                                 front_field->flags &= ~CHAR_FLAG_DIRTY;
 | 
|---|
 | 379 |                                 dev->ops.char_update(dev, col + x, row + y);
 | 
|---|
 | 380 |                         }
 | 
|---|
 | 381 |                 }
 | 
|---|
 | 382 |         }
 | 
|---|
 | 383 |         
 | 
|---|
 | 384 |         async_answer_0(iid, EOK);
 | 
|---|
 | 385 | }
 | 
|---|
 | 386 | 
 | 
|---|
 | 387 | static void client_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
 | 
|---|
 | 388 | {
 | 
|---|
 | 389 |         /* Accept the connection */
 | 
|---|
 | 390 |         async_answer_0(iid, EOK);
 | 
|---|
 | 391 |         
 | 
|---|
 | 392 |         while (true) {
 | 
|---|
 | 393 |                 ipc_call_t call;
 | 
|---|
 | 394 |                 ipc_callid_t callid = async_get_call(&call);
 | 
|---|
 | 395 |                 
 | 
|---|
 | 396 |                 if (!IPC_GET_IMETHOD(call)) {
 | 
|---|
 | 397 |                         async_answer_0(callid, EOK);
 | 
|---|
 | 398 |                         break;
 | 
|---|
 | 399 |                 }
 | 
|---|
 | 400 |                 
 | 
|---|
 | 401 |                 switch (IPC_GET_IMETHOD(call)) {
 | 
|---|
 | 402 |                         case OUTPUT_YIELD:
 | 
|---|
 | 403 |                                 srv_yield(callid, &call);
 | 
|---|
 | 404 |                                 break;
 | 
|---|
 | 405 |                         case OUTPUT_CLAIM:
 | 
|---|
 | 406 |                                 srv_claim(callid, &call);
 | 
|---|
 | 407 |                                 break;
 | 
|---|
 | 408 |                         case OUTPUT_GET_DIMENSIONS:
 | 
|---|
 | 409 |                                 srv_get_dimensions(callid, &call);
 | 
|---|
 | 410 |                                 break;
 | 
|---|
 | 411 |                         case OUTPUT_GET_CAPS:
 | 
|---|
 | 412 |                                 srv_get_caps(callid, &call);
 | 
|---|
 | 413 |                                 break;
 | 
|---|
 | 414 |                         
 | 
|---|
 | 415 |                         case OUTPUT_FRONTBUF_CREATE:
 | 
|---|
 | 416 |                                 srv_frontbuf_create(callid, &call);
 | 
|---|
 | 417 |                                 break;
 | 
|---|
 | 418 |                         case OUTPUT_FRONTBUF_DESTROY:
 | 
|---|
 | 419 |                                 srv_frontbuf_destroy(callid, &call);
 | 
|---|
 | 420 |                                 break;
 | 
|---|
 | 421 |                         
 | 
|---|
 | 422 |                         case OUTPUT_CURSOR_UPDATE:
 | 
|---|
 | 423 |                                 srv_cursor_update(callid, &call);
 | 
|---|
 | 424 |                                 break;
 | 
|---|
 | 425 |                         case OUTPUT_SET_STYLE:
 | 
|---|
 | 426 |                                 srv_set_style(callid, &call);
 | 
|---|
 | 427 |                                 break;
 | 
|---|
 | 428 |                         case OUTPUT_SET_COLOR:
 | 
|---|
 | 429 |                                 srv_set_color(callid, &call);
 | 
|---|
 | 430 |                                 break;
 | 
|---|
 | 431 |                         case OUTPUT_SET_RGB_COLOR:
 | 
|---|
 | 432 |                                 srv_set_rgb_color(callid, &call);
 | 
|---|
 | 433 |                                 break;
 | 
|---|
 | 434 |                         case OUTPUT_UPDATE:
 | 
|---|
 | 435 |                                 srv_update(callid, &call);
 | 
|---|
 | 436 |                                 break;
 | 
|---|
 | 437 |                         case OUTPUT_DAMAGE:
 | 
|---|
 | 438 |                                 srv_damage(callid, &call);
 | 
|---|
 | 439 |                                 break;
 | 
|---|
 | 440 |                         
 | 
|---|
 | 441 |                         default:
 | 
|---|
 | 442 |                                 async_answer_0(callid, EINVAL);
 | 
|---|
 | 443 |                 }
 | 
|---|
 | 444 |         }
 | 
|---|
 | 445 | }
 | 
|---|
 | 446 | 
 | 
|---|
 | 447 | static void usage(char *name)
 | 
|---|
 | 448 | {
 | 
|---|
 | 449 |         printf("Usage: %s <service_name>\n", name);
 | 
|---|
 | 450 | }
 | 
|---|
 | 451 | 
 | 
|---|
 | 452 | int main(int argc, char *argv[])
 | 
|---|
 | 453 | {
 | 
|---|
 | 454 |         if (argc < 2) {
 | 
|---|
 | 455 |                 usage(argv[0]);
 | 
|---|
 | 456 |                 return 1;
 | 
|---|
 | 457 |         }
 | 
|---|
 | 458 |         
 | 
|---|
 | 459 |         printf("%s: HelenOS output service\n", NAME);
 | 
|---|
 | 460 |         
 | 
|---|
 | 461 |         /* Register server */
 | 
|---|
| [b688fd8] | 462 |         async_set_fallback_port_handler(client_connection, NULL);
 | 
|---|
| [6d5e378] | 463 |         int rc = loc_server_register(NAME);
 | 
|---|
 | 464 |         if (rc != EOK) {
 | 
|---|
 | 465 |                 printf("%s: Unable to register driver\n", NAME);
 | 
|---|
 | 466 |                 return rc;
 | 
|---|
 | 467 |         }
 | 
|---|
 | 468 |         
 | 
|---|
 | 469 |         service_id_t service_id;
 | 
|---|
 | 470 |         rc = loc_service_register(argv[1], &service_id);
 | 
|---|
 | 471 |         if (rc != EOK) {
 | 
|---|
 | 472 |                 printf("%s: Unable to register service %s\n", NAME, argv[1]);
 | 
|---|
 | 473 |                 return rc;
 | 
|---|
 | 474 |         }
 | 
|---|
 | 475 |         
 | 
|---|
 | 476 |         ega_init();
 | 
|---|
 | 477 |         kchar_init();
 | 
|---|
 | 478 |         niagara_init();
 | 
|---|
 | 479 |         ski_init();
 | 
|---|
 | 480 |         
 | 
|---|
 | 481 |         printf("%s: Accepting connections\n", NAME);
 | 
|---|
 | 482 |         task_retval(0);
 | 
|---|
 | 483 |         async_manager();
 | 
|---|
 | 484 |         
 | 
|---|
 | 485 |         /* Never reached */
 | 
|---|
 | 486 |         return 0;
 | 
|---|
 | 487 | }
 | 
|---|