Changeset a8f7029 in mainline
- Timestamp:
- 2011-12-25T21:39:52Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- e747303
- Parents:
- b1f44b4
- Location:
- uspace/drv/char/i8042
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/char/i8042/i8042.c
rb1f44b4 ra8f7029 51 51 #include <ddf/interrupt.h> 52 52 53 #include <ops/char_dev.h> 54 53 55 #include "i8042.h" 54 56 55 57 #define NAME "i8042" 58 59 static int i8042_write_kbd(ddf_fun_t *, char *, size_t); 60 static int i8042_read_kbd(ddf_fun_t *, char *, size_t); 61 static int i8042_write_aux(ddf_fun_t *, char *, size_t); 62 static int i8042_read_aux(ddf_fun_t *, char *, size_t); 63 64 static char_dev_ops_t kbd_iface = { 65 .read = i8042_read_kbd, 66 .write = i8042_write_kbd, 67 }; 68 69 static char_dev_ops_t aux_iface = { 70 .read = i8042_read_aux, 71 .write = i8042_write_aux, 72 }; 73 74 static ddf_dev_ops_t kbd_ops = { 75 .interfaces[CHAR_DEV_IFACE] = &kbd_iface 76 }; 77 78 static ddf_dev_ops_t aux_ops = { 79 .interfaces[CHAR_DEV_IFACE] = &aux_iface 80 }; 56 81 57 82 /* Interesting bits for status register */ … … 69 94 #define i8042_KBD_DISABLE 0x10 70 95 #define i8042_AUX_DISABLE 0x20 71 #define i8042_KBD_TRANSLATE 0x40 96 #define i8042_KBD_TRANSLATE 0x40 /* Use this to switch to XT scancodes */ 72 97 73 98 static const irq_cmd_t i8042_cmds[] = { … … 97 122 } 98 123 }; 99 124 /*----------------------------------------------------------------------------*/ 100 125 static void wait_ready(i8042_t *dev) 101 126 { … … 103 128 while (pio_read_8(&dev->regs->status) & i8042_INPUT_FULL); 104 129 } 105 130 /*----------------------------------------------------------------------------*/ 131 static void wait_ready_write(i8042_t *dev) 132 { 133 assert(dev); 134 while (pio_read_8(&dev->regs->status) & i8042_OUTPUT_FULL); 135 } 136 /*----------------------------------------------------------------------------*/ 106 137 static void i8042_irq_handler( 107 138 ddf_dev_t *dev, ipc_callid_t iid, ipc_call_t *call) 108 139 { 109 110 const int status = IPC_GET_ARG1(*call);111 const int data = IPC_GET_ARG2(*call);112 const int devid = (status & i8042_AUX_DATA) ? DEVID_AUX : DEVID_PRI;113 ddf_msg(LVL_WARN, "Unhandled %s data: %x , status: %x.",114 (devid == DEVID_AUX) ? "AUX" : "PRIMARY", data, status);115 #if 0116 140 if (!dev || !dev->driver_data) 117 141 return; 118 119 if (device.port[devid].client_sess != NULL) { 120 async_exch_t *exch = 121 async_exchange_begin(device.port[devid].client_sess); 122 if (exch) { 123 async_msg_1(exch, IPC_FIRST_USER_METHOD, data); 124 async_exchange_end(exch); 125 } 142 i8042_t *controller = dev->driver_data; 143 fibril_mutex_lock(&controller->guard); 144 145 const uint8_t status = IPC_GET_ARG1(*call); 146 const uint8_t data = IPC_GET_ARG2(*call); 147 char ** buffer = (status & i8042_AUX_DATA) ? 148 &controller->aux_buffer : &controller->kbd_buffer; 149 char * buffer_end = (status & i8042_AUX_DATA) ? 150 controller->aux_buffer_end : controller->kbd_buffer_end; 151 if (*buffer != NULL && *buffer < buffer_end) { 152 *(*buffer)++ = data; 153 if (*buffer == buffer_end) 154 fibril_condvar_signal(&controller->data_avail); 126 155 } else { 127 ddf_msg(LVL_WARN, "No client session.\n"); 128 } 129 #endif 156 ddf_msg(LVL_WARN, "Unhandled %s data: %x , status: %x.", 157 (status & i8042_AUX_DATA) ? "AUX" : "KBD", data, status); 158 } 159 160 fibril_mutex_unlock(&controller->guard); 130 161 } 131 162 /*----------------------------------------------------------------------------*/ … … 151 182 return ENOMEM; 152 183 } 184 185 dev->kbd_fun->ops = &kbd_ops; 186 dev->mouse_fun->ops = &aux_ops; 187 dev->kbd_fun->driver_data = dev; 188 dev->mouse_fun->driver_data = dev; 189 190 fibril_mutex_initialize(&dev->guard); 191 fibril_condvar_initialize(&dev->data_avail); 192 dev->kbd_buffer = NULL; 193 dev->kbd_buffer_end = NULL; 194 dev->aux_buffer = NULL; 195 dev->aux_buffer_end = NULL; 153 196 154 197 #define CHECK_RET_DESTROY(ret, msg...) \ … … 215 258 "Failed set handler for mouse: %s.\n", str_error(ret)); 216 259 217 #if 0218 ret = ddf_fun_add_to_category(dev->kbd_fun, "keyboard");219 if (ret != EOK)220 ddf_msg(LVL_WARN, "Failed to register kbd fun to category.\n");221 ret = ddf_fun_add_to_category(dev->mouse_fun, "mouse");222 if (ret != EOK)223 ddf_msg(LVL_WARN, "Failed to register mouse fun to category.\n");224 #endif225 260 /* Enable interrupts */ 226 261 async_sess_t *parent_sess = … … 229 264 ret = parent_sess ? EOK : ENOMEM; 230 265 CHECK_RET_UNBIND_DESTROY(ret, "Failed to create parent connection.\n"); 266 231 267 const bool enabled = hw_res_enable_interrupt(parent_sess); 232 268 async_hangup(parent_sess); … … 243 279 return EOK; 244 280 } 281 /*----------------------------------------------------------------------------*/ 282 static int i8042_write_kbd(ddf_fun_t *fun, char *buffer, size_t size) 283 { 284 assert(fun); 285 assert(fun->driver_data); 286 i8042_t *controller = fun->driver_data; 287 fibril_mutex_lock(&controller->guard); 288 for (size_t i = 0; i < size; ++i) { 289 wait_ready_write(controller); 290 pio_write_8(&controller->regs->data, buffer[i]); 291 } 292 fibril_mutex_unlock(&controller->guard); 293 return EOK; 294 } 295 /*----------------------------------------------------------------------------*/ 296 static int i8042_read_kbd(ddf_fun_t *fun, char *buffer, size_t size) 297 { 298 assert(fun); 299 assert(fun->driver_data); 300 bzero(buffer, size); 301 302 i8042_t *controller = fun->driver_data; 303 fibril_mutex_lock(&controller->guard); 304 /* There is someone else reading from the device. */ 305 if (controller->kbd_buffer) { 306 fibril_mutex_unlock(&controller->guard); 307 return EBUSY; 308 } 309 controller->kbd_buffer = buffer; 310 controller->kbd_buffer_end = buffer + size; 311 /* Wait for buffer to be filled */ 312 while (controller->kbd_buffer != controller->kbd_buffer_end) 313 fibril_condvar_wait( 314 &controller->data_avail, &controller->guard); 315 316 controller->kbd_buffer = NULL; 317 controller->kbd_buffer_end = NULL; 318 fibril_mutex_unlock(&controller->guard); 319 return EOK; 320 } 321 /*----------------------------------------------------------------------------*/ 322 static int i8042_write_aux(ddf_fun_t *fun, char *buffer, size_t size) 323 { 324 assert(fun); 325 assert(fun->driver_data); 326 i8042_t *controller = fun->driver_data; 327 fibril_mutex_lock(&controller->guard); 328 for (size_t i = 0; i < size; ++i) { 329 wait_ready_write(controller); 330 pio_write_8(&controller->regs->status, i8042_CMD_WRITE_AUX); 331 pio_write_8(&controller->regs->data, buffer[i]); 332 } 333 fibril_mutex_unlock(&controller->guard); 334 return EOK; 335 } 336 /*----------------------------------------------------------------------------*/ 337 static int i8042_read_aux(ddf_fun_t *fun, char *buffer, size_t size) 338 { 339 assert(fun); 340 assert(fun->driver_data); 341 bzero(buffer, size); 342 343 i8042_t *controller = fun->driver_data; 344 fibril_mutex_lock(&controller->guard); 345 /* There is someone else reading from the device. */ 346 if (controller->aux_buffer) { 347 fibril_mutex_unlock(&controller->guard); 348 return EBUSY; 349 } 350 controller->aux_buffer = buffer; 351 controller->aux_buffer_end = buffer + size; 352 /* Wait for buffer to be filled */ 353 while (controller->aux_buffer != controller->aux_buffer_end) 354 fibril_condvar_wait( 355 &controller->data_avail, &controller->guard); 356 357 controller->aux_buffer = NULL; 358 controller->aux_buffer_end = NULL; 359 fibril_mutex_unlock(&controller->guard); 360 return EOK; 361 } 362 /*----------------------------------------------------------------------------*/ 245 363 246 364 /** Character device connection handler */ -
uspace/drv/char/i8042/i8042.h
rb1f44b4 ra8f7029 73 73 ddf_fun_t *kbd_fun; 74 74 ddf_fun_t *mouse_fun; 75 char * kbd_buffer; 76 char * kbd_buffer_end; 77 char * aux_buffer; 78 char * aux_buffer_end; 75 79 fibril_mutex_t guard; 76 80 fibril_condvar_t data_avail; … … 78 82 79 83 int i8042_init(i8042_t *, void *, size_t, int, int, ddf_dev_t *); 80 int i8042_write_kbd(i8042_t *, uint8_t);81 int i8042_read_kbd(i8042_t *, uint8_t *);82 int i8042_write_aux(i8042_t *, uint8_t);83 int i8042_read_aux(i8042_t *, uint8_t *);84 85 84 #endif 86 85 /**
Note:
See TracChangeset
for help on using the changeset viewer.