Changeset 2df6f6fe in mainline
- Timestamp:
- 2012-01-23T18:24:10Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 786bd56, 876f6463, 948911d
- Parents:
- 88dfee7
- Location:
- uspace/drv
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/pci/pciintel/pci.c
r88dfee7 r2df6f6fe 92 92 static bool pciintel_enable_interrupt(ddf_fun_t *fnode) 93 93 { 94 /* This is an old ugly way , copied from ne2000 driver*/94 /* This is an old ugly way */ 95 95 assert(fnode); 96 96 pci_fun_t *dev_data = (pci_fun_t *) fnode->driver_data; -
uspace/drv/char/i8042/buffer.h
r88dfee7 r2df6f6fe 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 28 29 /** 29 30 * @addtogroup kbd 30 31 * @{ 31 32 */ 33 32 34 /** @file 33 35 * @brief Cyclic buffer structure. … … 46 48 * Attempt to insert byte into the full buffer will block until it can succeed. 47 49 * Attempt to read from empty buffer will block until it can succeed. 50 * 48 51 */ 49 52 typedef struct { 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. */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. */ 56 59 } buffer_t; 57 60 58 61 /** Initialize cyclic buffer using provided memory space. 62 * 59 63 * @param buffer Cyclic buffer structure to initialize. 60 * @param data Memory space to use. 61 * @param size Size of the memory place. 64 * @param data Memory space to use. 65 * @param size Size of the memory place. 66 * 62 67 */ 63 68 static inline void buffer_init(buffer_t *buffer, uint8_t *data, size_t size) 64 69 { 65 70 assert(buffer); 71 66 72 fibril_mutex_initialize(&buffer->guard); 67 73 fibril_condvar_initialize(&buffer->change); … … 74 80 75 81 /** Write byte to cyclic buffer. 82 * 76 83 * @param buffer Cyclic buffer to write to. 77 * @param data Data to write. 84 * @param data Data to write. 85 * 78 86 */ 79 87 static inline void buffer_write(buffer_t *buffer, uint8_t data) 80 88 { 81 89 fibril_mutex_lock(&buffer->guard); 82 90 83 91 /* Next position. */ 84 92 uint8_t *new_head = buffer->write_head + 1; 85 93 if (new_head == buffer->buffer_end) 86 94 new_head = buffer->buffer; 87 95 88 96 /* Buffer full. */ 89 97 while (new_head == buffer->read_head) 90 98 fibril_condvar_wait(&buffer->change, &buffer->guard); 91 99 92 100 /* Write data. */ 93 101 *buffer->write_head = data; 94 102 95 103 /* Buffer was empty. */ 96 104 if (buffer->write_head == buffer->read_head) 97 105 fibril_condvar_broadcast(&buffer->change); 98 106 99 107 /* Move head */ 100 108 buffer->write_head = new_head; … … 103 111 104 112 /** Read byte from cyclic buffer. 113 * 105 114 * @param buffer Cyclic buffer to read from. 115 * 106 116 * @return Byte read. 117 * 107 118 */ 108 119 static inline uint8_t buffer_read(buffer_t *buffer) 109 120 { 110 121 fibril_mutex_lock(&buffer->guard); 122 111 123 /* Buffer is empty. */ 112 124 while (buffer->write_head == buffer->read_head) 113 125 fibril_condvar_wait(&buffer->change, &buffer->guard); 114 126 115 127 /* Next position. */ 116 128 uint8_t *new_head = buffer->read_head + 1; 117 129 if (new_head == buffer->buffer_end) 118 130 new_head = buffer->buffer; 119 131 120 132 /* Read data. */ 121 133 const uint8_t data = *buffer->read_head; 122 134 123 135 /* Buffer was full. */ 124 136 uint8_t *new_write_head = buffer->write_head + 1; … … 127 139 if (new_write_head == buffer->read_head) 128 140 fibril_condvar_broadcast(&buffer->change); 129 141 130 142 /* Move head */ 131 143 buffer->read_head = new_head; 132 144 133 145 fibril_mutex_unlock(&buffer->guard); 134 146 return data; 135 147 } 148 136 149 #endif 150 137 151 /** 138 152 * @} -
uspace/drv/char/i8042/i8042.c
r88dfee7 r2df6f6fe 29 29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 30 */ 31 31 32 /** @addtogroup kbd_port 32 33 * @ingroup kbd 33 34 * @{ 34 35 */ 36 35 37 /** @file 36 38 * @brief i8042 PS/2 port driver. … … 44 46 #include <str_error.h> 45 47 #include <inttypes.h> 46 47 48 #include <ddf/log.h> 48 49 #include <ddf/interrupt.h> 49 50 50 #include "i8042.h" 51 51 52 #define NAME "i8042" 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) 53 99 54 100 void default_handler(ddf_fun_t *, ipc_callid_t, ipc_call_t *); … … 59 105 }; 60 106 61 /* Interesting bits for status register */62 #define i8042_OUTPUT_FULL 0x0163 #define i8042_INPUT_FULL 0x0264 #define i8042_AUX_DATA 0x2065 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 0x0172 #define i8042_AUX_IE 0x0273 #define i8042_KBD_DISABLE 0x1074 #define i8042_AUX_DISABLE 0x2075 #define i8042_KBD_TRANSLATE 0x40 /* Use this to switch to XT scancodes */76 77 107 /** i8042 Interrupt pseudo-code. */ 78 108 static const irq_cmd_t i8042_cmds[] = { 79 109 { 80 110 .cmd = CMD_PIO_READ_8, 81 .addr = NULL, 111 .addr = NULL, /* will be patched in run-time */ 82 112 .dstarg = 1 83 113 }, … … 95 125 { 96 126 .cmd = CMD_PIO_READ_8, 97 .addr = NULL, 127 .addr = NULL, /* will be patched in run-time */ 98 128 .dstarg = 2 99 129 }, … … 111 141 112 142 /** Interrupt handler routine. 113 * Writes new data to the corresponding buffer. 114 * @param dev Device that caued the interrupt. 115 * @param iid Call id. 143 * 144 * Write new data to the corresponding buffer. 145 * 146 * @param dev Device that caued the interrupt. 147 * @param iid Call id. 116 148 * @param call pointerr to call 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) 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)) 122 155 return; 156 123 157 i8042_t *controller = dev->driver_data; 124 158 125 159 const uint8_t status = IPC_GET_ARG1(*call); 126 160 const uint8_t data = IPC_GET_ARG2(*call); 161 127 162 buffer_t *buffer = (status & i8042_AUX_DATA) ? 128 163 &controller->aux_buffer : &controller->kbd_buffer; 164 129 165 buffer_write(buffer, data); 130 166 } 131 167 132 168 /** Initialize i8042 driver structure. 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. 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. 137 174 * @param irq_mouse IRQ for aux port. 138 * @param ddf_dev DDF device structure of the device. 175 * @param ddf_dev DDF device structure of the device. 176 * 139 177 * @return Error code. 178 * 140 179 */ 141 180 int i8042_init(i8042_t *dev, void *regs, size_t reg_size, int irq_kbd, … … 144 183 assert(ddf_dev); 145 184 assert(dev); 146 185 147 186 if (reg_size < sizeof(i8042_regs_t)) 148 187 return EINVAL; 149 150 if (pio_enable(regs, sizeof(i8042_regs_t), (void **)&dev->regs) != 0)188 189 if (pio_enable(regs, sizeof(i8042_regs_t), (void **) &dev->regs) != 0) 151 190 return -1; 152 191 153 192 dev->kbd_fun = ddf_fun_create(ddf_dev, fun_inner, "ps2a"); 154 193 if (!dev->kbd_fun) 155 194 return ENOMEM; 195 156 196 int ret = ddf_fun_add_match_id(dev->kbd_fun, "char/xtkbd", 90); 157 197 if (ret != EOK) { … … 159 199 return ret; 160 200 } 161 201 162 202 dev->aux_fun = ddf_fun_create(ddf_dev, fun_inner, "ps2b"); 163 203 if (!dev->aux_fun) { … … 165 205 return ENOMEM; 166 206 } 167 207 168 208 ret = ddf_fun_add_match_id(dev->aux_fun, "char/ps2mouse", 90); 169 209 if (ret != EOK) { … … 172 212 return ret; 173 213 } 174 214 175 215 dev->kbd_fun->ops = &ops; 176 216 dev->aux_fun->ops = &ops; 177 217 dev->kbd_fun->driver_data = dev; 178 218 dev->aux_fun->driver_data = dev; 179 219 180 220 buffer_init(&dev->kbd_buffer, dev->kbd_data, BUFFER_SIZE); 181 221 buffer_init(&dev->aux_buffer, dev->aux_data, BUFFER_SIZE); 182 222 fibril_mutex_initialize(&dev->write_guard); 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 223 197 224 ret = ddf_fun_bind(dev->kbd_fun); 198 CHECK_RET_DESTROY(ret, 199 "Failed to bind keyboard function: %s.",str_error(ret));200 225 CHECK_RET_DESTROY(ret, "Failed to bind keyboard function: %s.", 226 str_error(ret)); 227 201 228 ret = ddf_fun_bind(dev->aux_fun); 202 CHECK_RET_DESTROY(ret, 203 "Failed to bind mouse function: %s.",str_error(ret));204 229 CHECK_RET_DESTROY(ret, "Failed to bind mouse function: %s.", 230 str_error(ret)); 231 205 232 /* Disable kbd and aux */ 206 233 wait_ready(dev); … … 208 235 wait_ready(dev); 209 236 pio_write_8(&dev->regs->data, i8042_KBD_DISABLE | i8042_AUX_DISABLE); 210 237 211 238 /* Flush all current IO */ 212 239 while (pio_read_8(&dev->regs->status) & i8042_OUTPUT_FULL) 213 240 (void) pio_read_8(&dev->regs->data); 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 241 230 242 const size_t cmd_count = sizeof(i8042_cmds) / sizeof(irq_cmd_t); 231 243 irq_cmd_t cmds[cmd_count]; … … 233 245 cmds[0].addr = (void *) &dev->regs->status; 234 246 cmds[3].addr = (void *) &dev->regs->data; 235 236 irq_code_t irq_code = { .cmdcount = cmd_count, .cmds = cmds }; 247 248 irq_code_t irq_code = { 249 .cmdcount = cmd_count, 250 .cmds = cmds 251 }; 252 237 253 ret = register_interrupt_handler(ddf_dev, irq_kbd, i8042_irq_handler, 238 254 &irq_code); 239 CHECK_RET_UNBIND_DESTROY(ret, 240 "Failed set handler for kbd: %s.",str_error(ret));241 255 CHECK_RET_UNBIND_DESTROY(ret, "Failed set handler for kbd: %s.", 256 str_error(ret)); 257 242 258 ret = register_interrupt_handler(ddf_dev, irq_mouse, i8042_irq_handler, 243 259 &irq_code); 244 CHECK_RET_UNBIND_DESTROY(ret, 245 "Failed set handler for mouse: %s.",str_error(ret));246 260 CHECK_RET_UNBIND_DESTROY(ret, "Failed set handler for mouse: %s.", 261 str_error(ret)); 262 247 263 /* Enable interrupts */ 248 264 async_sess_t *parent_sess = … … 251 267 ret = parent_sess ? EOK : ENOMEM; 252 268 CHECK_RET_UNBIND_DESTROY(ret, "Failed to create parent connection."); 253 269 254 270 const bool enabled = hw_res_enable_interrupt(parent_sess); 255 271 async_hangup(parent_sess); 256 272 ret = enabled ? EOK : EIO; 257 273 CHECK_RET_UNBIND_DESTROY(ret, "Failed to enable interrupts: %s."); 258 274 259 275 /* Enable port interrupts. */ 260 276 wait_ready(dev); … … 263 279 pio_write_8(&dev->regs->data, i8042_KBD_IE | i8042_KBD_TRANSLATE | 264 280 i8042_AUX_IE); 265 281 266 282 return EOK; 267 283 } 268 284 269 // TODO use shared instead this285 // FIXME TODO use shared instead this 270 286 enum { 271 287 IPC_CHAR_READ = DEV_FIRST_CUSTOM_METHOD, … … 274 290 275 291 /** Write data to i8042 port. 276 * @param fun DDF function. 292 * 293 * @param fun DDF function. 277 294 * @param buffer Data source. 278 * @param size Data size. 295 * @param size Data size. 296 * 279 297 * @return Bytes written. 298 * 280 299 */ 281 300 static int i8042_write(ddf_fun_t *fun, char *buffer, size_t size) … … 283 302 assert(fun); 284 303 assert(fun->driver_data); 304 285 305 i8042_t *controller = fun->driver_data; 286 306 fibril_mutex_lock(&controller->write_guard); 307 287 308 for (size_t i = 0; i < size; ++i) { 288 309 wait_ready(controller); 310 289 311 if (controller->aux_fun == fun) 290 pio_write_8( 291 &controller->regs->status, i8042_CMD_WRITE_AUX); 312 pio_write_8(&controller->regs->status, 313 i8042_CMD_WRITE_AUX); 314 292 315 pio_write_8(&controller->regs->data, buffer[i]); 293 316 } 317 294 318 fibril_mutex_unlock(&controller->write_guard); 295 319 return size; … … 297 321 298 322 /** Read data from i8042 port. 299 * @param fun DDF function. 323 * 324 * @param fun DDF function. 300 325 * @param buffer Data place. 301 * @param size Data place size. 326 * @param size Data place size. 327 * 302 328 * @return Bytes read. 329 * 303 330 */ 304 331 static int i8042_read(ddf_fun_t *fun, char *data, size_t size) … … 306 333 assert(fun); 307 334 assert(fun->driver_data); 308 335 309 336 i8042_t *controller = fun->driver_data; 310 337 buffer_t *buffer = (fun == controller->aux_fun) ? 311 338 &controller->aux_buffer : &controller->kbd_buffer; 312 for (size_t i = 0; i < size; ++i) { 339 340 for (size_t i = 0; i < size; ++i) 313 341 *data++ = buffer_read(buffer); 314 }342 315 343 return size; 316 344 } 317 345 318 346 /** Handle data requests. 319 * @param fun ddf_fun_t function. 320 * @param id callid 347 * 348 * @param fun ddf_fun_t function. 349 * @param id callid 321 350 * @param call IPC request. 351 * 322 352 */ 323 353 void default_handler(ddf_fun_t *fun, ipc_callid_t id, ipc_call_t *call) … … 325 355 const sysarg_t method = IPC_GET_IMETHOD(*call); 326 356 const size_t size = IPC_GET_ARG1(*call); 357 327 358 switch (method) { 328 359 case IPC_CHAR_READ: 329 360 if (size <= 4 * sizeof(sysarg_t)) { 330 361 sysarg_t message[4] = {}; 331 i8042_read(fun, (char*)message, size); 362 363 i8042_read(fun, (char *) message, size); 332 364 async_answer_4(id, size, message[0], message[1], 333 365 message[2], message[3]); 334 } else {366 } else 335 367 async_answer_0(id, ELIMIT); 336 }337 368 break; 338 369 339 370 case IPC_CHAR_WRITE: 340 371 if (size <= 3 * sizeof(sysarg_t)) { 341 372 const sysarg_t message[3] = { 342 IPC_GET_ARG2(*call), IPC_GET_ARG3(*call), 343 IPC_GET_ARG4(*call) }; 344 i8042_write(fun, (char*)message, size); 373 IPC_GET_ARG2(*call), 374 IPC_GET_ARG3(*call), 375 IPC_GET_ARG4(*call) 376 }; 377 378 i8042_write(fun, (char *) message, size); 345 379 async_answer_0(id, size); 346 } else {380 } else 347 381 async_answer_0(id, ELIMIT); 348 } 349 382 350 383 default: 351 384 async_answer_0(id, EINVAL); 352 385 } 353 386 } 387 354 388 /** 355 389 * @} -
uspace/drv/char/i8042/i8042.h
r88dfee7 r2df6f6fe 27 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 28 */ 29 29 30 /** @addtogroup kbd_port 30 31 * @ingroup kbd 31 32 * @{ 32 33 */ 34 33 35 /** @file 34 36 * @brief i8042 port driver. … … 41 43 #include <fibril_synch.h> 42 44 #include <ddf/driver.h> 43 44 45 #include "buffer.h" 45 46 46 #define BUFFER_SIZE 12 47 #define NAME "i8042" 48 49 #define BUFFER_SIZE 12 47 50 48 51 /** i8042 HW I/O interface */ … … 55 58 /** i8042 driver structure. */ 56 59 typedef struct i8042 { 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. */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. */ 62 65 uint8_t aux_data[BUFFER_SIZE]; /**< Primary port buffer space. */ 63 66 uint8_t kbd_data[BUFFER_SIZE]; /**< Aux. port buffer space. */ … … 66 69 67 70 int i8042_init(i8042_t *, void *, size_t, int, int, ddf_dev_t *); 71 68 72 #endif 73 69 74 /** 70 75 * @} -
uspace/drv/char/i8042/main.c
r88dfee7 r2df6f6fe 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 28 29 /** @addtogroup drvi8042 29 30 * @{ 30 31 */ 32 31 33 /** @file 32 34 * @brief i8042 driver DDF bits. … … 41 43 #include <ddf/log.h> 42 44 #include <stdio.h> 43 44 45 #include "i8042.h" 45 46 46 #define NAME "i8042" 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) 47 54 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); 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 } 51 141 52 142 /** DDF driver operations. */ … … 61 151 }; 62 152 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 */71 153 int main(int argc, char *argv[]) 72 154 { 73 printf( NAME ": HelenOS ps/2 driver.\n");155 printf("%s: HelenOS PS/2 driver.\n", NAME); 74 156 ddf_log_init(NAME, LVL_NOTE); 75 157 return ddf_driver_main(&i8042_driver); 76 158 } 77 159 78 /** Initialize a new ddf driver instance of i8042 driver79 *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)093 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 }166 160 /** 167 161 * @}
Note:
See TracChangeset
for help on using the changeset viewer.