Changes in uspace/drv/char/i8042/i8042.c [ca4730a5:75751db6] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/char/i8042/i8042.c
rca4730a5 r75751db6 2 2 * Copyright (c) 2001-2004 Jakub Jermar 3 3 * Copyright (c) 2006 Josef Cejka 4 * Copyright (c) 20 09Jiri Svoboda4 * Copyright (c) 2014 Jiri Svoboda 5 5 * Copyright (c) 2011 Jan Vesely 6 6 * All rights reserved. … … 39 39 */ 40 40 41 #include <ddf/log.h> 42 #include <ddf/interrupt.h> 43 #include <ddi.h> 41 44 #include <device/hw_res.h> 42 #include <ddi.h>43 45 #include <errno.h> 44 46 #include <str_error.h> 45 47 #include <inttypes.h> 46 #include < ddf/log.h>47 #include <ddf/interrupt.h> 48 #include <io/chardev_srv.h> 49 48 50 #include "i8042.h" 49 51 … … 64 66 #define i8042_KBD_TRANSLATE 0x40 /* Use this to switch to XT scancodes */ 65 67 66 void default_handler(ddf_fun_t *, ipc_callid_t, ipc_call_t *); 67 68 /** Port function operations. */ 69 static ddf_dev_ops_t ops = { 70 .default_handler = default_handler, 68 static void i8042_char_conn(ipc_callid_t, ipc_call_t *, void *); 69 static int i8042_read(chardev_srv_t *, void *, size_t); 70 static int i8042_write(chardev_srv_t *, const void *, size_t); 71 72 static chardev_ops_t i8042_chardev_ops = { 73 .read = i8042_read, 74 .write = i8042_write 71 75 }; 72 76 … … 106 110 }; 107 111 108 /** Get i8042 soft state from device node. */109 static i8042_t *dev_i8042(ddf_dev_t *dev)110 {111 return ddf_dev_data_get(dev);112 }113 114 112 /** Wait until it is safe to write to the device. */ 115 113 static void wait_ready(i8042_t *dev) … … 123 121 * Write new data to the corresponding buffer. 124 122 * 125 * @param dev Device that caued the interrupt.126 123 * @param iid Call id. 127 124 * @param call pointerr to call data. 128 * 129 */ 130 static void i8042_irq_handler(ddf_dev_t *dev, ipc_callid_t iid, 131 ipc_call_t *call) 132 { 133 i8042_t *controller = dev_i8042(dev); 125 * @param dev Device that caued the interrupt. 126 * 127 */ 128 static void i8042_irq_handler(ipc_callid_t iid, ipc_call_t *call, 129 ddf_dev_t *dev) 130 { 131 i8042_t *controller = ddf_dev_data_get(dev); 134 132 135 133 const uint8_t status = IPC_GET_ARG1(*call); … … 145 143 * 146 144 * @param dev Driver structure to initialize. 147 * @param regs I/O address of registers. 148 * @param reg_size size of the reserved I/O address space. 145 * @param regs I/O range of registers. 149 146 * @param irq_kbd IRQ for primary port. 150 147 * @param irq_mouse IRQ for aux port. … … 154 151 * 155 152 */ 156 int i8042_init(i8042_t *dev, void *regs, size_t reg_size, int irq_kbd,153 int i8042_init(i8042_t *dev, addr_range_t *regs, int irq_kbd, 157 154 int irq_mouse, ddf_dev_t *ddf_dev) 158 155 { … … 162 159 const size_t cmd_count = sizeof(i8042_cmds) / sizeof(irq_cmd_t); 163 160 irq_cmd_t cmds[cmd_count]; 161 i8042_regs_t *ar; 164 162 165 163 int rc; … … 170 168 dev->aux_fun = NULL; 171 169 172 if (reg _size < sizeof(i8042_regs_t)) {170 if (regs->size < sizeof(i8042_regs_t)) { 173 171 rc = EINVAL; 174 172 goto error; 175 173 } 176 174 177 if (pio_enable (regs, sizeof(i8042_regs_t), (void **) &dev->regs) != 0) {175 if (pio_enable_range(regs, (void **) &dev->regs) != 0) { 178 176 rc = EIO; 179 177 goto error; … … 186 184 }; 187 185 186 dev->kbd = ddf_fun_data_alloc(dev->kbd_fun, sizeof(i8042_port_t)); 187 if (dev->kbd == NULL) { 188 rc = ENOMEM; 189 goto error; 190 } 191 192 dev->kbd->ctl = dev; 193 chardev_srvs_init(&dev->kbd->cds); 194 dev->kbd->cds.ops = &i8042_chardev_ops; 195 dev->kbd->cds.sarg = dev->kbd; 196 188 197 rc = ddf_fun_add_match_id(dev->kbd_fun, "char/xtkbd", 90); 189 198 if (rc != EOK) … … 196 205 } 197 206 207 dev->aux = ddf_fun_data_alloc(dev->aux_fun, sizeof(i8042_port_t)); 208 if (dev->aux == NULL) { 209 rc = ENOMEM; 210 goto error; 211 } 212 213 dev->aux->ctl = dev; 214 chardev_srvs_init(&dev->aux->cds); 215 dev->aux->cds.ops = &i8042_chardev_ops; 216 dev->aux->cds.sarg = dev->aux; 217 198 218 rc = ddf_fun_add_match_id(dev->aux_fun, "char/ps2mouse", 90); 199 219 if (rc != EOK) 200 220 goto error; 201 221 202 ddf_fun_set_ ops(dev->kbd_fun, &ops);203 ddf_fun_set_ ops(dev->aux_fun, &ops);222 ddf_fun_set_conn_handler(dev->kbd_fun, i8042_char_conn); 223 ddf_fun_set_conn_handler(dev->aux_fun, i8042_char_conn); 204 224 205 225 buffer_init(&dev->kbd_buffer, dev->kbd_data, BUFFER_SIZE); … … 234 254 235 255 memcpy(ranges, i8042_ranges, sizeof(i8042_ranges)); 236 ranges[0].base = (uintptr_t) regs; 237 256 ranges[0].base = RNGABS(*regs); 257 258 259 ar = RNGABSPTR(*regs); 238 260 memcpy(cmds, i8042_cmds, sizeof(i8042_cmds)); 239 cmds[0].addr = (void *) & (((i8042_regs_t *) regs)->status);240 cmds[3].addr = (void *) & (((i8042_regs_t *) regs)->data);261 cmds[0].addr = (void *) &ar->status; 262 cmds[3].addr = (void *) &ar->data; 241 263 242 264 irq_code_t irq_code = { … … 296 318 } 297 319 298 // FIXME TODO use shared instead this299 enum {300 IPC_CHAR_READ = DEV_FIRST_CUSTOM_METHOD,301 IPC_CHAR_WRITE,302 };303 304 320 /** Write data to i8042 port. 305 321 * 306 * @param fun DDF function.307 * @param buffer Data source .308 * @param size Data size .322 * @param srv Connection-specific data 323 * @param buffer Data source 324 * @param size Data size 309 325 * 310 326 * @return Bytes written. 311 327 * 312 328 */ 313 static int i8042_write(ddf_fun_t *fun, char *buffer, size_t size) 314 { 315 i8042_t *controller = dev_i8042(ddf_fun_get_dev(fun)); 316 fibril_mutex_lock(&controller->write_guard); 329 static int i8042_write(chardev_srv_t *srv, const void *data, size_t size) 330 { 331 i8042_port_t *port = (i8042_port_t *)srv->srvs->sarg; 332 i8042_t *i8042 = port->ctl; 333 const char *dp = (const char *)data; 334 335 fibril_mutex_lock(&i8042->write_guard); 317 336 318 337 for (size_t i = 0; i < size; ++i) { 319 if ( controller->aux_fun == fun) {320 wait_ready( controller);321 pio_write_8(& controller->regs->status,338 if (port == i8042->aux) { 339 wait_ready(i8042); 340 pio_write_8(&i8042->regs->status, 322 341 i8042_CMD_WRITE_AUX); 323 342 } 324 343 325 wait_ready( controller);326 pio_write_8(& controller->regs->data, buffer[i]);327 } 328 329 fibril_mutex_unlock(& controller->write_guard);344 wait_ready(i8042); 345 pio_write_8(&i8042->regs->data, dp[i]); 346 } 347 348 fibril_mutex_unlock(&i8042->write_guard); 330 349 return size; 331 350 } … … 333 352 /** Read data from i8042 port. 334 353 * 335 * @param fun DDF function.336 * @param buffer Data place .337 * @param size Data place size .354 * @param srv Connection-specific data 355 * @param buffer Data place 356 * @param size Data place size 338 357 * 339 358 * @return Bytes read. 340 359 * 341 360 */ 342 static int i8042_read(ddf_fun_t *fun, char *data, size_t size) 343 { 344 i8042_t *controller = dev_i8042(ddf_fun_get_dev(fun)); 345 buffer_t *buffer = (fun == controller->aux_fun) ? 346 &controller->aux_buffer : &controller->kbd_buffer; 361 static int i8042_read(chardev_srv_t *srv, void *dest, size_t size) 362 { 363 i8042_port_t *port = (i8042_port_t *)srv->srvs->sarg; 364 i8042_t *i8042 = port->ctl; 365 uint8_t *destp = (uint8_t *)dest; 366 367 buffer_t *buffer = (port == i8042->aux) ? 368 &i8042->aux_buffer : &i8042->kbd_buffer; 347 369 348 370 for (size_t i = 0; i < size; ++i) 349 *d ata++ = buffer_read(buffer);371 *destp++ = buffer_read(buffer); 350 372 351 373 return size; … … 354 376 /** Handle data requests. 355 377 * 356 * @param fun ddf_fun_t function.357 378 * @param id callid 358 379 * @param call IPC request. 359 * 360 */ 361 void default_handler(ddf_fun_t *fun, ipc_callid_t id, ipc_call_t *call) 362 { 363 const sysarg_t method = IPC_GET_IMETHOD(*call); 364 const size_t size = IPC_GET_ARG1(*call); 365 366 switch (method) { 367 case IPC_CHAR_READ: 368 if (size <= 4 * sizeof(sysarg_t)) { 369 sysarg_t message[4] = {}; 370 371 i8042_read(fun, (char *) message, size); 372 async_answer_4(id, size, message[0], message[1], 373 message[2], message[3]); 374 } else 375 async_answer_0(id, ELIMIT); 376 break; 377 378 case IPC_CHAR_WRITE: 379 if (size <= 3 * sizeof(sysarg_t)) { 380 const sysarg_t message[3] = { 381 IPC_GET_ARG2(*call), 382 IPC_GET_ARG3(*call), 383 IPC_GET_ARG4(*call) 384 }; 385 386 i8042_write(fun, (char *) message, size); 387 async_answer_0(id, size); 388 } else 389 async_answer_0(id, ELIMIT); 390 391 default: 392 async_answer_0(id, EINVAL); 393 } 380 * @param arg ddf_fun_t function. 381 */ 382 void i8042_char_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg) 383 { 384 i8042_port_t *port = ddf_fun_data_get((ddf_fun_t *)arg); 385 386 chardev_conn(iid, icall, &port->cds); 394 387 } 395 388
Note:
See TracChangeset
for help on using the changeset viewer.