Changeset a35b458 in mainline for uspace/drv/char
- Timestamp:
- 2018-03-02T20:10:49Z (8 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- f1380b7
- Parents:
- 3061bc1
- git-author:
- Jiří Zárevúcky <zarevucky.jiri@…> (2018-02-28 17:38:31)
- git-committer:
- Jiří Zárevúcky <zarevucky.jiri@…> (2018-03-02 20:10:49)
- Location:
- uspace/drv/char
- Files:
-
- 4 edited
-
i8042/i8042.c (modified) (19 diffs)
-
i8042/main.c (modified) (8 diffs)
-
ns8250/cyclic_buffer.h (modified) (1 diff)
-
ns8250/ns8250.c (modified) (45 diffs)
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/char/i8042/i8042.c
r3061bc1 ra35b458 130 130 i8042_t *controller = ddf_dev_data_get(dev); 131 131 errno_t rc; 132 132 133 133 const uint8_t status = IPC_GET_ARG1(*call); 134 134 const uint8_t data = IPC_GET_ARG2(*call); 135 135 136 136 i8042_port_t *port = (status & i8042_AUX_DATA) ? 137 137 controller->aux : controller->kbd; 138 138 139 139 fibril_mutex_lock(&port->buf_lock); 140 140 141 141 rc = circ_buf_push(&port->cbuf, &data); 142 142 if (rc != EOK) … … 169 169 ddf_fun_t *aux_fun; 170 170 i8042_regs_t *ar; 171 171 172 172 errno_t rc; 173 173 bool kbd_bound = false; 174 174 bool aux_bound = false; 175 175 176 176 if (regs->size < sizeof(i8042_regs_t)) { 177 177 rc = EINVAL; 178 178 goto error; 179 179 } 180 180 181 181 if (pio_enable_range(regs, (void **) &dev->regs) != 0) { 182 182 rc = EIO; 183 183 goto error; 184 184 } 185 185 186 186 kbd_fun = ddf_fun_create(ddf_dev, fun_inner, "ps2a"); 187 187 if (kbd_fun == NULL) { … … 189 189 goto error; 190 190 }; 191 191 192 192 dev->kbd = ddf_fun_data_alloc(kbd_fun, sizeof(i8042_port_t)); 193 193 if (dev->kbd == NULL) { … … 195 195 goto error; 196 196 } 197 197 198 198 dev->kbd->fun = kbd_fun; 199 199 dev->kbd->ctl = dev; … … 203 203 fibril_mutex_initialize(&dev->kbd->buf_lock); 204 204 fibril_condvar_initialize(&dev->kbd->buf_cv); 205 205 206 206 rc = ddf_fun_add_match_id(dev->kbd->fun, "char/xtkbd", 90); 207 207 if (rc != EOK) 208 208 goto error; 209 209 210 210 aux_fun = ddf_fun_create(ddf_dev, fun_inner, "ps2b"); 211 211 if (aux_fun == NULL) { … … 213 213 goto error; 214 214 } 215 215 216 216 dev->aux = ddf_fun_data_alloc(aux_fun, sizeof(i8042_port_t)); 217 217 if (dev->aux == NULL) { … … 219 219 goto error; 220 220 } 221 221 222 222 dev->aux->fun = aux_fun; 223 223 dev->aux->ctl = dev; … … 227 227 fibril_mutex_initialize(&dev->aux->buf_lock); 228 228 fibril_condvar_initialize(&dev->aux->buf_cv); 229 229 230 230 rc = ddf_fun_add_match_id(dev->aux->fun, "char/ps2mouse", 90); 231 231 if (rc != EOK) 232 232 goto error; 233 233 234 234 ddf_fun_set_conn_handler(dev->kbd->fun, i8042_char_conn); 235 235 ddf_fun_set_conn_handler(dev->aux->fun, i8042_char_conn); 236 236 237 237 circ_buf_init(&dev->kbd->cbuf, dev->kbd->buf_data, BUFFER_SIZE, 1); 238 238 circ_buf_init(&dev->aux->cbuf, dev->aux->buf_data, BUFFER_SIZE, 1); 239 239 fibril_mutex_initialize(&dev->write_guard); 240 240 241 241 rc = ddf_fun_bind(dev->kbd->fun); 242 242 if (rc != EOK) { … … 246 246 } 247 247 kbd_bound = true; 248 248 249 249 rc = ddf_fun_bind(dev->aux->fun); 250 250 if (rc != EOK) { … … 254 254 } 255 255 aux_bound = true; 256 256 257 257 /* Disable kbd and aux */ 258 258 wait_ready(dev); … … 260 260 wait_ready(dev); 261 261 pio_write_8(&dev->regs->data, i8042_KBD_DISABLE | i8042_AUX_DISABLE); 262 262 263 263 /* Flush all current IO */ 264 264 while (pio_read_8(&dev->regs->status) & i8042_OUTPUT_FULL) … … 280 280 .cmds = cmds 281 281 }; 282 282 283 283 int irq_kbd_cap; 284 284 rc = register_interrupt_handler(ddf_dev, irq_kbd, … … 289 289 goto error; 290 290 } 291 291 292 292 int irq_mouse_cap; 293 293 rc = register_interrupt_handler(ddf_dev, irq_mouse, … … 298 298 goto error; 299 299 } 300 300 301 301 /* Enable interrupts */ 302 302 async_sess_t *parent_sess = ddf_dev_parent_sess_get(ddf_dev); 303 303 assert(parent_sess != NULL); 304 304 305 305 rc = hw_res_enable_interrupt(parent_sess, irq_kbd); 306 306 if (rc != EOK) { … … 318 318 goto error; 319 319 } 320 320 321 321 /* Enable port interrupts. */ 322 322 wait_ready(dev); … … 325 325 pio_write_8(&dev->regs->data, i8042_KBD_IE | i8042_KBD_TRANSLATE | 326 326 i8042_AUX_IE); 327 327 328 328 return EOK; 329 329 error: … … 356 356 i8042_t *i8042 = port->ctl; 357 357 const char *dp = (const char *)data; 358 358 359 359 fibril_mutex_lock(&i8042->write_guard); 360 360 361 361 for (size_t i = 0; i < size; ++i) { 362 362 if (port == i8042->aux) { … … 365 365 i8042_CMD_WRITE_AUX); 366 366 } 367 367 368 368 wait_ready(i8042); 369 369 pio_write_8(&i8042->regs->data, dp[i]); 370 370 } 371 371 372 372 fibril_mutex_unlock(&i8042->write_guard); 373 373 *nwr = size; … … 392 392 uint8_t *destp = (uint8_t *)dest; 393 393 errno_t rc; 394 394 395 395 fibril_mutex_lock(&port->buf_lock); 396 396 397 397 while (circ_buf_nused(&port->cbuf) == 0) 398 398 fibril_condvar_wait(&port->buf_cv, &port->buf_lock); -
uspace/drv/char/i8042/main.c
r3061bc1 ra35b458 59 59 { 60 60 assert(dev); 61 61 62 62 async_sess_t *parent_sess = ddf_dev_parent_sess_get(dev); 63 63 if (parent_sess == NULL) 64 64 return ENOMEM; 65 65 66 66 hw_res_list_parsed_t hw_resources; 67 67 hw_res_list_parsed_init(&hw_resources); … … 69 69 if (ret != EOK) 70 70 return ret; 71 71 72 72 if ((hw_resources.irqs.count != 2) || 73 73 (hw_resources.io_ranges.count != 1)) { … … 75 75 return EINVAL; 76 76 } 77 77 78 78 if (p_io_reg) 79 79 *p_io_reg = hw_resources.io_ranges.ranges[0]; 80 80 81 81 if (kbd_irq) 82 82 *kbd_irq = hw_resources.irqs.irqs[0]; 83 83 84 84 if (mouse_irq) 85 85 *mouse_irq = hw_resources.irqs.irqs[1]; 86 86 87 87 hw_res_list_parsed_clean(&hw_resources); 88 88 return EOK; … … 102 102 int mouse = 0; 103 103 errno_t rc; 104 104 105 105 if (!device) 106 106 return EINVAL; 107 107 108 108 rc = get_my_registers(device, &io_regs, &kbd, &mouse); 109 109 if (rc != EOK) { … … 112 112 return rc; 113 113 } 114 114 115 115 ddf_msg(LVL_DEBUG, 116 116 "I/O regs at %p (size %zuB), IRQ kbd %d, IRQ mouse %d.", 117 117 RNGABSPTR(io_regs), RNGSZ(io_regs), kbd, mouse); 118 118 119 119 i8042_t *i8042 = ddf_dev_data_alloc(device, sizeof(i8042_t)); 120 120 if (i8042 == NULL) { … … 122 122 return ENOMEM; 123 123 } 124 124 125 125 rc = i8042_init(i8042, &io_regs, kbd, mouse, device); 126 126 if (rc != EOK) { … … 129 129 return rc; 130 130 } 131 131 132 132 ddf_msg(LVL_NOTE, "Controlling '%s' (%" PRIun ").", 133 133 ddf_dev_get_name(device), ddf_dev_get_handle(device)); … … 150 150 printf("%s: HelenOS PS/2 driver.\n", NAME); 151 151 ddf_log_init(NAME); 152 152 153 153 return ddf_driver_main(&i8042_driver); 154 154 } -
uspace/drv/char/ns8250/cyclic_buffer.h
r3061bc1 ra35b458 65 65 { 66 66 assert(!buf_is_empty(buf)); 67 67 68 68 uint8_t res = buf->buf[buf->start]; 69 69 buf->start = (buf->start + 1) % BUF_LEN; -
uspace/drv/char/ns8250/ns8250.c
r3061bc1 ra35b458 238 238 while (!is_transmit_empty(regs)) 239 239 ; 240 240 241 241 pio_write_8(®s->data, c); 242 242 } … … 256 256 char *bp = (char *) buf; 257 257 size_t pos = 0; 258 258 259 259 if (count == 0) { 260 260 *nread = 0; 261 261 return EOK; 262 262 } 263 263 264 264 fibril_mutex_lock(&ns->mutex); 265 265 while (buf_is_empty(&ns->input_buffer)) … … 270 270 } 271 271 fibril_mutex_unlock(&ns->mutex); 272 272 273 273 *nread = pos; 274 274 return EOK; … … 301 301 size_t idx; 302 302 uint8_t *bp = (uint8_t *) buf; 303 303 304 304 for (idx = 0; idx < count; idx++) 305 305 ns8250_putchar(ns, bp[idx]); 306 306 307 307 *nwritten = count; 308 308 return EOK; … … 355 355 { 356 356 ddf_msg(LVL_DEBUG, "ns8250_pio_enable %s", ddf_dev_get_name(ns->dev)); 357 357 358 358 /* Gain control over port's registers. */ 359 359 if (pio_enable((void *) ns->io_addr, REG_COUNT, … … 365 365 366 366 ns->regs = (ns8250_regs_t *)ns->port; 367 367 368 368 return true; 369 369 } … … 377 377 { 378 378 ddf_msg(LVL_DEBUG, "ns8250_dev_probe %s", ddf_dev_get_name(ns->dev)); 379 379 380 380 bool res = true; 381 381 uint8_t olddata; 382 382 383 383 olddata = pio_read_8(&ns->regs->mcr); 384 384 385 385 pio_write_8(&ns->regs->mcr, NS8250_MCR_LOOPBACK); 386 386 if (pio_read_8(&ns->regs->msr) & NS8250_MSR_SIGNALS) 387 387 res = false; 388 388 389 389 pio_write_8(&ns->regs->mcr, NS8250_MCR_ALL); 390 390 if ((pio_read_8(&ns->regs->msr) & NS8250_MSR_SIGNALS) 391 391 != NS8250_MSR_SIGNALS) 392 392 res = false; 393 393 394 394 pio_write_8(&ns->regs->mcr, olddata); 395 395 396 396 if (!res) { 397 397 ddf_msg(LVL_DEBUG, "Device %s is not present.", 398 398 ddf_dev_get_name(ns->dev)); 399 399 } 400 400 401 401 return res; 402 402 } … … 410 410 { 411 411 errno_t ret = EOK; 412 412 413 413 ddf_msg(LVL_DEBUG, "ns8250_dev_initialize %s", ddf_dev_get_name(ns->dev)); 414 414 415 415 hw_resource_list_t hw_resources; 416 416 memset(&hw_resources, 0, sizeof(hw_resource_list_t)); 417 417 418 418 /* Get hw resources. */ 419 419 ret = hw_res_get_resource_list(ns->parent_sess, &hw_resources); … … 423 423 goto failed; 424 424 } 425 425 426 426 size_t i; 427 427 hw_resource_t *res; 428 428 bool irq = false; 429 429 bool ioport = false; 430 430 431 431 for (i = 0; i < hw_resources.count; i++) { 432 432 res = &hw_resources.resources[i]; … … 438 438 ddf_dev_get_name(ns->dev), ns->irq); 439 439 break; 440 440 441 441 case IO_RANGE: 442 442 ns->io_addr = res->res.io_range.address; … … 451 451 "0x%#" PRIxn ".", ddf_dev_get_name(ns->dev), ns->io_addr); 452 452 break; 453 453 454 454 default: 455 455 break; 456 456 } 457 457 } 458 458 459 459 if (!irq || !ioport) { 460 460 ddf_msg(LVL_ERROR, "Missing HW resource(s) for device %s.", … … 463 463 goto failed; 464 464 } 465 465 466 466 hw_res_clean_resource_list(&hw_resources); 467 467 return ret; 468 468 469 469 failed: 470 470 ns8250_dev_cleanup(ns); … … 507 507 if (rc != EOK) 508 508 return EIO; 509 509 510 510 /* Read LSR to clear possible previous LSR interrupt */ 511 511 pio_read_8(&ns->regs->lsr); 512 512 513 513 /* Enable interrupt on the serial port. */ 514 514 ns8250_port_interrupts_enable(ns->regs); 515 515 516 516 return EOK; 517 517 } … … 551 551 uint16_t divisor; 552 552 uint8_t div_low, div_high; 553 553 554 554 if (baud_rate < 50 || MAX_BAUD_RATE % baud_rate != 0) { 555 555 ddf_msg(LVL_ERROR, "Invalid baud rate %d requested.", … … 557 557 return EINVAL; 558 558 } 559 559 560 560 divisor = MAX_BAUD_RATE / baud_rate; 561 561 div_low = (uint8_t)divisor; 562 562 div_high = (uint8_t)(divisor >> 8); 563 563 564 564 /* Enable DLAB to be able to access baud rate divisor. */ 565 565 enable_dlab(regs); 566 566 567 567 /* Set divisor low byte. */ 568 568 pio_write_8(®s->data, div_low); 569 569 /* Set divisor high byte. */ 570 570 pio_write_8(®s->ier, div_high); 571 571 572 572 clear_dlab(regs); 573 573 574 574 return EOK; 575 575 } … … 584 584 uint16_t divisor; 585 585 uint8_t div_low, div_high; 586 586 587 587 /* Enable DLAB to be able to access baud rate divisor. */ 588 588 enable_dlab(regs); 589 589 590 590 /* Get divisor low byte. */ 591 591 div_low = pio_read_8(®s->data); 592 592 /* Get divisor high byte. */ 593 593 div_high = pio_read_8(®s->ier); 594 594 595 595 clear_dlab(regs); 596 596 597 597 divisor = (div_high << 8) | div_low; 598 598 return MAX_BAUD_RATE / divisor; … … 610 610 { 611 611 uint8_t val; 612 612 613 613 val = pio_read_8(®s->lcr); 614 614 *parity = ((val >> NS8250_LCR_PARITY) & 7); 615 615 616 616 /* Silence warnings */ 617 617 *word_length = 0; … … 631 631 break; 632 632 } 633 633 634 634 if ((val >> NS8250_LCR_STOPBITS) & 1) 635 635 *stop_bits = 2; … … 650 650 { 651 651 uint8_t val; 652 652 653 653 switch (word_length) { 654 654 case 5: … … 667 667 return EINVAL; 668 668 } 669 669 670 670 switch (stop_bits) { 671 671 case 1: … … 678 678 return EINVAL; 679 679 } 680 680 681 681 switch (parity) { 682 682 case SERIAL_NO_PARITY: … … 690 690 return EINVAL; 691 691 } 692 692 693 693 pio_write_8(®s->lcr, val); 694 694 695 695 return EOK; 696 696 } … … 748 748 ns8250_regs_t *regs = ns->regs; 749 749 bool cont = true; 750 750 751 751 fibril_mutex_lock(&ns->mutex); 752 752 while (cont) { … … 754 754 if (cont) { 755 755 uint8_t val = ns8250_read_8(regs); 756 756 757 757 if (ns->client_connections > 0) { 758 758 bool buf_was_empty = buf_is_empty(&ns->input_buffer); … … 794 794 } 795 795 } 796 796 797 797 ns8250_read_from_device(ns); 798 798 hw_res_clear_interrupt(ns->parent_sess, ns->irq); … … 832 832 bool need_unreg_intr_handler = false; 833 833 errno_t rc; 834 834 835 835 ddf_msg(LVL_DEBUG, "ns8250_dev_add %s (handle = %d)", 836 836 ddf_dev_get_name(dev), (int) ddf_dev_get_handle(dev)); 837 837 838 838 /* Allocate soft-state for the device */ 839 839 ns = ddf_dev_data_alloc(dev, sizeof(ns8250_t)); … … 842 842 goto fail; 843 843 } 844 844 845 845 fibril_mutex_initialize(&ns->mutex); 846 846 fibril_condvar_initialize(&ns->input_buffer_available); 847 847 ns->dev = dev; 848 848 849 849 ns->parent_sess = ddf_dev_parent_sess_get(ns->dev); 850 850 if (ns->parent_sess == NULL) { … … 854 854 goto fail; 855 855 } 856 856 857 857 rc = ns8250_dev_initialize(ns); 858 858 if (rc != EOK) 859 859 goto fail; 860 860 861 861 need_cleanup = true; 862 862 863 863 if (!ns8250_pio_enable(ns)) { 864 864 rc = EADDRNOTAVAIL; 865 865 goto fail; 866 866 } 867 867 868 868 /* Find out whether the device is present. */ 869 869 if (!ns8250_dev_probe(ns)) { … … 871 871 goto fail; 872 872 } 873 873 874 874 /* Serial port initialization (baud rate etc.). */ 875 875 ns8250_initialize_port(ns); 876 876 877 877 /* Register interrupt handler. */ 878 878 rc = ns8250_register_interrupt_handler(ns, &ns->irq_cap); … … 891 891 goto fail; 892 892 } 893 893 894 894 fun = ddf_fun_create(dev, fun_exposed, "a"); 895 895 if (fun == NULL) { … … 897 897 goto fail; 898 898 } 899 899 900 900 ddf_fun_set_conn_handler(fun, ns8250_char_conn); 901 901 902 902 chardev_srvs_init(&ns->cds); 903 903 ns->cds.ops = &ns8250_chardev_ops; 904 904 ns->cds.sarg = ns; 905 905 906 906 rc = ddf_fun_bind(fun); 907 907 if (rc != EOK) { … … 911 911 912 912 ns->fun = fun; 913 913 914 914 ddf_fun_add_to_category(fun, "serial"); 915 915 916 916 ddf_msg(LVL_NOTE, "Device %s successfully initialized.", 917 917 ddf_dev_get_name(dev)); 918 918 919 919 return EOK; 920 920 fail: … … 932 932 ns8250_t *ns = dev_ns8250(dev); 933 933 errno_t rc; 934 934 935 935 fibril_mutex_lock(&ns->mutex); 936 936 if (ns->client_connections > 0) { … … 940 940 ns->removed = true; 941 941 fibril_mutex_unlock(&ns->mutex); 942 942 943 943 rc = ddf_fun_unbind(ns->fun); 944 944 if (rc != EOK) { … … 946 946 return rc; 947 947 } 948 948 949 949 ddf_fun_destroy(ns->fun); 950 950 951 951 ns8250_port_cleanup(ns); 952 952 ns8250_unregister_interrupt_handler(ns); … … 967 967 ns8250_t *ns = srv_ns8250(srv); 968 968 errno_t res; 969 969 970 970 fibril_mutex_lock(&ns->mutex); 971 971 if (ns->removed) { … … 976 976 } 977 977 fibril_mutex_unlock(&ns->mutex); 978 978 979 979 return res; 980 980 } … … 990 990 { 991 991 ns8250_t *data = srv_ns8250(srv); 992 992 993 993 fibril_mutex_lock(&data->mutex); 994 994 995 995 assert(data->client_connections > 0); 996 996 997 997 if (!(--data->client_connections)) 998 998 buf_clear(&data->input_buffer); 999 999 1000 1000 fibril_mutex_unlock(&data->mutex); 1001 1001 1002 1002 return EOK; 1003 1003 } … … 1018 1018 ns8250_t *data = dev_ns8250(dev); 1019 1019 ns8250_regs_t *regs = data->regs; 1020 1020 1021 1021 fibril_mutex_lock(&data->mutex); 1022 1022 ns8250_port_interrupts_disable(regs); … … 1025 1025 ns8250_port_interrupts_enable(regs); 1026 1026 fibril_mutex_unlock(&data->mutex); 1027 1027 1028 1028 ddf_msg(LVL_DEBUG, "ns8250_get_props: baud rate %d, parity 0x%x, word " 1029 1029 "length %d, stop bits %d", *baud_rate, *parity, *word_length, … … 1046 1046 "length %d, stop bits %d", baud_rate, parity, word_length, 1047 1047 stop_bits); 1048 1048 1049 1049 ns8250_t *data = dev_ns8250(dev); 1050 1050 ns8250_regs_t *regs = data->regs; 1051 1051 errno_t ret; 1052 1052 1053 1053 fibril_mutex_lock(&data->mutex); 1054 1054 ns8250_port_interrupts_disable(regs); … … 1058 1058 ns8250_port_interrupts_enable(regs); 1059 1059 fibril_mutex_unlock(&data->mutex); 1060 1060 1061 1061 return ret; 1062 1062 } … … 1074 1074 errno_t ret; 1075 1075 unsigned int baud_rate, parity, word_length, stop_bits; 1076 1076 1077 1077 switch (method) { 1078 1078 case SERIAL_GET_COM_PROPS: … … 1082 1082 stop_bits); 1083 1083 break; 1084 1084 1085 1085 case SERIAL_SET_COM_PROPS: 1086 1086 baud_rate = IPC_GET_ARG1(*call); … … 1092 1092 async_answer_0(callid, ret); 1093 1093 break; 1094 1094 1095 1095 default: 1096 1096 async_answer_0(callid, ENOTSUP);
Note:
See TracChangeset
for help on using the changeset viewer.
