Changes in / [786bd56:304faab] in mainline
- Files:
-
- 14 edited
-
kernel/arch/amd64/include/interrupt.h (modified) (1 diff)
-
kernel/arch/amd64/src/amd64.c (modified) (1 diff)
-
kernel/arch/ia32/include/interrupt.h (modified) (1 diff)
-
kernel/arch/ia32/src/ia32.c (modified) (1 diff)
-
kernel/arch/ia64/include/interrupt.h (modified) (1 diff)
-
kernel/arch/ia64/src/ia64.c (modified) (2 diffs)
-
uspace/drv/bus/isa/isa.dev (modified) (1 diff)
-
uspace/drv/bus/isa/isa.ma (modified) (1 diff)
-
uspace/drv/bus/pci/pciintel/pci.c (modified) (1 diff)
-
uspace/drv/char/i8042/buffer.h (modified) (5 diffs)
-
uspace/drv/char/i8042/i8042.c (modified) (18 diffs)
-
uspace/drv/char/i8042/i8042.h (modified) (4 diffs)
-
uspace/drv/char/i8042/main.c (modified) (3 diffs)
-
uspace/lib/c/generic/loc.c (modified) (7 diffs)
Legend:
- Unmodified
- Added
- Removed
-
kernel/arch/amd64/include/interrupt.h
r786bd56 r304faab 55 55 #define IRQ_PIC_SPUR 7 56 56 #define IRQ_MOUSE 12 57 #define IRQ_NE2000 9 57 58 58 59 /* This one must have four least significant bits set to ones */ -
kernel/arch/amd64/src/amd64.c
r786bd56 r304faab 214 214 } 215 215 } 216 217 /* 218 * This is the necessary evil until the userspace driver is entirely 219 * self-sufficient. 220 */ 221 sysinfo_set_item_val("i8042", NULL, true); 222 sysinfo_set_item_val("i8042.inr_a", NULL, IRQ_KBD); 223 sysinfo_set_item_val("i8042.inr_b", NULL, IRQ_MOUSE); 224 sysinfo_set_item_val("i8042.address.physical", NULL, 225 (uintptr_t) I8042_BASE); 226 sysinfo_set_item_val("i8042.address.kernel", NULL, 227 (uintptr_t) I8042_BASE); 216 228 #endif 217 229 218 230 if (irqs_info != NULL) 219 231 sysinfo_set_item_val(irqs_info, NULL, true); 232 233 sysinfo_set_item_val("netif.ne2000.inr", NULL, IRQ_NE2000); 220 234 } 221 235 -
kernel/arch/ia32/include/interrupt.h
r786bd56 r304faab 55 55 #define IRQ_PIC_SPUR 7 56 56 #define IRQ_MOUSE 12 57 #define IRQ_NE2000 5 57 58 58 59 /* This one must have four least significant bits set to ones */ -
kernel/arch/ia32/src/ia32.c
r786bd56 r304faab 168 168 } 169 169 } 170 171 /* 172 * This is the necessary evil until the userspace driver is entirely 173 * self-sufficient. 174 */ 175 sysinfo_set_item_val("i8042", NULL, true); 176 sysinfo_set_item_val("i8042.inr_a", NULL, IRQ_KBD); 177 sysinfo_set_item_val("i8042.inr_b", NULL, IRQ_MOUSE); 178 sysinfo_set_item_val("i8042.address.physical", NULL, 179 (uintptr_t) I8042_BASE); 180 sysinfo_set_item_val("i8042.address.kernel", NULL, 181 (uintptr_t) I8042_BASE); 170 182 #endif 171 183 172 184 if (irqs_info != NULL) 173 185 sysinfo_set_item_val(irqs_info, NULL, true); 186 187 sysinfo_set_item_val("netif.ne2000.inr", NULL, IRQ_NE2000); 174 188 } 175 189 -
kernel/arch/ia64/include/interrupt.h
r786bd56 r304faab 61 61 #define IRQ_KBD (0x01 + LEGACY_INTERRUPT_BASE) 62 62 #define IRQ_MOUSE (0x0c + LEGACY_INTERRUPT_BASE) 63 #define IRQ_NE2000 (0x09 + LEGACY_INTERRUPT_BASE) 63 64 64 65 /** General Exception codes. */ -
kernel/arch/ia64/src/ia64.c
r786bd56 r304faab 188 188 189 189 #ifdef CONFIG_I8042 190 i8042_instance_t *i8042_instance = i8042_init((i8042_t *) I8042_BASE, 191 IRQ_KBD); 190 i8042_instance_t *i8042_instance = i8042_init((i8042_t *) I8042_BASE, IRQ_KBD); 192 191 if (i8042_instance) { 193 192 kbrd_instance_t *kbrd_instance = kbrd_init(); … … 198 197 } 199 198 } 200 #endif 201 199 200 sysinfo_set_item_val("i8042", NULL, true); 201 sysinfo_set_item_val("i8042.inr_a", NULL, IRQ_KBD); 202 sysinfo_set_item_val("i8042.inr_b", NULL, IRQ_MOUSE); 203 sysinfo_set_item_val("i8042.address.physical", NULL, 204 (uintptr_t) I8042_BASE); 205 sysinfo_set_item_val("i8042.address.kernel", NULL, 206 (uintptr_t) I8042_BASE); 207 #endif 208 209 sysinfo_set_item_val("netif.ne2000.inr", NULL, IRQ_NE2000); 210 202 211 sysinfo_set_item_val("ia64_iospace", NULL, true); 203 212 sysinfo_set_item_val("ia64_iospace.address", NULL, true); -
uspace/drv/bus/isa/isa.dev
r786bd56 r304faab 14 14 irq 12 15 15 io_range 060 5 16 16 17 17 18 ne2k: -
uspace/drv/bus/isa/isa.ma
r786bd56 r304faab 1 9 pci/ class=06&subclass=011 9 pci/ven=8086&dev=7000 -
uspace/drv/bus/pci/pciintel/pci.c
r786bd56 r304faab 92 92 static bool pciintel_enable_interrupt(ddf_fun_t *fnode) 93 93 { 94 /* This is an old ugly way */94 /* This is an old ugly way, copied from ne2000 driver */ 95 95 assert(fnode); 96 96 pci_fun_t *dev_data = (pci_fun_t *) fnode->driver_data; -
uspace/drv/char/i8042/buffer.h
r786bd56 r304faab 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 29 28 /** 30 29 * @addtogroup kbd 31 30 * @{ 32 31 */ 33 34 32 /** @file 35 33 * @brief Cyclic buffer structure. … … 48 46 * Attempt to insert byte into the full buffer will block until it can succeed. 49 47 * Attempt to read from empty buffer will block until it can succeed. 50 *51 48 */ 52 49 typedef struct { 53 uint8_t *buffer; /**< Storage space. */54 uint8_t *buffer_end; /**< End of storage place. */55 fibril_mutex_t guard; /**< Protects buffer structures. */56 fibril_condvar_t change; /**< Indicates change (empty/full). */57 uint8_t *read_head; /**< Place of the next readable element. */58 uint8_t *write_head; /**< Pointer to the next writable place. */50 uint8_t *buffer; /**< Storage space. */ 51 uint8_t *buffer_end; /**< End of storage place. */ 52 fibril_mutex_t guard; /**< Protects buffer structures. */ 53 fibril_condvar_t change; /**< Indicates change (empty/full). */ 54 uint8_t *read_head; /**< Place of the next readable element. */ 55 uint8_t *write_head; /**< Pointer to the next writable place. */ 59 56 } buffer_t; 60 57 61 58 /** Initialize cyclic buffer using provided memory space. 62 *63 59 * @param buffer Cyclic buffer structure to initialize. 64 * @param data Memory space to use. 65 * @param size Size of the memory place. 66 * 60 * @param data Memory space to use. 61 * @param size Size of the memory place. 67 62 */ 68 63 static inline void buffer_init(buffer_t *buffer, uint8_t *data, size_t size) 69 64 { 70 65 assert(buffer); 71 72 66 fibril_mutex_initialize(&buffer->guard); 73 67 fibril_condvar_initialize(&buffer->change); … … 80 74 81 75 /** Write byte to cyclic buffer. 82 *83 76 * @param buffer Cyclic buffer to write to. 84 * @param data Data to write. 85 * 77 * @param data Data to write. 86 78 */ 87 79 static inline void buffer_write(buffer_t *buffer, uint8_t data) 88 80 { 89 81 fibril_mutex_lock(&buffer->guard); 90 82 91 83 /* Next position. */ 92 84 uint8_t *new_head = buffer->write_head + 1; 93 85 if (new_head == buffer->buffer_end) 94 86 new_head = buffer->buffer; 95 87 96 88 /* Buffer full. */ 97 89 while (new_head == buffer->read_head) 98 90 fibril_condvar_wait(&buffer->change, &buffer->guard); 99 91 100 92 /* Write data. */ 101 93 *buffer->write_head = data; 102 94 103 95 /* Buffer was empty. */ 104 96 if (buffer->write_head == buffer->read_head) 105 97 fibril_condvar_broadcast(&buffer->change); 106 98 107 99 /* Move head */ 108 100 buffer->write_head = new_head; … … 111 103 112 104 /** Read byte from cyclic buffer. 113 *114 105 * @param buffer Cyclic buffer to read from. 115 *116 106 * @return Byte read. 117 *118 107 */ 119 108 static inline uint8_t buffer_read(buffer_t *buffer) 120 109 { 121 110 fibril_mutex_lock(&buffer->guard); 122 123 111 /* Buffer is empty. */ 124 112 while (buffer->write_head == buffer->read_head) 125 113 fibril_condvar_wait(&buffer->change, &buffer->guard); 126 114 127 115 /* Next position. */ 128 116 uint8_t *new_head = buffer->read_head + 1; 129 117 if (new_head == buffer->buffer_end) 130 118 new_head = buffer->buffer; 131 119 132 120 /* Read data. */ 133 121 const uint8_t data = *buffer->read_head; 134 122 135 123 /* Buffer was full. */ 136 124 uint8_t *new_write_head = buffer->write_head + 1; … … 139 127 if (new_write_head == buffer->read_head) 140 128 fibril_condvar_broadcast(&buffer->change); 141 129 142 130 /* Move head */ 143 131 buffer->read_head = new_head; 144 132 145 133 fibril_mutex_unlock(&buffer->guard); 146 134 return data; 147 135 } 148 149 136 #endif 150 151 137 /** 152 138 * @} -
uspace/drv/char/i8042/i8042.c
r786bd56 r304faab 29 29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 30 */ 31 32 31 /** @addtogroup kbd_port 33 32 * @ingroup kbd 34 33 * @{ 35 34 */ 36 37 35 /** @file 38 36 * @brief i8042 PS/2 port driver. … … 46 44 #include <str_error.h> 47 45 #include <inttypes.h> 46 48 47 #include <ddf/log.h> 49 48 #include <ddf/interrupt.h> 49 50 50 #include "i8042.h" 51 51 52 /* Interesting bits for status register */ 53 #define i8042_OUTPUT_FULL 0x01 54 #define i8042_INPUT_FULL 0x02 55 #define i8042_AUX_DATA 0x20 56 57 /* Command constants */ 58 #define i8042_CMD_WRITE_CMDB 0x60 /**< Write command byte */ 59 #define i8042_CMD_WRITE_AUX 0xd4 /**< Write aux device */ 60 61 /* Command byte fields */ 62 #define i8042_KBD_IE 0x01 63 #define i8042_AUX_IE 0x02 64 #define i8042_KBD_DISABLE 0x10 65 #define i8042_AUX_DISABLE 0x20 66 #define i8042_KBD_TRANSLATE 0x40 /* Use this to switch to XT scancodes */ 67 68 #define CHECK_RET_DESTROY(ret, msg...) \ 69 do { \ 70 if (ret != EOK) { \ 71 ddf_msg(LVL_ERROR, msg); \ 72 if (dev->kbd_fun) { \ 73 dev->kbd_fun->driver_data = NULL; \ 74 ddf_fun_destroy(dev->kbd_fun); \ 75 } \ 76 if (dev->aux_fun) { \ 77 dev->aux_fun->driver_data = NULL; \ 78 ddf_fun_destroy(dev->aux_fun); \ 79 } \ 80 } \ 81 } while (0) 82 83 #define CHECK_RET_UNBIND_DESTROY(ret, msg...) \ 84 do { \ 85 if (ret != EOK) { \ 86 ddf_msg(LVL_ERROR, msg); \ 87 if (dev->kbd_fun) { \ 88 ddf_fun_unbind(dev->kbd_fun); \ 89 dev->kbd_fun->driver_data = NULL; \ 90 ddf_fun_destroy(dev->kbd_fun); \ 91 } \ 92 if (dev->aux_fun) { \ 93 ddf_fun_unbind(dev->aux_fun); \ 94 dev->aux_fun->driver_data = NULL; \ 95 ddf_fun_destroy(dev->aux_fun); \ 96 } \ 97 } \ 98 } while (0) 52 #define NAME "i8042" 99 53 100 54 void default_handler(ddf_fun_t *, ipc_callid_t, ipc_call_t *); … … 105 59 }; 106 60 61 /* Interesting bits for status register */ 62 #define i8042_OUTPUT_FULL 0x01 63 #define i8042_INPUT_FULL 0x02 64 #define i8042_AUX_DATA 0x20 65 66 /* Command constants */ 67 #define i8042_CMD_WRITE_CMDB 0x60 /**< write command byte */ 68 #define i8042_CMD_WRITE_AUX 0xd4 /**< write aux device */ 69 70 /* Command byte fields */ 71 #define i8042_KBD_IE 0x01 72 #define i8042_AUX_IE 0x02 73 #define i8042_KBD_DISABLE 0x10 74 #define i8042_AUX_DISABLE 0x20 75 #define i8042_KBD_TRANSLATE 0x40 /* Use this to switch to XT scancodes */ 76 107 77 /** i8042 Interrupt pseudo-code. */ 108 78 static const irq_cmd_t i8042_cmds[] = { 109 79 { 110 80 .cmd = CMD_PIO_READ_8, 111 .addr = NULL, /* will be patched in run-time */81 .addr = NULL, /* will be patched in run-time */ 112 82 .dstarg = 1 113 83 }, … … 125 95 { 126 96 .cmd = CMD_PIO_READ_8, 127 .addr = NULL, /* will be patched in run-time */97 .addr = NULL, /* will be patched in run-time */ 128 98 .dstarg = 2 129 99 }, … … 141 111 142 112 /** Interrupt handler routine. 143 * 144 * Write new data to the corresponding buffer. 145 * 146 * @param dev Device that caued the interrupt. 147 * @param iid Call id. 113 * Writes new data to the corresponding buffer. 114 * @param dev Device that caued the interrupt. 115 * @param iid Call id. 148 116 * @param call pointerr to call data. 149 * 150 */ 151 static void i8042_irq_handler(ddf_dev_t *dev, ipc_callid_t iid, 152 ipc_call_t *call) 153 { 154 if ((!dev) || (!dev->driver_data)) 117 */ 118 static void i8042_irq_handler( 119 ddf_dev_t *dev, ipc_callid_t iid, ipc_call_t *call) 120 { 121 if (!dev || !dev->driver_data) 155 122 return; 156 157 123 i8042_t *controller = dev->driver_data; 158 124 159 125 const uint8_t status = IPC_GET_ARG1(*call); 160 126 const uint8_t data = IPC_GET_ARG2(*call); 161 162 127 buffer_t *buffer = (status & i8042_AUX_DATA) ? 163 128 &controller->aux_buffer : &controller->kbd_buffer; 164 165 129 buffer_write(buffer, data); 166 130 } 167 131 168 132 /** Initialize i8042 driver structure. 169 * 170 * @param dev Driver structure to initialize. 171 * @param regs I/O address of registers. 172 * @param reg_size size of the reserved I/O address space. 173 * @param irq_kbd IRQ for primary port. 133 * @param dev Driver structure to initialize. 134 * @param regs I/O address of registers. 135 * @param reg_size size of the reserved I/O address space. 136 * @param irq_kbd IRQ for primary port. 174 137 * @param irq_mouse IRQ for aux port. 175 * @param ddf_dev DDF device structure of the device. 176 * 138 * @param ddf_dev DDF device structure of the device. 177 139 * @return Error code. 178 *179 140 */ 180 141 int i8042_init(i8042_t *dev, void *regs, size_t reg_size, int irq_kbd, … … 183 144 assert(ddf_dev); 184 145 assert(dev); 185 146 186 147 if (reg_size < sizeof(i8042_regs_t)) 187 148 return EINVAL; 188 189 if (pio_enable(regs, sizeof(i8042_regs_t), (void **)&dev->regs) != 0)149 150 if (pio_enable(regs, sizeof(i8042_regs_t), (void**)&dev->regs) != 0) 190 151 return -1; 191 152 192 153 dev->kbd_fun = ddf_fun_create(ddf_dev, fun_inner, "ps2a"); 193 154 if (!dev->kbd_fun) 194 155 return ENOMEM; 195 196 156 int ret = ddf_fun_add_match_id(dev->kbd_fun, "char/xtkbd", 90); 197 157 if (ret != EOK) { … … 199 159 return ret; 200 160 } 201 161 202 162 dev->aux_fun = ddf_fun_create(ddf_dev, fun_inner, "ps2b"); 203 163 if (!dev->aux_fun) { … … 205 165 return ENOMEM; 206 166 } 207 167 208 168 ret = ddf_fun_add_match_id(dev->aux_fun, "char/ps2mouse", 90); 209 169 if (ret != EOK) { … … 212 172 return ret; 213 173 } 214 174 215 175 dev->kbd_fun->ops = &ops; 216 176 dev->aux_fun->ops = &ops; 217 177 dev->kbd_fun->driver_data = dev; 218 178 dev->aux_fun->driver_data = dev; 219 179 220 180 buffer_init(&dev->kbd_buffer, dev->kbd_data, BUFFER_SIZE); 221 181 buffer_init(&dev->aux_buffer, dev->aux_data, BUFFER_SIZE); 222 182 fibril_mutex_initialize(&dev->write_guard); 223 183 184 #define CHECK_RET_DESTROY(ret, msg...) \ 185 if (ret != EOK) { \ 186 ddf_msg(LVL_ERROR, msg); \ 187 if (dev->kbd_fun) { \ 188 dev->kbd_fun->driver_data = NULL; \ 189 ddf_fun_destroy(dev->kbd_fun); \ 190 } \ 191 if (dev->aux_fun) { \ 192 dev->aux_fun->driver_data = NULL; \ 193 ddf_fun_destroy(dev->aux_fun); \ 194 } \ 195 } else (void)0 196 224 197 ret = ddf_fun_bind(dev->kbd_fun); 225 CHECK_RET_DESTROY(ret, "Failed to bind keyboard function: %s.",226 str_error(ret));227 198 CHECK_RET_DESTROY(ret, 199 "Failed to bind keyboard function: %s.", str_error(ret)); 200 228 201 ret = ddf_fun_bind(dev->aux_fun); 229 CHECK_RET_DESTROY(ret, "Failed to bind mouse function: %s.",230 str_error(ret));231 202 CHECK_RET_DESTROY(ret, 203 "Failed to bind mouse function: %s.", str_error(ret)); 204 232 205 /* Disable kbd and aux */ 233 206 wait_ready(dev); … … 235 208 wait_ready(dev); 236 209 pio_write_8(&dev->regs->data, i8042_KBD_DISABLE | i8042_AUX_DISABLE); 237 210 238 211 /* Flush all current IO */ 239 212 while (pio_read_8(&dev->regs->status) & i8042_OUTPUT_FULL) 240 213 (void) pio_read_8(&dev->regs->data); 241 214 215 #define CHECK_RET_UNBIND_DESTROY(ret, msg...) \ 216 if (ret != EOK) { \ 217 ddf_msg(LVL_ERROR, msg); \ 218 if (dev->kbd_fun) { \ 219 ddf_fun_unbind(dev->kbd_fun); \ 220 dev->kbd_fun->driver_data = NULL; \ 221 ddf_fun_destroy(dev->kbd_fun); \ 222 } \ 223 if (dev->aux_fun) { \ 224 ddf_fun_unbind(dev->aux_fun); \ 225 dev->aux_fun->driver_data = NULL; \ 226 ddf_fun_destroy(dev->aux_fun); \ 227 } \ 228 } else (void)0 229 242 230 const size_t cmd_count = sizeof(i8042_cmds) / sizeof(irq_cmd_t); 243 231 irq_cmd_t cmds[cmd_count]; … … 245 233 cmds[0].addr = (void *) &dev->regs->status; 246 234 cmds[3].addr = (void *) &dev->regs->data; 247 248 irq_code_t irq_code = { 249 .cmdcount = cmd_count, 250 .cmds = cmds 251 }; 252 235 236 irq_code_t irq_code = { .cmdcount = cmd_count, .cmds = cmds }; 253 237 ret = register_interrupt_handler(ddf_dev, irq_kbd, i8042_irq_handler, 254 238 &irq_code); 255 CHECK_RET_UNBIND_DESTROY(ret, "Failed set handler for kbd: %s.",256 str_error(ret));257 239 CHECK_RET_UNBIND_DESTROY(ret, 240 "Failed set handler for kbd: %s.", str_error(ret)); 241 258 242 ret = register_interrupt_handler(ddf_dev, irq_mouse, i8042_irq_handler, 259 243 &irq_code); 260 CHECK_RET_UNBIND_DESTROY(ret, "Failed set handler for mouse: %s.",261 str_error(ret));262 244 CHECK_RET_UNBIND_DESTROY(ret, 245 "Failed set handler for mouse: %s.", str_error(ret)); 246 263 247 /* Enable interrupts */ 264 248 async_sess_t *parent_sess = … … 267 251 ret = parent_sess ? EOK : ENOMEM; 268 252 CHECK_RET_UNBIND_DESTROY(ret, "Failed to create parent connection."); 269 253 270 254 const bool enabled = hw_res_enable_interrupt(parent_sess); 271 255 async_hangup(parent_sess); 272 256 ret = enabled ? EOK : EIO; 273 257 CHECK_RET_UNBIND_DESTROY(ret, "Failed to enable interrupts: %s."); 274 258 275 259 /* Enable port interrupts. */ 276 260 wait_ready(dev); … … 279 263 pio_write_8(&dev->regs->data, i8042_KBD_IE | i8042_KBD_TRANSLATE | 280 264 i8042_AUX_IE); 281 265 282 266 return EOK; 283 267 } 284 268 285 // FIXMETODO use shared instead this269 // TODO use shared instead this 286 270 enum { 287 271 IPC_CHAR_READ = DEV_FIRST_CUSTOM_METHOD, … … 290 274 291 275 /** Write data to i8042 port. 292 * 293 * @param fun DDF function. 276 * @param fun DDF function. 294 277 * @param buffer Data source. 295 * @param size Data size. 296 * 278 * @param size Data size. 297 279 * @return Bytes written. 298 *299 280 */ 300 281 static int i8042_write(ddf_fun_t *fun, char *buffer, size_t size) … … 302 283 assert(fun); 303 284 assert(fun->driver_data); 304 305 285 i8042_t *controller = fun->driver_data; 306 286 fibril_mutex_lock(&controller->write_guard); 307 308 287 for (size_t i = 0; i < size; ++i) { 309 288 wait_ready(controller); 310 311 289 if (controller->aux_fun == fun) 312 pio_write_8(&controller->regs->status, 313 i8042_CMD_WRITE_AUX); 314 290 pio_write_8( 291 &controller->regs->status, i8042_CMD_WRITE_AUX); 315 292 pio_write_8(&controller->regs->data, buffer[i]); 316 293 } 317 318 294 fibril_mutex_unlock(&controller->write_guard); 319 295 return size; … … 321 297 322 298 /** Read data from i8042 port. 323 * 324 * @param fun DDF function. 299 * @param fun DDF function. 325 300 * @param buffer Data place. 326 * @param size Data place size. 327 * 301 * @param size Data place size. 328 302 * @return Bytes read. 329 *330 303 */ 331 304 static int i8042_read(ddf_fun_t *fun, char *data, size_t size) … … 333 306 assert(fun); 334 307 assert(fun->driver_data); 335 308 336 309 i8042_t *controller = fun->driver_data; 337 310 buffer_t *buffer = (fun == controller->aux_fun) ? 338 311 &controller->aux_buffer : &controller->kbd_buffer; 339 340 for (size_t i = 0; i < size; ++i) 312 for (size_t i = 0; i < size; ++i) { 341 313 *data++ = buffer_read(buffer); 342 314 } 343 315 return size; 344 316 } 345 317 346 318 /** Handle data requests. 347 * 348 * @param fun ddf_fun_t function. 349 * @param id callid 319 * @param fun ddf_fun_t function. 320 * @param id callid 350 321 * @param call IPC request. 351 *352 322 */ 353 323 void default_handler(ddf_fun_t *fun, ipc_callid_t id, ipc_call_t *call) … … 355 325 const sysarg_t method = IPC_GET_IMETHOD(*call); 356 326 const size_t size = IPC_GET_ARG1(*call); 357 358 327 switch (method) { 359 328 case IPC_CHAR_READ: 360 329 if (size <= 4 * sizeof(sysarg_t)) { 361 330 sysarg_t message[4] = {}; 362 363 i8042_read(fun, (char *) message, size); 331 i8042_read(fun, (char*)message, size); 364 332 async_answer_4(id, size, message[0], message[1], 365 333 message[2], message[3]); 366 } else 334 } else { 367 335 async_answer_0(id, ELIMIT); 336 } 368 337 break; 369 338 370 339 case IPC_CHAR_WRITE: 371 340 if (size <= 3 * sizeof(sysarg_t)) { 372 341 const sysarg_t message[3] = { 373 IPC_GET_ARG2(*call), 374 IPC_GET_ARG3(*call), 375 IPC_GET_ARG4(*call) 376 }; 377 378 i8042_write(fun, (char *) message, size); 342 IPC_GET_ARG2(*call), IPC_GET_ARG3(*call), 343 IPC_GET_ARG4(*call) }; 344 i8042_write(fun, (char*)message, size); 379 345 async_answer_0(id, size); 380 } else 346 } else { 381 347 async_answer_0(id, ELIMIT); 382 348 } 349 383 350 default: 384 351 async_answer_0(id, EINVAL); 385 352 } 386 353 } 387 388 354 /** 389 355 * @} -
uspace/drv/char/i8042/i8042.h
r786bd56 r304faab 27 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 28 */ 29 30 29 /** @addtogroup kbd_port 31 30 * @ingroup kbd 32 31 * @{ 33 32 */ 34 35 33 /** @file 36 34 * @brief i8042 port driver. … … 43 41 #include <fibril_synch.h> 44 42 #include <ddf/driver.h> 43 45 44 #include "buffer.h" 46 45 47 #define NAME "i8042" 48 49 #define BUFFER_SIZE 12 46 #define BUFFER_SIZE 12 50 47 51 48 /** i8042 HW I/O interface */ … … 58 55 /** i8042 driver structure. */ 59 56 typedef struct i8042 { 60 i8042_regs_t *regs; /**< I/O registers. */61 ddf_fun_t *kbd_fun; /**< Pirmary port device function. */62 ddf_fun_t *aux_fun; /**< Auxiliary port device function. */63 buffer_t kbd_buffer; /**< Primary port buffer. */64 buffer_t aux_buffer; /**< Aux. port buffer. */57 i8042_regs_t *regs; /**< I/O registers. */ 58 ddf_fun_t *kbd_fun; /**< Pirmary port device function. */ 59 ddf_fun_t *aux_fun; /**< Auxiliary port device function. */ 60 buffer_t kbd_buffer; /**< Primary port buffer. */ 61 buffer_t aux_buffer; /**< Aux. port buffer. */ 65 62 uint8_t aux_data[BUFFER_SIZE]; /**< Primary port buffer space. */ 66 63 uint8_t kbd_data[BUFFER_SIZE]; /**< Aux. port buffer space. */ … … 69 66 70 67 int i8042_init(i8042_t *, void *, size_t, int, int, ddf_dev_t *); 71 72 68 #endif 73 74 69 /** 75 70 * @} -
uspace/drv/char/i8042/main.c
r786bd56 r304faab 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 29 28 /** @addtogroup drvi8042 30 29 * @{ 31 30 */ 32 33 31 /** @file 34 32 * @brief i8042 driver DDF bits. … … 43 41 #include <ddf/log.h> 44 42 #include <stdio.h> 43 45 44 #include "i8042.h" 46 45 47 #define CHECK_RET_RETURN(ret, message...) \ 48 do { \ 49 if (ret != EOK) { \ 50 ddf_msg(LVL_ERROR, message); \ 51 return ret; \ 52 } \ 53 } while (0) 46 #define NAME "i8042" 54 47 55 /** Get address of I/O registers. 56 * 57 * @param[in] dev Device asking for the addresses. 58 * @param[out] io_reg_address Base address of the memory range. 59 * @param[out] io_reg_size Size of the memory range. 60 * @param[out] kbd_irq Primary port IRQ. 61 * @param[out] mouse_irq Auxiliary port IRQ. 62 * 63 * @return Error code. 64 * 65 */ 66 static int get_my_registers(const ddf_dev_t *dev, uintptr_t *io_reg_address, 67 size_t *io_reg_size, int *kbd_irq, int *mouse_irq) 68 { 69 assert(dev); 70 71 async_sess_t *parent_sess = 72 devman_parent_device_connect(EXCHANGE_SERIALIZE, dev->handle, 73 IPC_FLAG_BLOCKING); 74 if (!parent_sess) 75 return ENOMEM; 76 77 hw_res_list_parsed_t hw_resources; 78 hw_res_list_parsed_init(&hw_resources); 79 const int ret = hw_res_get_list_parsed(parent_sess, &hw_resources, 0); 80 async_hangup(parent_sess); 81 if (ret != EOK) 82 return ret; 83 84 if ((hw_resources.irqs.count != 2) || 85 (hw_resources.io_ranges.count != 1)) { 86 hw_res_list_parsed_clean(&hw_resources); 87 return EINVAL; 88 } 89 90 if (io_reg_address) 91 *io_reg_address = hw_resources.io_ranges.ranges[0].address; 92 93 if (io_reg_size) 94 *io_reg_size = hw_resources.io_ranges.ranges[0].size; 95 96 if (kbd_irq) 97 *kbd_irq = hw_resources.irqs.irqs[0]; 98 99 if (mouse_irq) 100 *mouse_irq = hw_resources.irqs.irqs[1]; 101 102 hw_res_list_parsed_clean(&hw_resources); 103 return EOK; 104 } 105 106 /** Initialize a new ddf driver instance of i8042 driver 107 * 108 * @param[in] device DDF instance of the device to initialize. 109 * 110 * @return Error code. 111 * 112 */ 113 static int i8042_dev_add(ddf_dev_t *device) 114 { 115 if (!device) 116 return EINVAL; 117 118 uintptr_t io_regs = 0; 119 size_t io_size = 0; 120 int kbd = 0; 121 int mouse = 0; 122 123 int ret = get_my_registers(device, &io_regs, &io_size, &kbd, &mouse); 124 CHECK_RET_RETURN(ret, "Failed to get registers: %s.", 125 str_error(ret)); 126 ddf_msg(LVL_DEBUG, "I/O regs at %p (size %zuB), IRQ kbd %d, IRQ mouse %d.", 127 (void *) io_regs, io_size, kbd, mouse); 128 129 i8042_t *i8042 = ddf_dev_data_alloc(device, sizeof(i8042_t)); 130 ret = (i8042 == NULL) ? ENOMEM : EOK; 131 CHECK_RET_RETURN(ret, "Failed to allocate i8042 driver instance."); 132 133 ret = i8042_init(i8042, (void *) io_regs, io_size, kbd, mouse, device); 134 CHECK_RET_RETURN(ret, "Failed to initialize i8042 driver: %s.", 135 str_error(ret)); 136 137 ddf_msg(LVL_NOTE, "Controlling '%s' (%" PRIun ").", 138 device->name, device->handle); 139 return EOK; 140 } 48 static int get_my_registers(const ddf_dev_t *dev, 49 uintptr_t *io_reg_address, size_t *io_reg_size, int *kbd, int *mouse); 50 static int i8042_dev_add(ddf_dev_t *device); 141 51 142 52 /** DDF driver operations. */ … … 151 61 }; 152 62 63 /** Initialize global driver structures (NONE). 64 * 65 * @param[in] argc Nmber of arguments in argv vector (ignored). 66 * @param[in] argv Cmdline argument vector (ignored). 67 * @return Error code. 68 * 69 * Driver debug level is set here. 70 */ 153 71 int main(int argc, char *argv[]) 154 72 { 155 printf( "%s: HelenOS PS/2 driver.\n", NAME);73 printf(NAME ": HelenOS ps/2 driver.\n"); 156 74 ddf_log_init(NAME, LVL_NOTE); 157 75 return ddf_driver_main(&i8042_driver); 158 76 } 159 77 78 /** Initialize a new ddf driver instance of i8042 driver 79 * 80 * @param[in] device DDF instance of the device to initialize. 81 * @return Error code. 82 */ 83 static int i8042_dev_add(ddf_dev_t *device) 84 { 85 if (!device) 86 return EINVAL; 87 88 #define CHECK_RET_RETURN(ret, message...) \ 89 if (ret != EOK) { \ 90 ddf_msg(LVL_ERROR, message); \ 91 return ret; \ 92 } else (void)0 93 94 uintptr_t io_regs = 0; 95 size_t io_size = 0; 96 int kbd = 0, mouse = 0; 97 98 int ret = get_my_registers(device, &io_regs, &io_size, &kbd, &mouse); 99 CHECK_RET_RETURN(ret, 100 "Failed to get registers: %s.", str_error(ret)); 101 ddf_msg(LVL_DEBUG, 102 "I/O regs at %p (size %zuB), IRQ kbd %d, IRQ mouse %d.", 103 (void *) io_regs, io_size, kbd, mouse); 104 105 i8042_t *i8042 = ddf_dev_data_alloc(device, sizeof(i8042_t)); 106 ret = (i8042 == NULL) ? ENOMEM : EOK; 107 CHECK_RET_RETURN(ret, "Failed to allocate i8042 driver instance."); 108 109 ret = i8042_init(i8042, (void*)io_regs, io_size, kbd, mouse, device); 110 CHECK_RET_RETURN(ret, 111 "Failed to initialize i8042 driver: %s.", str_error(ret)); 112 113 ddf_msg(LVL_NOTE, "Controlling '%s' (%" PRIun ").", 114 device->name, device->handle); 115 return EOK; 116 } 117 118 /** Get address of I/O registers. 119 * 120 * @param[in] dev Device asking for the addresses. 121 * @param[out] io_reg_address Base address of the memory range. 122 * @param[out] io_reg_size Size of the memory range. 123 * @param[out] kbd_irq Primary port IRQ. 124 * @param[out] mouse_irq Auxiliary port IRQ. 125 * @return Error code. 126 */ 127 int get_my_registers(const ddf_dev_t *dev, uintptr_t *io_reg_address, 128 size_t *io_reg_size, int *kbd_irq, int *mouse_irq) 129 { 130 assert(dev); 131 132 async_sess_t *parent_sess = 133 devman_parent_device_connect(EXCHANGE_SERIALIZE, dev->handle, 134 IPC_FLAG_BLOCKING); 135 if (!parent_sess) 136 return ENOMEM; 137 138 hw_res_list_parsed_t hw_resources; 139 hw_res_list_parsed_init(&hw_resources); 140 const int ret = hw_res_get_list_parsed(parent_sess, &hw_resources, 0); 141 async_hangup(parent_sess); 142 if (ret != EOK) { 143 return ret; 144 } 145 146 if (hw_resources.irqs.count != 2 || hw_resources.io_ranges.count != 1) { 147 hw_res_list_parsed_clean(&hw_resources); 148 return EINVAL; 149 } 150 151 if (io_reg_address) 152 *io_reg_address = hw_resources.io_ranges.ranges[0].address; 153 154 if (io_reg_size) 155 *io_reg_size = hw_resources.io_ranges.ranges[0].size; 156 157 if (kbd_irq) 158 *kbd_irq = hw_resources.irqs.irqs[0]; 159 160 if (mouse_irq) 161 *mouse_irq = hw_resources.irqs.irqs[1]; 162 163 hw_res_list_parsed_clean(&hw_resources); 164 return EOK; 165 } 160 166 /** 161 167 * @} -
uspace/lib/c/generic/loc.c
r786bd56 r304faab 47 47 static FIBRIL_MUTEX_INITIALIZE(loc_callback_mutex); 48 48 static bool loc_callback_created = false; 49 static loc_cat_change_cb_t cat_change_cb = NULL;50 49 51 50 static async_sess_t *loc_supp_block_sess = NULL; … … 55 54 static async_sess_t *loc_consumer_sess = NULL; 56 55 56 static loc_cat_change_cb_t cat_change_cb = NULL; 57 57 58 static void loc_cb_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg) 58 59 { 60 loc_cat_change_cb_t cb_fun; 61 59 62 while (true) { 60 63 ipc_call_t call; … … 66 69 } 67 70 71 int retval; 72 68 73 switch (IPC_GET_IMETHOD(call)) { 69 74 case LOC_EVENT_CAT_CHANGE: 70 75 fibril_mutex_lock(&loc_callback_mutex); 71 loc_cat_change_cb_t cb_fun = cat_change_cb; 76 cb_fun = cat_change_cb; 77 if (cb_fun != NULL) { 78 (*cb_fun)(); 79 } 72 80 fibril_mutex_unlock(&loc_callback_mutex); 73 74 async_answer_0(callid, EOK); 75 76 if (cb_fun != NULL) 77 (*cb_fun)(); 78 81 retval = 0; 79 82 break; 80 83 default: 81 async_answer_0(callid, ENOTSUP);84 retval = ENOTSUP; 82 85 } 86 87 async_answer_0(callid, retval); 83 88 } 84 89 } … … 96 101 } 97 102 98 /** Create callback99 *100 * Must be called with loc_callback_mutex locked.101 *102 * @return EOK on success.103 *104 */105 103 static int loc_callback_create(void) 106 104 { 105 async_exch_t *exch; 106 sysarg_t retval; 107 int rc = EOK; 108 109 fibril_mutex_lock(&loc_callback_mutex); 110 107 111 if (!loc_callback_created) { 108 async_exch_t *exch = 109 loc_exchange_begin_blocking(LOC_PORT_CONSUMER); 112 exch = loc_exchange_begin_blocking(LOC_PORT_CONSUMER); 110 113 111 114 ipc_call_t answer; 112 115 aid_t req = async_send_0(exch, LOC_CALLBACK_CREATE, &answer); 113 int rc =async_connect_to_me(exch, 0, 0, 0, loc_cb_conn, NULL);116 async_connect_to_me(exch, 0, 0, 0, loc_cb_conn, NULL); 114 117 loc_exchange_end(exch); 115 118 119 async_wait_for(req, &retval); 116 120 if (rc != EOK) 117 return rc;118 119 sysarg_t retval;120 async_wait_for(req, &retval);121 if (retval != EOK)122 return retval;121 goto done; 122 123 if (retval != EOK) { 124 rc = retval; 125 goto done; 126 } 123 127 124 128 loc_callback_created = true; 125 129 } 126 130 127 return EOK; 131 rc = EOK; 132 done: 133 fibril_mutex_unlock(&loc_callback_mutex); 134 return rc; 128 135 } 129 136 … … 788 795 sysarg_t **data, size_t *count) 789 796 { 797 service_id_t *ids; 798 size_t act_size; 799 size_t alloc_size; 800 int rc; 801 790 802 *data = NULL; 791 *count = 0; 792 793 size_t act_size = 0; 794 int rc = loc_category_get_ids_once(method, arg1, NULL, 0, 803 act_size = 0; /* silence warning */ 804 805 rc = loc_category_get_ids_once(method, arg1, NULL, 0, 795 806 &act_size); 796 807 if (rc != EOK) 797 808 return rc; 798 799 size_talloc_size = act_size;800 service_id_t *ids = malloc(alloc_size);809 810 alloc_size = act_size; 811 ids = malloc(alloc_size); 801 812 if (ids == NULL) 802 813 return ENOMEM; 803 814 804 815 while (true) { 805 816 rc = loc_category_get_ids_once(method, arg1, ids, alloc_size, … … 807 818 if (rc != EOK) 808 819 return rc; 809 820 810 821 if (act_size <= alloc_size) 811 822 break; 812 813 alloc_size = act_size; 814 ids = realloc(ids, alloc_size); 823 824 alloc_size *= 2; 825 free(ids); 826 827 ids = malloc(alloc_size); 815 828 if (ids == NULL) 816 829 return ENOMEM; 817 830 } 818 831 819 832 *count = act_size / sizeof(category_id_t); 820 833 *data = ids; … … 854 867 int loc_register_cat_change_cb(loc_cat_change_cb_t cb_fun) 855 868 { 856 fibril_mutex_lock(&loc_callback_mutex); 857 if (loc_callback_create() != EOK) { 858 fibril_mutex_unlock(&loc_callback_mutex); 869 if (loc_callback_create() != EOK) 859 870 return EIO; 860 } 861 871 862 872 cat_change_cb = cb_fun; 863 fibril_mutex_unlock(&loc_callback_mutex);864 865 873 return EOK; 866 874 }
Note:
See TracChangeset
for help on using the changeset viewer.
