Changeset ee163b3 in mainline
- Timestamp:
- 2011-12-10T01:32:05Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 5960b48
- Parents:
- f44ba92
- Location:
- uspace/drv/char/i8042
- Files:
-
- 2 added
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
TabularUnified uspace/drv/char/i8042/Makefile ¶
rf44ba92 ree163b3 34 34 35 35 SOURCES = \ 36 i8042.c 36 i8042.c \ 37 main.c 37 38 38 39 include $(USPACE_PREFIX)/Makefile.common -
TabularUnified uspace/drv/char/i8042/i8042.c ¶
rf44ba92 ree163b3 42 42 #include <async.h> 43 43 #include <unistd.h> 44 #include <sysinfo.h>45 44 #include <stdio.h> 46 45 #include <errno.h> 46 #include <str_error.h> 47 47 #include <inttypes.h> 48 #include <ddf/log.h> 49 #include <ddf/interrupt.h> 50 48 51 #include "i8042.h" 49 52 … … 67 70 #define i8042_KBD_TRANSLATE 0x40 68 71 69 70 static irq_cmd_t i8042_cmds[] = { 72 static const irq_cmd_t i8042_cmds[] = { 71 73 { 72 74 .cmd = CMD_PIO_READ_8, … … 95 97 }; 96 98 97 static irq_code_t i8042_kbd = { 98 sizeof(i8042_cmds) / sizeof(irq_cmd_t), 99 i8042_cmds 100 }; 101 102 static i8042_dev_t device; 103 104 static void wait_ready(i8042_dev_t *dev) 99 static i8042_t device; 100 101 static void wait_ready(i8042_t *dev) 105 102 { 106 103 assert(dev); … … 108 105 } 109 106 110 static void i8042_irq_handler(ipc_callid_t iid, ipc_call_t *call); 107 static void i8042_irq_handler(ddf_dev_t *dev, 108 ipc_callid_t iid, ipc_call_t *call); 111 109 static void i8042_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg); 112 static int i8042_init(i8042_dev_t *dev); 113 static void i8042_port_write(i8042_dev_t *dev, int devid, uint8_t data); 114 115 116 int main(int argc, char *argv[]) 117 { 118 printf(NAME ": i8042 PS/2 port driver\n"); 119 120 int rc = loc_server_register(NAME, i8042_connection); 121 if (rc < 0) { 122 printf(NAME ": Unable to register server.\n"); 123 return rc; 124 } 125 126 if (i8042_init(&device) != EOK) 110 static void i8042_port_write(i8042_t *dev, int devid, uint8_t data); 111 112 int i8042_init(i8042_t *dev, void *regs, size_t reg_size, int irq_kbd, 113 int irq_mouse, ddf_dev_t *ddf_dev) 114 { 115 assert(ddf_dev); 116 assert(dev); 117 118 if (reg_size < sizeof(i8042_regs_t)) 119 return EINVAL; 120 121 if (pio_enable(regs, sizeof(i8042_regs_t), (void**)&dev->regs) != 0) 127 122 return -1; 128 123 129 for (int i = 0; i < MAX_DEVS; i++) { 130 device.port[i].client_sess = NULL; 131 132 static const char *names[MAX_DEVS] = { 133 NAMESPACE "/ps2a", NAMESPACE "/ps2b"}; 134 rc = loc_service_register(names[i], &device.port[i].service_id); 135 if (rc != EOK) { 136 printf(NAME ": Unable to register device %s.\n", 137 names[i]); 138 return rc; 139 } 140 printf(NAME ": Registered device %s\n", names[i]); 141 } 142 143 printf(NAME ": Accepting connections\n"); 144 task_retval(0); 145 async_manager(); 146 147 /* Not reached */ 148 return 0; 149 } 150 151 static int i8042_init(i8042_dev_t *dev) 152 { 153 static uintptr_t i8042_physical; 154 static uintptr_t i8042_kernel; 155 assert(dev); 156 if (sysinfo_get_value("i8042.address.physical", &i8042_physical) != EOK) 157 return -1; 158 159 if (sysinfo_get_value("i8042.address.kernel", &i8042_kernel) != EOK) 160 return -1; 161 162 void *vaddr; 163 if (pio_enable((void *) i8042_physical, sizeof(i8042_regs_t), &vaddr) != 0) 164 return -1; 165 166 dev->regs = vaddr; 167 168 sysarg_t inr_a; 169 sysarg_t inr_b; 170 171 if (sysinfo_get_value("i8042.inr_a", &inr_a) != EOK) 172 return -1; 173 174 if (sysinfo_get_value("i8042.inr_b", &inr_b) != EOK) 175 return -1; 176 177 async_set_interrupt_received(i8042_irq_handler); 178 124 dev->kbd_fun = ddf_fun_create(ddf_dev, fun_exposed, "ps2a"); 125 if (!dev->kbd_fun) 126 return ENOMEM; 127 128 dev->mouse_fun = ddf_fun_create(ddf_dev, fun_exposed, "ps2b"); 129 if (!dev->mouse_fun) { 130 ddf_fun_destroy(dev->kbd_fun); 131 return ENOMEM; 132 } 133 134 #define CHECK_RET_DESTROY(ret, msg...) \ 135 if (ret != EOK) { \ 136 ddf_msg(LVL_ERROR, msg); \ 137 if (dev->kbd_fun) { \ 138 dev->kbd_fun->driver_data = NULL; \ 139 ddf_fun_destroy(dev->kbd_fun); \ 140 } \ 141 if (dev->mouse_fun) { \ 142 dev->mouse_fun->driver_data = NULL; \ 143 ddf_fun_destroy(dev->mouse_fun); \ 144 } \ 145 } else (void)0 146 147 int ret = ddf_fun_bind(dev->kbd_fun); 148 CHECK_RET_DESTROY(ret, 149 "Failed to bind keyboard function: %s.\n", str_error(ret)); 150 151 ret = ddf_fun_bind(dev->mouse_fun); 152 CHECK_RET_DESTROY(ret, 153 "Failed to bind mouse function: %s.\n", str_error(ret)); 154 179 155 /* Disable kbd and aux */ 180 156 wait_ready(dev); … … 187 163 (void) pio_read_8(&dev->regs->data); 188 164 189 i8042_kbd.cmds[0].addr = (void *) &((i8042_regs_t *) i8042_kernel)->status; 190 i8042_kbd.cmds[3].addr = (void *) &((i8042_regs_t *) i8042_kernel)->data; 191 register_irq(inr_a, device_assign_devno(), 0, &i8042_kbd); 192 register_irq(inr_b, device_assign_devno(), 0, &i8042_kbd); 193 printf("%s: registered for interrupts %" PRIun " and %" PRIun "\n", 194 NAME, inr_a, inr_b); 165 #define CHECK_RET_UNBIND_DESTROY(ret, msg...) \ 166 if (ret != EOK) { \ 167 ddf_msg(LVL_ERROR, msg); \ 168 if (dev->kbd_fun) { \ 169 ddf_fun_unbind(dev->kbd_fun); \ 170 dev->kbd_fun->driver_data = NULL; \ 171 ddf_fun_destroy(dev->kbd_fun); \ 172 } \ 173 if (dev->mouse_fun) { \ 174 ddf_fun_unbind(dev->mouse_fun); \ 175 dev->mouse_fun->driver_data = NULL; \ 176 ddf_fun_destroy(dev->mouse_fun); \ 177 } \ 178 } else (void)0 179 const size_t cmd_count = sizeof(i8042_cmds) / sizeof(irq_cmd_t); 180 irq_cmd_t cmds[cmd_count]; 181 memcpy(cmds, i8042_cmds, sizeof(i8042_cmds)); 182 cmds[0].addr = (void *) &dev->regs->status; 183 cmds[3].addr = (void *) &dev->regs->data; 184 185 irq_code_t irq_code = { .cmdcount = cmd_count, .cmds = cmds }; 186 ddf_msg(LVL_DEBUG, 187 "Registering interrupt handler for device %s on irq %d.\n", 188 ddf_dev->name, irq_kbd); 189 ret = register_interrupt_handler(ddf_dev, irq_kbd, i8042_irq_handler, 190 &irq_code); 191 CHECK_RET_UNBIND_DESTROY(ret, 192 "Failed set handler for kbd: %s.\n", str_error(ret)); 193 194 ddf_msg(LVL_DEBUG, 195 "Registering interrupt handler for device %s on irq %d.\n", 196 ddf_dev->name, irq_mouse); 197 ret = register_interrupt_handler(ddf_dev, irq_mouse, i8042_irq_handler, 198 &irq_code); 199 CHECK_RET_UNBIND_DESTROY(ret, 200 "Failed set handler for mouse: %s.\n", str_error(ret)); 201 202 ret = ddf_fun_add_to_category(dev->kbd_fun, "keyboard"); 203 if (ret != EOK) 204 ddf_msg(LVL_WARN, "Failed to register kbd fun to category.\n"); 205 ret = ddf_fun_add_to_category(dev->mouse_fun, "mouse"); 206 if (ret != EOK) 207 ddf_msg(LVL_WARN, "Failed to register mouse fun to category.\n"); 208 209 // TODO: Don't rely on kernel enabling interrupts do it yourself. 195 210 196 211 wait_ready(dev); … … 200 215 i8042_AUX_IE); 201 216 202 return 0; 217 // TODO: Plug in connection. 218 219 return ret; 220 (void)i8042_connection; 203 221 } 204 222 … … 271 289 } 272 290 273 void i8042_port_write(i8042_dev_t *dev, int devid, uint8_t data) 274 { 291 void i8042_port_write(i8042_t *dev, int devid, uint8_t data) 292 { 293 275 294 assert(dev); 276 295 if (devid == DEVID_AUX) { … … 282 301 } 283 302 284 static void i8042_irq_handler(ipc_callid_t iid, ipc_call_t *call) 285 { 286 int status, data; 287 int devid; 288 289 status = IPC_GET_ARG1(*call); 290 data = IPC_GET_ARG2(*call); 291 292 if ((status & i8042_AUX_DATA)) { 293 devid = DEVID_AUX; 294 } else { 295 devid = DEVID_PRI; 296 } 303 void i8042_irq_handler(ddf_dev_t *dev, ipc_callid_t iid, ipc_call_t *call) 304 { 305 ddf_msg(LVL_FATAL, "IRQ!!!.\n"); 306 if (!dev || !dev->driver_data) 307 return; 308 309 const int status = IPC_GET_ARG1(*call); 310 const int data = IPC_GET_ARG2(*call); 311 const int devid = (status & i8042_AUX_DATA) ? DEVID_AUX : DEVID_PRI; 297 312 298 313 if (device.port[devid].client_sess != NULL) { 299 314 async_exch_t *exch = 300 315 async_exchange_begin(device.port[devid].client_sess); 301 async_msg_1(exch, IPC_FIRST_USER_METHOD, data); 302 async_exchange_end(exch); 316 if (exch) { 317 async_msg_1(exch, IPC_FIRST_USER_METHOD, data); 318 async_exchange_end(exch); 319 } 320 } else { 321 ddf_msg(LVL_WARN, "No client session.\n"); 303 322 } 304 323 } -
TabularUnified uspace/drv/char/i8042/i8042.h ¶
rf44ba92 ree163b3 42 42 #include <libarch/ddi.h> 43 43 #include <async.h> 44 #include <ddf/driver.h> 44 45 45 46 /** i8042 HW I/O interface */ … … 65 66 i8042_regs_t *regs; 66 67 i8042_port_t port[MAX_DEVS]; 67 } i8042_dev_t; 68 ddf_fun_t *kbd_fun; 69 ddf_fun_t *mouse_fun; 70 } i8042_t; 71 72 int i8042_init(i8042_t *, void *, size_t, int, int, ddf_dev_t *); 68 73 69 74 #endif 70 71 75 /** 72 76 * @}
Note:
See TracChangeset
for help on using the changeset viewer.