Changeset adf4f13 in mainline
- Timestamp:
- 2012-04-05T19:59:53Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- f3676f3c
- Parents:
- 3e2952b (diff), c7235d40 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/char/ns8250/ns8250.c
r3e2952b radf4f13 74 74 #define DLAB_MASK (1 << 7) 75 75 76 /** Interrupt Enable Register definition. */ 77 #define NS8250_IER_RXREADY (1 << 0) 78 #define NS8250_IER_THRE (1 << 1) 79 #define NS8250_IER_RXSTATUS (1 << 2) 80 #define NS8250_IER_MODEM_STATUS (1 << 3) 81 82 /** Interrupt ID Register definition. */ 83 #define NS8250_IID_ACTIVE (1 << 0) 84 85 /** FIFO Control Register definition. */ 86 #define NS8250_FCR_FIFOENABLE (1 << 0) 87 #define NS8250_FCR_RXFIFORESET (1 << 1) 88 #define NS8250_FCR_TXFIFORESET (1 << 2) 89 #define NS8250_FCR_DMAMODE (1 << 3) 90 #define NS8250_FCR_RXTRIGGERLOW (1 << 6) 91 #define NS8250_FCR_RXTRIGGERHI (1 << 7) 92 93 /** Line Control Register definition. */ 94 #define NS8250_LCR_STOPBITS (1 << 2) 95 #define NS8250_LCR_PARITY (1 << 3) 96 #define NS8250_LCR_SENDBREAK (1 << 6) 97 #define NS8250_LCR_DLAB (1 << 7) 98 99 /** Modem Control Register definition. */ 100 #define NS8250_MCR_DTR (1 << 0) 101 #define NS8250_MCR_RTS (1 << 1) 102 #define NS8250_MCR_OUT1 (1 << 2) 103 #define NS8250_MCR_OUT2 (1 << 3) 104 #define NS8250_MCR_LOOPBACK (1 << 4) 105 #define NS8250_MCR_ALL (0x1f) 106 107 /** Line Status Register definition. */ 108 #define NS8250_LSR_RXREADY (1 << 0) 109 #define NS8250_LSR_OE (1 << 1) 110 #define NS8250_LSR_PE (1 << 2) 111 #define NS8250_LSR_FE (1 << 3) 112 #define NS8250_LSR_BREAK (1 << 4) 113 #define NS8250_LSR_THRE (1 << 5) 114 #define NS8250_LSR_TSE (1 << 6) 115 116 /** Modem Status Register definition. */ 117 #define NS8250_MSR_DELTACTS (1 << 0) 118 #define NS8250_MSR_DELTADSR (1 << 1) 119 #define NS8250_MSR_RITRAILING (1 << 2) 120 #define NS8250_MSR_DELTADCD (1 << 3) 121 #define NS8250_MSR_CTS (1 << 4) 122 #define NS8250_MSR_DSR (1 << 5) 123 #define NS8250_MSR_RI (1 << 6) 124 #define NS8250_MSR_DCD (1 << 7) 125 #define NS8250_MSR_SIGNALS (NS8250_MSR_CTS | NS8250_MSR_DSR \ 126 | NS8250_MSR_RI | NS8250_MSR_DCD) 127 76 128 /** Obtain soft-state structure from function node */ 77 129 #define NS8250(fnode) ((ns8250_t *) ((fnode)->dev->driver_data)) … … 96 148 } stop_bit_t; 97 149 150 /** 8250 UART registers layout. */ 151 typedef struct { 152 ioport8_t data; /**< Data register. */ 153 ioport8_t ier; /**< Interrupt Enable Reg. */ 154 ioport8_t iid; /**< Interrupt ID Reg. */ 155 ioport8_t lcr; /**< Line Control Reg. */ 156 ioport8_t mcr; /**< Modem Control Reg. */ 157 ioport8_t lsr; /**< Line Status Reg. */ 158 ioport8_t msr; /**< Modem Status Reg. */ 159 } ns8250_regs_t; 160 98 161 /** The driver data for the serial port devices. */ 99 162 typedef struct ns8250 { … … 102 165 /** DDF function node */ 103 166 ddf_fun_t *fun; 167 /** I/O registers **/ 168 ns8250_regs_t *regs; 104 169 /** Is there any client conntected to the device? */ 105 170 bool client_connected; … … 124 189 * otherwise. 125 190 */ 126 static bool ns8250_received( ioport8_t *port)127 { 128 return (pio_read_8( port + 5) & 1) != 0;191 static bool ns8250_received(ns8250_regs_t *regs) 192 { 193 return (pio_read_8(®s->lsr) & NS8250_LSR_RXREADY) != 0; 129 194 } 130 195 … … 134 199 * @return The data read. 135 200 */ 136 static uint8_t ns8250_read_8( ioport8_t *port)137 { 138 return pio_read_8( port);201 static uint8_t ns8250_read_8(ns8250_regs_t *regs) 202 { 203 return pio_read_8(®s->data); 139 204 } 140 205 … … 143 208 * @param port The base address of the serial port device's ports. 144 209 */ 145 static bool is_transmit_empty( ioport8_t *port)146 { 147 return (pio_read_8( port + 5) & 0x20) != 0;210 static bool is_transmit_empty(ns8250_regs_t *regs) 211 { 212 return (pio_read_8(®s->lsr) & NS8250_LSR_THRE) != 0; 148 213 } 149 214 … … 153 218 * @param c The character to be written to the serial port device. 154 219 */ 155 static void ns8250_write_8( ioport8_t *port, uint8_t c)156 { 157 while (!is_transmit_empty( port))220 static void ns8250_write_8(ns8250_regs_t *regs, uint8_t c) 221 { 222 while (!is_transmit_empty(regs)) 158 223 ; 159 224 160 pio_write_8( port, c);225 pio_write_8(®s->data, c); 161 226 } 162 227 … … 193 258 { 194 259 fibril_mutex_lock(&ns->mutex); 195 ns8250_write_8(ns-> port, c);260 ns8250_write_8(ns->regs, c); 196 261 fibril_mutex_unlock(&ns->mutex); 197 262 } … … 212 277 ns8250_putchar(ns, (uint8_t) buf[idx]); 213 278 214 return 0;279 return count; 215 280 } 216 281 … … 266 331 return false; 267 332 } 333 334 ns->regs = (ns8250_regs_t *)ns->port; 268 335 269 336 return true; … … 279 346 ddf_msg(LVL_DEBUG, "ns8250_dev_probe %s", ns->dev->name); 280 347 281 ioport8_t *port_addr = ns->port;282 348 bool res = true; 283 349 uint8_t olddata; 284 350 285 olddata = pio_read_8( port_addr + 4);286 287 pio_write_8( port_addr + 4, 0x10);288 if (pio_read_8( port_addr + 6) & 0xf0)351 olddata = pio_read_8(&ns->regs->mcr); 352 353 pio_write_8(&ns->regs->mcr, NS8250_MCR_LOOPBACK); 354 if (pio_read_8(&ns->regs->msr) & NS8250_MSR_SIGNALS) 289 355 res = false; 290 356 291 pio_write_8(port_addr + 4, 0x1f); 292 if ((pio_read_8(port_addr + 6) & 0xf0) != 0xf0) 357 pio_write_8(&ns->regs->mcr, NS8250_MCR_ALL); 358 if ((pio_read_8(&ns->regs->msr) & NS8250_MSR_SIGNALS) 359 != NS8250_MSR_SIGNALS) 293 360 res = false; 294 361 295 pio_write_8( port_addr + 4, olddata);362 pio_write_8(&ns->regs->mcr, olddata); 296 363 297 364 if (!res) { … … 390 457 * @param port The base address of the serial port device's ports. 391 458 */ 392 static inline void ns8250_port_interrupts_enable(ioport8_t *port) 393 { 394 pio_write_8(port + 1, 0x1); /* Interrupt when data received. */ 395 pio_write_8(port + 4, 0xB); 459 static inline void ns8250_port_interrupts_enable(ns8250_regs_t *regs) 460 { 461 /* Interrupt when data received. */ 462 pio_write_8(®s->ier, NS8250_IER_RXREADY); 463 pio_write_8(®s->mcr, NS8250_MCR_DTR | NS8250_MCR_RTS 464 | NS8250_MCR_OUT2); 396 465 } 397 466 … … 400 469 * @param port The base address of the serial port device's ports 401 470 */ 402 static inline void ns8250_port_interrupts_disable( ioport8_t *port)403 { 404 pio_write_8( port + 1, 0x0); /* Disable all interrupts. */471 static inline void ns8250_port_interrupts_disable(ns8250_regs_t *regs) 472 { 473 pio_write_8(®s->ier, 0x0); /* Disable all interrupts. */ 405 474 } 406 475 … … 431 500 432 501 /* Enable interrupt on the serial port. */ 433 ns8250_port_interrupts_enable(ns-> port);502 ns8250_port_interrupts_enable(ns->regs); 434 503 435 504 return EOK; … … 443 512 * @param port The base address of the serial port device's ports. 444 513 */ 445 static inline void enable_dlab( ioport8_t *port)446 { 447 uint8_t val = pio_read_8( port + 3);448 pio_write_8( port + 3, val | DLAB_MASK);514 static inline void enable_dlab(ns8250_regs_t *regs) 515 { 516 uint8_t val = pio_read_8(®s->lcr); 517 pio_write_8(®s->lcr, val | NS8250_LCR_DLAB); 449 518 } 450 519 … … 453 522 * @param port The base address of the serial port device's ports. 454 523 */ 455 static inline void clear_dlab( ioport8_t *port)456 { 457 uint8_t val = pio_read_8( port + 3);458 pio_write_8( port + 3, val & (~DLAB_MASK));524 static inline void clear_dlab(ns8250_regs_t *regs) 525 { 526 uint8_t val = pio_read_8(®s->lcr); 527 pio_write_8(®s->lcr, val & (~NS8250_LCR_DLAB)); 459 528 } 460 529 … … 466 535 * if the specified baud_rate is not valid). 467 536 */ 468 static int ns8250_port_set_baud_rate( ioport8_t *port, unsigned int baud_rate)537 static int ns8250_port_set_baud_rate(ns8250_regs_t *regs, unsigned int baud_rate) 469 538 { 470 539 uint16_t divisor; … … 482 551 483 552 /* Enable DLAB to be able to access baud rate divisor. */ 484 enable_dlab( port);553 enable_dlab(regs); 485 554 486 555 /* Set divisor low byte. */ 487 pio_write_8( port + 0, div_low);556 pio_write_8(®s->data, div_low); 488 557 /* Set divisor high byte. */ 489 pio_write_8( port + 1, div_high);490 491 clear_dlab( port);558 pio_write_8(®s->ier, div_high); 559 560 clear_dlab(regs); 492 561 493 562 return EOK; … … 499 568 * @param baud_rate The ouput parameter to which the baud rate is stored. 500 569 */ 501 static unsigned int ns8250_port_get_baud_rate( ioport8_t *port)570 static unsigned int ns8250_port_get_baud_rate(ns8250_regs_t *regs) 502 571 { 503 572 uint16_t divisor; … … 505 574 506 575 /* Enable DLAB to be able to access baud rate divisor. */ 507 enable_dlab( port);576 enable_dlab(regs); 508 577 509 578 /* Get divisor low byte. */ 510 div_low = pio_read_8( port + 0);579 div_low = pio_read_8(®s->data); 511 580 /* Get divisor high byte. */ 512 div_high = pio_read_8( port + 1);513 514 clear_dlab( port);581 div_high = pio_read_8(®s->ier); 582 583 clear_dlab(regs); 515 584 516 585 divisor = (div_high << 8) | div_low; … … 525 594 * @param stop_bits The number of stop bits used (one or two). 526 595 */ 527 static void ns8250_port_get_com_props( ioport8_t *port, unsigned int *parity,596 static void ns8250_port_get_com_props(ns8250_regs_t *regs, unsigned int *parity, 528 597 unsigned int *word_length, unsigned int *stop_bits) 529 598 { 530 599 uint8_t val; 531 600 532 val = pio_read_8( port + 3);533 *parity = ((val >> 3) & 7);601 val = pio_read_8(®s->lcr); 602 *parity = ((val >> NS8250_LCR_PARITY) & 7); 534 603 535 604 switch (val & 3) { … … 548 617 } 549 618 550 if ((val >> 2) & 1)619 if ((val >> NS8250_LCR_STOPBITS) & 1) 551 620 *stop_bits = 2; 552 621 else … … 562 631 * is invalid. 563 632 */ 564 static int ns8250_port_set_com_props( ioport8_t *port, unsigned int parity,633 static int ns8250_port_set_com_props(ns8250_regs_t *regs, unsigned int parity, 565 634 unsigned int word_length, unsigned int stop_bits) 566 635 { … … 586 655 switch (stop_bits) { 587 656 case 1: 588 val |= ONE_STOP_BIT << 2;657 val |= ONE_STOP_BIT << NS8250_LCR_STOPBITS; 589 658 break; 590 659 case 2: 591 val |= TWO_STOP_BITS << 2;660 val |= TWO_STOP_BITS << NS8250_LCR_STOPBITS; 592 661 break; 593 662 default: … … 601 670 case SERIAL_MARK_PARITY: 602 671 case SERIAL_SPACE_PARITY: 603 val |= parity << 3;672 val |= parity << NS8250_LCR_PARITY; 604 673 break; 605 674 default: … … 607 676 } 608 677 609 pio_write_8( port + 3, val);678 pio_write_8(®s->lcr, val); 610 679 611 680 return EOK; … … 620 689 static void ns8250_initialize_port(ns8250_t *ns) 621 690 { 622 ioport8_t *port = ns->port;623 624 691 /* Disable interrupts. */ 625 ns8250_port_interrupts_disable( port);692 ns8250_port_interrupts_disable(ns->regs); 626 693 /* Set baud rate. */ 627 ns8250_port_set_baud_rate( port, 38400);694 ns8250_port_set_baud_rate(ns->regs, 38400); 628 695 /* 8 bits, no parity, two stop bits. */ 629 ns8250_port_set_com_props( port, SERIAL_NO_PARITY, 8, 2);696 ns8250_port_set_com_props(ns->regs, SERIAL_NO_PARITY, 8, 2); 630 697 /* Enable FIFO, clear them, with 14-byte threshold. */ 631 pio_write_8(port + 2, 0xC7); 698 pio_write_8(&ns->regs->iid, NS8250_FCR_FIFOENABLE 699 | NS8250_FCR_RXFIFORESET | NS8250_FCR_TXFIFORESET 700 | NS8250_FCR_RXTRIGGERLOW | NS8250_FCR_RXTRIGGERHI); 632 701 /* 633 702 * RTS/DSR set (Request to Send and Data Terminal Ready lines enabled), 634 703 * Aux Output2 set - needed for interrupts. 635 704 */ 636 pio_write_8(port + 4, 0x0B); 705 pio_write_8(&ns->regs->mcr, NS8250_MCR_DTR | NS8250_MCR_RTS 706 | NS8250_MCR_OUT2); 637 707 } 638 708 … … 644 714 { 645 715 /* Disable FIFO */ 646 pio_write_8( ns->port + 2, 0x00);716 pio_write_8(&ns->regs->iid, 0x00); 647 717 /* Disable DTR, RTS, OUT1, OUT2 (int. enable) */ 648 pio_write_8( ns->port + 4, 0x00);718 pio_write_8(&ns->regs->mcr, 0x00); 649 719 /* Disable all interrupts from the port */ 650 ns8250_port_interrupts_disable(ns-> port);720 ns8250_port_interrupts_disable(ns->regs); 651 721 } 652 722 … … 658 728 static void ns8250_read_from_device(ns8250_t *ns) 659 729 { 660 ioport8_t *port = ns->port;730 ns8250_regs_t *regs = ns->regs; 661 731 bool cont = true; 662 732 … … 664 734 fibril_mutex_lock(&ns->mutex); 665 735 666 cont = ns8250_received( port);736 cont = ns8250_received(regs); 667 737 if (cont) { 668 uint8_t val = ns8250_read_8( port);738 uint8_t val = ns8250_read_8(regs); 669 739 670 740 if (ns->client_connected) { … … 896 966 { 897 967 ns8250_t *data = (ns8250_t *) dev->driver_data; 898 ioport8_t *port = data->port;968 ns8250_regs_t *regs = data->regs; 899 969 900 970 fibril_mutex_lock(&data->mutex); 901 ns8250_port_interrupts_disable( port);902 *baud_rate = ns8250_port_get_baud_rate( port);903 ns8250_port_get_com_props( port, parity, word_length, stop_bits);904 ns8250_port_interrupts_enable( port);971 ns8250_port_interrupts_disable(regs); 972 *baud_rate = ns8250_port_get_baud_rate(regs); 973 ns8250_port_get_com_props(regs, parity, word_length, stop_bits); 974 ns8250_port_interrupts_enable(regs); 905 975 fibril_mutex_unlock(&data->mutex); 906 976 … … 927 997 928 998 ns8250_t *data = (ns8250_t *) dev->driver_data; 929 ioport8_t *port = data->port;999 ns8250_regs_t *regs = data->regs; 930 1000 int ret; 931 1001 932 1002 fibril_mutex_lock(&data->mutex); 933 ns8250_port_interrupts_disable( port);934 ret = ns8250_port_set_baud_rate( port, baud_rate);1003 ns8250_port_interrupts_disable(regs); 1004 ret = ns8250_port_set_baud_rate(regs, baud_rate); 935 1005 if (ret == EOK) 936 ret = ns8250_port_set_com_props( port, parity, word_length, stop_bits);937 ns8250_port_interrupts_enable( port);1006 ret = ns8250_port_set_com_props(regs, parity, word_length, stop_bits); 1007 ns8250_port_interrupts_enable(regs); 938 1008 fibril_mutex_unlock(&data->mutex); 939 1009
Note:
See TracChangeset
for help on using the changeset viewer.