Changes in uspace/drv/char/ns8250/ns8250.c [4510e06:c7235d40] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/char/ns8250/ns8250.c
r4510e06 rc7235d40 40 40 #include <stdio.h> 41 41 #include <errno.h> 42 #include < stdbool.h>42 #include <bool.h> 43 43 #include <fibril_synch.h> 44 44 #include <stdlib.h> … … 51 51 #include <sys/stat.h> 52 52 #include <ddi.h> 53 #include <libarch/ddi.h> 53 54 54 55 #include <ddf/driver.h> … … 57 58 #include <ops/char_dev.h> 58 59 60 #include <devman.h> 59 61 #include <ns.h> 62 #include <ipc/devman.h> 60 63 #include <ipc/services.h> 61 64 #include <ipc/irc.h> … … 79 82 /** Interrupt ID Register definition. */ 80 83 #define NS8250_IID_ACTIVE (1 << 0) 81 #define NS8250_IID_CAUSE_MASK 0x0e82 #define NS8250_IID_CAUSE_RXSTATUS 0x0683 84 84 85 /** FIFO Control Register definition. */ … … 125 126 | NS8250_MSR_RI | NS8250_MSR_DCD) 126 127 128 /** Obtain soft-state structure from function node */ 129 #define NS8250(fnode) ((ns8250_t *) ((fnode)->dev->driver_data)) 130 131 /** Obtain soft-state structure from device node */ 132 #define NS8250_FROM_DEV(dnode) ((ns8250_t *) ((dnode)->driver_data)) 133 127 134 /** The number of bits of one data unit send by the serial port. */ 128 135 typedef enum { … … 160 167 /** I/O registers **/ 161 168 ns8250_regs_t *regs; 162 /** Are there any clients connected to the device? */163 unsigned client_connections;169 /** Is there any client conntected to the device? */ 170 bool client_connected; 164 171 /** The irq assigned to this device. */ 165 172 int irq; … … 168 175 /** The i/o port used to access the serial ports registers. */ 169 176 ioport8_t *port; 170 /** The buffer for incom ing data. */177 /** The buffer for incomming data. */ 171 178 cyclic_buffer_t input_buffer; 172 179 /** The fibril mutex for synchronizing the access to the device. */ 173 180 fibril_mutex_t mutex; 174 /** Indicates that some data has become available */175 fibril_condvar_t input_buffer_available;176 181 /** True if device is removed. */ 177 182 bool removed; 178 183 } ns8250_t; 179 184 180 /** Obtain soft-state structure from device node */ 181 static ns8250_t *dev_ns8250(ddf_dev_t *dev) 182 { 183 return ddf_dev_data_get(dev); 184 } 185 186 /** Obtain soft-state structure from function node */ 187 static ns8250_t *fun_ns8250(ddf_fun_t *fun) 188 { 189 return dev_ns8250(ddf_fun_get_dev(fun)); 190 } 191 192 /** Find out if there is some incoming data available on the serial port. 185 /** Find out if there is some incomming data available on the serial port. 193 186 * 194 187 * @param port The base address of the serial port device's ports. … … 244 237 static int ns8250_read(ddf_fun_t *fun, char *buf, size_t count) 245 238 { 246 ns8250_t *ns = fun_ns8250(fun); 247 int ret = 0; 248 249 if (count == 0) return 0; 239 ns8250_t *ns = NS8250(fun); 240 int ret = EOK; 250 241 251 242 fibril_mutex_lock(&ns->mutex); 252 while (buf_is_empty(&ns->input_buffer))253 fibril_condvar_wait(&ns->input_buffer_available, &ns->mutex);254 243 while (!buf_is_empty(&ns->input_buffer) && (size_t)ret < count) { 255 244 buf[ret] = (char)buf_pop_front(&ns->input_buffer); … … 282 271 static int ns8250_write(ddf_fun_t *fun, char *buf, size_t count) 283 272 { 284 ns8250_t *ns = fun_ns8250(fun);273 ns8250_t *ns = NS8250(fun); 285 274 size_t idx; 286 275 … … 320 309 static void ns8250_dev_cleanup(ns8250_t *ns) 321 310 { 311 if (ns->dev->parent_sess) { 312 async_hangup(ns->dev->parent_sess); 313 ns->dev->parent_sess = NULL; 314 } 322 315 } 323 316 … … 329 322 static bool ns8250_pio_enable(ns8250_t *ns) 330 323 { 331 ddf_msg(LVL_DEBUG, "ns8250_pio_enable %s", ddf_dev_get_name(ns->dev));324 ddf_msg(LVL_DEBUG, "ns8250_pio_enable %s", ns->dev->name); 332 325 333 326 /* Gain control over port's registers. */ … … 335 328 (void **) &ns->port)) { 336 329 ddf_msg(LVL_ERROR, "Cannot map the port %#" PRIx32 337 " for device %s.", ns->io_addr, ddf_dev_get_name(ns->dev));330 " for device %s.", ns->io_addr, ns->dev->name); 338 331 return false; 339 332 } … … 351 344 static bool ns8250_dev_probe(ns8250_t *ns) 352 345 { 353 ddf_msg(LVL_DEBUG, "ns8250_dev_probe %s", ddf_dev_get_name(ns->dev));346 ddf_msg(LVL_DEBUG, "ns8250_dev_probe %s", ns->dev->name); 354 347 355 348 bool res = true; … … 371 364 if (!res) { 372 365 ddf_msg(LVL_DEBUG, "Device %s is not present.", 373 ddf_dev_get_name(ns->dev));366 ns->dev->name); 374 367 } 375 368 … … 384 377 static int ns8250_dev_initialize(ns8250_t *ns) 385 378 { 386 async_sess_t *parent_sess; 379 ddf_msg(LVL_DEBUG, "ns8250_dev_initialize %s", ns->dev->name); 380 387 381 int ret = EOK; 388 389 ddf_msg(LVL_DEBUG, "ns8250_dev_initialize %s", ddf_dev_get_name(ns->dev));390 382 391 383 hw_resource_list_t hw_resources; … … 393 385 394 386 /* Connect to the parent's driver. */ 395 parent_sess = ddf_dev_parent_sess_create(ns->dev, EXCHANGE_SERIALIZE); 396 if (parent_sess == NULL) { 387 ns->dev->parent_sess = devman_parent_device_connect(EXCHANGE_SERIALIZE, 388 ns->dev->handle, IPC_FLAG_BLOCKING); 389 if (!ns->dev->parent_sess) { 397 390 ddf_msg(LVL_ERROR, "Failed to connect to parent driver of " 398 "device %s.", ddf_dev_get_name(ns->dev));391 "device %s.", ns->dev->name); 399 392 ret = ENOENT; 400 393 goto failed; … … 402 395 403 396 /* Get hw resources. */ 404 ret = hw_res_get_resource_list( parent_sess, &hw_resources);397 ret = hw_res_get_resource_list(ns->dev->parent_sess, &hw_resources); 405 398 if (ret != EOK) { 406 399 ddf_msg(LVL_ERROR, "Failed to get HW resources for device " 407 "%s.", ddf_dev_get_name(ns->dev));400 "%s.", ns->dev->name); 408 401 goto failed; 409 402 } … … 421 414 irq = true; 422 415 ddf_msg(LVL_NOTE, "Device %s was asigned irq = 0x%x.", 423 ddf_dev_get_name(ns->dev), ns->irq);416 ns->dev->name, ns->irq); 424 417 break; 425 418 … … 428 421 if (res->res.io_range.size < REG_COUNT) { 429 422 ddf_msg(LVL_ERROR, "I/O range assigned to " 430 "device %s is too small.", ddf_dev_get_name(ns->dev));423 "device %s is too small.", ns->dev->name); 431 424 ret = ELIMIT; 432 425 goto failed; … … 434 427 ioport = true; 435 428 ddf_msg(LVL_NOTE, "Device %s was asigned I/O address = " 436 "0x%x.", ddf_dev_get_name(ns->dev), ns->io_addr);429 "0x%x.", ns->dev->name, ns->io_addr); 437 430 break; 438 431 … … 444 437 if (!irq || !ioport) { 445 438 ddf_msg(LVL_ERROR, "Missing HW resource(s) for device %s.", 446 ddf_dev_get_name(ns->dev));439 ns->dev->name); 447 440 ret = ENOENT; 448 441 goto failed; … … 467 460 { 468 461 /* Interrupt when data received. */ 469 pio_write_8(®s->ier, NS8250_IER_RXREADY | NS8250_IER_RXSTATUS);462 pio_write_8(®s->ier, NS8250_IER_RXREADY); 470 463 pio_write_8(®s->mcr, NS8250_MCR_DTR | NS8250_MCR_RTS 471 464 | NS8250_MCR_OUT2); … … 506 499 async_exchange_end(exch); 507 500 508 /* Read LSR to clear possible previous LSR interrupt */509 pio_read_8(&ns->regs->lsr);510 511 501 /* Enable interrupt on the serial port. */ 512 502 ns8250_port_interrupts_enable(ns->regs); … … 612 602 *parity = ((val >> NS8250_LCR_PARITY) & 7); 613 603 614 /* Silence warnings */615 *word_length = 0;616 617 604 switch (val & 3) { 618 605 case WORD_LENGTH_5: … … 708 695 /* 8 bits, no parity, two stop bits. */ 709 696 ns8250_port_set_com_props(ns->regs, SERIAL_NO_PARITY, 8, 2); 710 /* 711 * Enable FIFO, clear them, with 4-byte threshold for greater 712 * reliability. 713 */ 697 /* Enable FIFO, clear them, with 14-byte threshold. */ 714 698 pio_write_8(&ns->regs->iid, NS8250_FCR_FIFOENABLE 715 | NS8250_FCR_RXFIFORESET | NS8250_FCR_TXFIFORESET 716 | NS8250_FCR_RXTRIGGERLOW );699 | NS8250_FCR_RXFIFORESET | NS8250_FCR_TXFIFORESET 700 | NS8250_FCR_RXTRIGGERLOW | NS8250_FCR_RXTRIGGERHI); 717 701 /* 718 702 * RTS/DSR set (Request to Send and Data Terminal Ready lines enabled), … … 747 731 bool cont = true; 748 732 749 fibril_mutex_lock(&ns->mutex);750 733 while (cont) { 734 fibril_mutex_lock(&ns->mutex); 735 751 736 cont = ns8250_received(regs); 752 737 if (cont) { 753 738 uint8_t val = ns8250_read_8(regs); 754 739 755 if (ns->client_connections > 0) { 756 bool buf_was_empty = buf_is_empty(&ns->input_buffer); 740 if (ns->client_connected) { 757 741 if (!buf_push_back(&ns->input_buffer, val)) { 758 742 ddf_msg(LVL_WARN, "Buffer overflow on " 759 "%s.", ddf_dev_get_name(ns->dev)); 760 break; 743 "%s.", ns->dev->name); 761 744 } else { 762 745 ddf_msg(LVL_DEBUG2, "Character %c saved " 763 746 "to the buffer of %s.", 764 val, ddf_dev_get_name(ns->dev)); 765 if (buf_was_empty) 766 fibril_condvar_broadcast(&ns->input_buffer_available); 747 val, ns->dev->name); 767 748 } 768 749 } 769 750 } 770 } 771 fibril_mutex_unlock(&ns->mutex); 772 fibril_yield(); 751 752 fibril_mutex_unlock(&ns->mutex); 753 fibril_yield(); 754 } 773 755 } 774 756 775 757 /** The interrupt handler. 776 758 * 777 * The serial port is initialized to interrupt when some data come or line 778 * status register changes, so the interrupt is handled by reading the incoming 779 * data and reading the line status register. 759 * The serial port is initialized to interrupt when some data come, so the 760 * interrupt is handled by reading the incomming data. 780 761 * 781 762 * @param dev The serial port device. … … 784 765 ipc_call_t *icall) 785 766 { 786 ns8250_t *ns = dev_ns8250(dev); 787 788 uint8_t iir = pio_read_8(&ns->regs->iid); 789 if ((iir & NS8250_IID_CAUSE_MASK) == NS8250_IID_CAUSE_RXSTATUS) { 790 uint8_t lsr = pio_read_8(&ns->regs->lsr); 791 if (lsr & NS8250_LSR_OE) { 792 ddf_msg(LVL_WARN, "Overrun error on %s", ddf_dev_get_name(ns->dev)); 793 } 794 } 795 796 ns8250_read_from_device(ns); 767 ns8250_read_from_device(NS8250_FROM_DEV(dev)); 797 768 } 798 769 … … 830 801 831 802 ddf_msg(LVL_DEBUG, "ns8250_dev_add %s (handle = %d)", 832 d df_dev_get_name(dev), (int) ddf_dev_get_handle(dev));803 dev->name, (int) dev->handle); 833 804 834 805 /* Allocate soft-state for the device */ … … 840 811 841 812 fibril_mutex_initialize(&ns->mutex); 842 fibril_condvar_initialize(&ns->input_buffer_available);843 813 ns->dev = dev; 844 814 … … 885 855 886 856 /* Set device operations. */ 887 ddf_fun_set_ops(fun, &ns8250_dev_ops);857 fun->ops = &ns8250_dev_ops; 888 858 rc = ddf_fun_bind(fun); 889 859 if (rc != EOK) { … … 897 867 898 868 ddf_msg(LVL_NOTE, "Device %s successfully initialized.", 899 d df_dev_get_name(dev));869 dev->name); 900 870 901 871 return EOK; … … 910 880 static int ns8250_dev_remove(ddf_dev_t *dev) 911 881 { 912 ns8250_t *ns = dev_ns8250(dev);882 ns8250_t *ns = NS8250_FROM_DEV(dev); 913 883 int rc; 914 884 915 885 fibril_mutex_lock(&ns->mutex); 916 if (ns->client_connections > 0) {886 if (ns->client_connected) { 917 887 fibril_mutex_unlock(&ns->mutex); 918 888 return EBUSY; … … 944 914 static int ns8250_open(ddf_fun_t *fun) 945 915 { 946 ns8250_t *ns = fun_ns8250(fun);916 ns8250_t *ns = NS8250(fun); 947 917 int res; 948 918 949 919 fibril_mutex_lock(&ns->mutex); 950 if (ns->removed) { 920 if (ns->client_connected) { 921 res = ELIMIT; 922 } else if (ns->removed) { 951 923 res = ENXIO; 952 924 } else { 953 925 res = EOK; 954 ns->client_connect ions++;926 ns->client_connected = true; 955 927 } 956 928 fibril_mutex_unlock(&ns->mutex); … … 968 940 static void ns8250_close(ddf_fun_t *fun) 969 941 { 970 ns8250_t *data = fun_ns8250(fun);942 ns8250_t *data = (ns8250_t *) fun->dev->driver_data; 971 943 972 944 fibril_mutex_lock(&data->mutex); 973 945 974 assert(data->client_connect ions > 0);975 976 if (!(--data->client_connections))977 946 assert(data->client_connected); 947 948 data->client_connected = false; 949 buf_clear(&data->input_buffer); 978 950 979 951 fibril_mutex_unlock(&data->mutex); … … 993 965 unsigned int *word_length, unsigned int* stop_bits) 994 966 { 995 ns8250_t *data = dev_ns8250(dev);967 ns8250_t *data = (ns8250_t *) dev->driver_data; 996 968 ns8250_regs_t *regs = data->regs; 997 969 … … 1024 996 stop_bits); 1025 997 1026 ns8250_t *data = dev_ns8250(dev);998 ns8250_t *data = (ns8250_t *) dev->driver_data; 1027 999 ns8250_regs_t *regs = data->regs; 1028 1000 int ret; … … 1053 1025 switch (method) { 1054 1026 case SERIAL_GET_COM_PROPS: 1055 ns8250_get_props( ddf_fun_get_dev(fun), &baud_rate, &parity, &word_length,1027 ns8250_get_props(fun->dev, &baud_rate, &parity, &word_length, 1056 1028 &stop_bits); 1057 1029 async_answer_4(callid, EOK, baud_rate, parity, word_length, … … 1064 1036 word_length = IPC_GET_ARG3(*call); 1065 1037 stop_bits = IPC_GET_ARG4(*call); 1066 ret = ns8250_set_props( ddf_fun_get_dev(fun), baud_rate, parity, word_length,1038 ret = ns8250_set_props(fun->dev, baud_rate, parity, word_length, 1067 1039 stop_bits); 1068 1040 async_answer_0(callid, ret); … … 1081 1053 static void ns8250_init(void) 1082 1054 { 1083 ddf_log_init(NAME );1055 ddf_log_init(NAME, LVL_ERROR); 1084 1056 1085 1057 ns8250_dev_ops.open = &ns8250_open;
Note:
See TracChangeset
for help on using the changeset viewer.