900 lines · c
1// SPDX-License-Identifier: GPL-2.0+2/*3 * Copyright 2003 Digi International (www.digi.com)4 * Scott H Kilau <Scott_Kilau at digi dot com>5 *6 * NOTE TO LINUX KERNEL HACKERS: DO NOT REFORMAT THIS CODE!7 *8 * This is shared code between Digi's CVS archive and the9 * Linux Kernel sources.10 * Changing the source just for reformatting needlessly breaks11 * our CVS diff history.12 *13 * Send any bug fixes/changes to: Eng.Linux at digi dot com.14 * Thank you.15 *16 */17 18#include <linux/delay.h> /* For udelay */19#include <linux/io.h> /* For read[bwl]/write[bwl] */20#include <linux/serial.h> /* For struct async_serial */21#include <linux/serial_reg.h> /* For the various UART offsets */22#include <linux/pci.h>23#include <linux/tty.h>24 25#include "jsm.h" /* Driver main header file */26 27static struct {28 unsigned int rate;29 unsigned int cflag;30} baud_rates[] = {31 { 921600, B921600 },32 { 460800, B460800 },33 { 230400, B230400 },34 { 115200, B115200 },35 { 57600, B57600 },36 { 38400, B38400 },37 { 19200, B19200 },38 { 9600, B9600 },39 { 4800, B4800 },40 { 2400, B2400 },41 { 1200, B1200 },42 { 600, B600 },43 { 300, B300 },44 { 200, B200 },45 { 150, B150 },46 { 134, B134 },47 { 110, B110 },48 { 75, B75 },49 { 50, B50 },50};51 52static void cls_set_cts_flow_control(struct jsm_channel *ch)53{54 u8 lcrb = readb(&ch->ch_cls_uart->lcr);55 u8 ier = readb(&ch->ch_cls_uart->ier);56 u8 isr_fcr = 0;57 58 /*59 * The Enhanced Register Set may only be accessed when60 * the Line Control Register is set to 0xBFh.61 */62 writeb(UART_EXAR654_ENHANCED_REGISTER_SET, &ch->ch_cls_uart->lcr);63 64 isr_fcr = readb(&ch->ch_cls_uart->isr_fcr);65 66 /* Turn on CTS flow control, turn off IXON flow control */67 isr_fcr |= (UART_EXAR654_EFR_ECB | UART_EXAR654_EFR_CTSDSR);68 isr_fcr &= ~(UART_EXAR654_EFR_IXON);69 70 writeb(isr_fcr, &ch->ch_cls_uart->isr_fcr);71 72 /* Write old LCR value back out, which turns enhanced access off */73 writeb(lcrb, &ch->ch_cls_uart->lcr);74 75 /*76 * Enable interrupts for CTS flow, turn off interrupts for77 * received XOFF chars78 */79 ier |= (UART_EXAR654_IER_CTSDSR);80 ier &= ~(UART_EXAR654_IER_XOFF);81 writeb(ier, &ch->ch_cls_uart->ier);82 83 /* Set the usual FIFO values */84 writeb((UART_FCR_ENABLE_FIFO), &ch->ch_cls_uart->isr_fcr);85 86 writeb((UART_FCR_ENABLE_FIFO | UART_16654_FCR_RXTRIGGER_56 |87 UART_16654_FCR_TXTRIGGER_16 | UART_FCR_CLEAR_RCVR),88 &ch->ch_cls_uart->isr_fcr);89 90 ch->ch_t_tlevel = 16;91}92 93static void cls_set_ixon_flow_control(struct jsm_channel *ch)94{95 u8 lcrb = readb(&ch->ch_cls_uart->lcr);96 u8 ier = readb(&ch->ch_cls_uart->ier);97 u8 isr_fcr = 0;98 99 /*100 * The Enhanced Register Set may only be accessed when101 * the Line Control Register is set to 0xBFh.102 */103 writeb(UART_EXAR654_ENHANCED_REGISTER_SET, &ch->ch_cls_uart->lcr);104 105 isr_fcr = readb(&ch->ch_cls_uart->isr_fcr);106 107 /* Turn on IXON flow control, turn off CTS flow control */108 isr_fcr |= (UART_EXAR654_EFR_ECB | UART_EXAR654_EFR_IXON);109 isr_fcr &= ~(UART_EXAR654_EFR_CTSDSR);110 111 writeb(isr_fcr, &ch->ch_cls_uart->isr_fcr);112 113 /* Now set our current start/stop chars while in enhanced mode */114 writeb(ch->ch_startc, &ch->ch_cls_uart->mcr);115 writeb(0, &ch->ch_cls_uart->lsr);116 writeb(ch->ch_stopc, &ch->ch_cls_uart->msr);117 writeb(0, &ch->ch_cls_uart->spr);118 119 /* Write old LCR value back out, which turns enhanced access off */120 writeb(lcrb, &ch->ch_cls_uart->lcr);121 122 /*123 * Disable interrupts for CTS flow, turn on interrupts for124 * received XOFF chars125 */126 ier &= ~(UART_EXAR654_IER_CTSDSR);127 ier |= (UART_EXAR654_IER_XOFF);128 writeb(ier, &ch->ch_cls_uart->ier);129 130 /* Set the usual FIFO values */131 writeb((UART_FCR_ENABLE_FIFO), &ch->ch_cls_uart->isr_fcr);132 133 writeb((UART_FCR_ENABLE_FIFO | UART_16654_FCR_RXTRIGGER_16 |134 UART_16654_FCR_TXTRIGGER_16 | UART_FCR_CLEAR_RCVR),135 &ch->ch_cls_uart->isr_fcr);136}137 138static void cls_set_no_output_flow_control(struct jsm_channel *ch)139{140 u8 lcrb = readb(&ch->ch_cls_uart->lcr);141 u8 ier = readb(&ch->ch_cls_uart->ier);142 u8 isr_fcr = 0;143 144 /*145 * The Enhanced Register Set may only be accessed when146 * the Line Control Register is set to 0xBFh.147 */148 writeb(UART_EXAR654_ENHANCED_REGISTER_SET, &ch->ch_cls_uart->lcr);149 150 isr_fcr = readb(&ch->ch_cls_uart->isr_fcr);151 152 /* Turn off IXON flow control, turn off CTS flow control */153 isr_fcr |= (UART_EXAR654_EFR_ECB);154 isr_fcr &= ~(UART_EXAR654_EFR_CTSDSR | UART_EXAR654_EFR_IXON);155 156 writeb(isr_fcr, &ch->ch_cls_uart->isr_fcr);157 158 /* Write old LCR value back out, which turns enhanced access off */159 writeb(lcrb, &ch->ch_cls_uart->lcr);160 161 /*162 * Disable interrupts for CTS flow, turn off interrupts for163 * received XOFF chars164 */165 ier &= ~(UART_EXAR654_IER_CTSDSR);166 ier &= ~(UART_EXAR654_IER_XOFF);167 writeb(ier, &ch->ch_cls_uart->ier);168 169 /* Set the usual FIFO values */170 writeb((UART_FCR_ENABLE_FIFO), &ch->ch_cls_uart->isr_fcr);171 172 writeb((UART_FCR_ENABLE_FIFO | UART_16654_FCR_RXTRIGGER_16 |173 UART_16654_FCR_TXTRIGGER_16 | UART_FCR_CLEAR_RCVR),174 &ch->ch_cls_uart->isr_fcr);175 176 ch->ch_r_watermark = 0;177 ch->ch_t_tlevel = 16;178 ch->ch_r_tlevel = 16;179}180 181static void cls_set_rts_flow_control(struct jsm_channel *ch)182{183 u8 lcrb = readb(&ch->ch_cls_uart->lcr);184 u8 ier = readb(&ch->ch_cls_uart->ier);185 u8 isr_fcr = 0;186 187 /*188 * The Enhanced Register Set may only be accessed when189 * the Line Control Register is set to 0xBFh.190 */191 writeb(UART_EXAR654_ENHANCED_REGISTER_SET, &ch->ch_cls_uart->lcr);192 193 isr_fcr = readb(&ch->ch_cls_uart->isr_fcr);194 195 /* Turn on RTS flow control, turn off IXOFF flow control */196 isr_fcr |= (UART_EXAR654_EFR_ECB | UART_EXAR654_EFR_RTSDTR);197 isr_fcr &= ~(UART_EXAR654_EFR_IXOFF);198 199 writeb(isr_fcr, &ch->ch_cls_uart->isr_fcr);200 201 /* Write old LCR value back out, which turns enhanced access off */202 writeb(lcrb, &ch->ch_cls_uart->lcr);203 204 /* Enable interrupts for RTS flow */205 ier |= (UART_EXAR654_IER_RTSDTR);206 writeb(ier, &ch->ch_cls_uart->ier);207 208 /* Set the usual FIFO values */209 writeb((UART_FCR_ENABLE_FIFO), &ch->ch_cls_uart->isr_fcr);210 211 writeb((UART_FCR_ENABLE_FIFO | UART_16654_FCR_RXTRIGGER_56 |212 UART_16654_FCR_TXTRIGGER_16 | UART_FCR_CLEAR_RCVR),213 &ch->ch_cls_uart->isr_fcr);214 215 ch->ch_r_watermark = 4;216 ch->ch_r_tlevel = 8;217}218 219static void cls_set_ixoff_flow_control(struct jsm_channel *ch)220{221 u8 lcrb = readb(&ch->ch_cls_uart->lcr);222 u8 ier = readb(&ch->ch_cls_uart->ier);223 u8 isr_fcr = 0;224 225 /*226 * The Enhanced Register Set may only be accessed when227 * the Line Control Register is set to 0xBFh.228 */229 writeb(UART_EXAR654_ENHANCED_REGISTER_SET, &ch->ch_cls_uart->lcr);230 231 isr_fcr = readb(&ch->ch_cls_uart->isr_fcr);232 233 /* Turn on IXOFF flow control, turn off RTS flow control */234 isr_fcr |= (UART_EXAR654_EFR_ECB | UART_EXAR654_EFR_IXOFF);235 isr_fcr &= ~(UART_EXAR654_EFR_RTSDTR);236 237 writeb(isr_fcr, &ch->ch_cls_uart->isr_fcr);238 239 /* Now set our current start/stop chars while in enhanced mode */240 writeb(ch->ch_startc, &ch->ch_cls_uart->mcr);241 writeb(0, &ch->ch_cls_uart->lsr);242 writeb(ch->ch_stopc, &ch->ch_cls_uart->msr);243 writeb(0, &ch->ch_cls_uart->spr);244 245 /* Write old LCR value back out, which turns enhanced access off */246 writeb(lcrb, &ch->ch_cls_uart->lcr);247 248 /* Disable interrupts for RTS flow */249 ier &= ~(UART_EXAR654_IER_RTSDTR);250 writeb(ier, &ch->ch_cls_uart->ier);251 252 /* Set the usual FIFO values */253 writeb((UART_FCR_ENABLE_FIFO), &ch->ch_cls_uart->isr_fcr);254 255 writeb((UART_FCR_ENABLE_FIFO | UART_16654_FCR_RXTRIGGER_16 |256 UART_16654_FCR_TXTRIGGER_16 | UART_FCR_CLEAR_RCVR),257 &ch->ch_cls_uart->isr_fcr);258}259 260static void cls_set_no_input_flow_control(struct jsm_channel *ch)261{262 u8 lcrb = readb(&ch->ch_cls_uart->lcr);263 u8 ier = readb(&ch->ch_cls_uart->ier);264 u8 isr_fcr = 0;265 266 /*267 * The Enhanced Register Set may only be accessed when268 * the Line Control Register is set to 0xBFh.269 */270 writeb(UART_EXAR654_ENHANCED_REGISTER_SET, &ch->ch_cls_uart->lcr);271 272 isr_fcr = readb(&ch->ch_cls_uart->isr_fcr);273 274 /* Turn off IXOFF flow control, turn off RTS flow control */275 isr_fcr |= (UART_EXAR654_EFR_ECB);276 isr_fcr &= ~(UART_EXAR654_EFR_RTSDTR | UART_EXAR654_EFR_IXOFF);277 278 writeb(isr_fcr, &ch->ch_cls_uart->isr_fcr);279 280 /* Write old LCR value back out, which turns enhanced access off */281 writeb(lcrb, &ch->ch_cls_uart->lcr);282 283 /* Disable interrupts for RTS flow */284 ier &= ~(UART_EXAR654_IER_RTSDTR);285 writeb(ier, &ch->ch_cls_uart->ier);286 287 /* Set the usual FIFO values */288 writeb((UART_FCR_ENABLE_FIFO), &ch->ch_cls_uart->isr_fcr);289 290 writeb((UART_FCR_ENABLE_FIFO | UART_16654_FCR_RXTRIGGER_16 |291 UART_16654_FCR_TXTRIGGER_16 | UART_FCR_CLEAR_RCVR),292 &ch->ch_cls_uart->isr_fcr);293 294 ch->ch_t_tlevel = 16;295 ch->ch_r_tlevel = 16;296}297 298/*299 * cls_clear_break.300 * Determines whether its time to shut off break condition.301 *302 * No locks are assumed to be held when calling this function.303 * channel lock is held and released in this function.304 */305static void cls_clear_break(struct jsm_channel *ch)306{307 unsigned long lock_flags;308 309 spin_lock_irqsave(&ch->ch_lock, lock_flags);310 311 /* Turn break off, and unset some variables */312 if (ch->ch_flags & CH_BREAK_SENDING) {313 u8 temp = readb(&ch->ch_cls_uart->lcr);314 315 writeb((temp & ~UART_LCR_SBC), &ch->ch_cls_uart->lcr);316 317 ch->ch_flags &= ~(CH_BREAK_SENDING);318 jsm_dbg(IOCTL, &ch->ch_bd->pci_dev,319 "clear break Finishing UART_LCR_SBC! finished: %lx\n",320 jiffies);321 }322 spin_unlock_irqrestore(&ch->ch_lock, lock_flags);323}324 325static void cls_disable_receiver(struct jsm_channel *ch)326{327 u8 tmp = readb(&ch->ch_cls_uart->ier);328 329 tmp &= ~(UART_IER_RDI);330 writeb(tmp, &ch->ch_cls_uart->ier);331}332 333static void cls_enable_receiver(struct jsm_channel *ch)334{335 u8 tmp = readb(&ch->ch_cls_uart->ier);336 337 tmp |= (UART_IER_RDI);338 writeb(tmp, &ch->ch_cls_uart->ier);339}340 341/* Make the UART raise any of the output signals we want up */342static void cls_assert_modem_signals(struct jsm_channel *ch)343{344 if (!ch)345 return;346 347 writeb(ch->ch_mostat, &ch->ch_cls_uart->mcr);348}349 350static void cls_copy_data_from_uart_to_queue(struct jsm_channel *ch)351{352 int qleft = 0;353 u8 linestatus;354 u8 error_mask = 0;355 u16 head;356 u16 tail;357 unsigned long flags;358 359 if (!ch)360 return;361 362 spin_lock_irqsave(&ch->ch_lock, flags);363 364 /* cache head and tail of queue */365 head = ch->ch_r_head & RQUEUEMASK;366 tail = ch->ch_r_tail & RQUEUEMASK;367 368 ch->ch_cached_lsr = 0;369 370 /* Store how much space we have left in the queue */371 qleft = tail - head - 1;372 if (qleft < 0)373 qleft += RQUEUEMASK + 1;374 375 /*376 * Create a mask to determine whether we should377 * insert the character (if any) into our queue.378 */379 if (ch->ch_c_iflag & IGNBRK)380 error_mask |= UART_LSR_BI;381 382 while (1) {383 /*384 * Grab the linestatus register, we need to385 * check to see if there is any data to read386 */387 linestatus = readb(&ch->ch_cls_uart->lsr);388 389 /* Break out if there is no data to fetch */390 if (!(linestatus & UART_LSR_DR))391 break;392 393 /*394 * Discard character if we are ignoring the error mask395 * which in this case is the break signal.396 */397 if (linestatus & error_mask) {398 readb(&ch->ch_cls_uart->txrx);399 continue;400 }401 402 /*403 * If our queue is full, we have no choice but to drop some404 * data. The assumption is that HWFLOW or SWFLOW should have405 * stopped things way way before we got to this point.406 *407 * I decided that I wanted to ditch the oldest data first,408 * I hope thats okay with everyone? Yes? Good.409 */410 while (qleft < 1) {411 tail = (tail + 1) & RQUEUEMASK;412 ch->ch_r_tail = tail;413 ch->ch_err_overrun++;414 qleft++;415 }416 417 ch->ch_equeue[head] = linestatus & (UART_LSR_BI | UART_LSR_PE418 | UART_LSR_FE);419 ch->ch_rqueue[head] = readb(&ch->ch_cls_uart->txrx);420 421 qleft--;422 423 if (ch->ch_equeue[head] & UART_LSR_PE)424 ch->ch_err_parity++;425 if (ch->ch_equeue[head] & UART_LSR_BI)426 ch->ch_err_break++;427 if (ch->ch_equeue[head] & UART_LSR_FE)428 ch->ch_err_frame++;429 430 /* Add to, and flip head if needed */431 head = (head + 1) & RQUEUEMASK;432 ch->ch_rxcount++;433 }434 435 /*436 * Write new final heads to channel structure.437 */438 ch->ch_r_head = head & RQUEUEMASK;439 ch->ch_e_head = head & EQUEUEMASK;440 441 spin_unlock_irqrestore(&ch->ch_lock, flags);442}443 444static void cls_copy_data_from_queue_to_uart(struct jsm_channel *ch)445{446 struct tty_port *tport;447 int n;448 u32 len_written = 0;449 450 if (!ch)451 return;452 453 tport = &ch->uart_port.state->port;454 455 /* If port is "stopped", don't send any data to the UART */456 if ((ch->ch_flags & CH_STOP) || (ch->ch_flags & CH_BREAK_SENDING))457 return;458 459 /* We have to do it this way, because of the EXAR TXFIFO count bug. */460 if (!(ch->ch_flags & (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM)))461 return;462 463 n = 32;464 while (n > 0) {465 unsigned char c;466 467 if (!kfifo_get(&tport->xmit_fifo, &c))468 break;469 470 writeb(c, &ch->ch_cls_uart->txrx);471 n--;472 ch->ch_txcount++;473 len_written++;474 }475 476 if (len_written > ch->ch_t_tlevel)477 ch->ch_flags &= ~(CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);478 479 if (kfifo_is_empty(&tport->xmit_fifo))480 uart_write_wakeup(&ch->uart_port);481}482 483static void cls_parse_modem(struct jsm_channel *ch, u8 signals)484{485 u8 msignals = signals;486 487 jsm_dbg(MSIGS, &ch->ch_bd->pci_dev,488 "neo_parse_modem: port: %d msignals: %x\n",489 ch->ch_portnum, msignals);490 491 /*492 * Scrub off lower bits.493 * They signify delta's, which I don't care about494 * Keep DDCD and DDSR though495 */496 msignals &= 0xf8;497 498 if (msignals & UART_MSR_DDCD)499 uart_handle_dcd_change(&ch->uart_port, msignals & UART_MSR_DCD);500 if (msignals & UART_MSR_DDSR)501 uart_handle_dcd_change(&ch->uart_port, msignals & UART_MSR_CTS);502 503 if (msignals & UART_MSR_DCD)504 ch->ch_mistat |= UART_MSR_DCD;505 else506 ch->ch_mistat &= ~UART_MSR_DCD;507 508 if (msignals & UART_MSR_DSR)509 ch->ch_mistat |= UART_MSR_DSR;510 else511 ch->ch_mistat &= ~UART_MSR_DSR;512 513 if (msignals & UART_MSR_RI)514 ch->ch_mistat |= UART_MSR_RI;515 else516 ch->ch_mistat &= ~UART_MSR_RI;517 518 if (msignals & UART_MSR_CTS)519 ch->ch_mistat |= UART_MSR_CTS;520 else521 ch->ch_mistat &= ~UART_MSR_CTS;522 523 jsm_dbg(MSIGS, &ch->ch_bd->pci_dev,524 "Port: %d DTR: %d RTS: %d CTS: %d DSR: %d " "RI: %d CD: %d\n",525 ch->ch_portnum,526 !!((ch->ch_mistat | ch->ch_mostat) & UART_MCR_DTR),527 !!((ch->ch_mistat | ch->ch_mostat) & UART_MCR_RTS),528 !!((ch->ch_mistat | ch->ch_mostat) & UART_MSR_CTS),529 !!((ch->ch_mistat | ch->ch_mostat) & UART_MSR_DSR),530 !!((ch->ch_mistat | ch->ch_mostat) & UART_MSR_RI),531 !!((ch->ch_mistat | ch->ch_mostat) & UART_MSR_DCD));532}533 534/* Parse the ISR register for the specific port */535static inline void cls_parse_isr(struct jsm_board *brd, uint port)536{537 struct jsm_channel *ch;538 u8 isr = 0;539 unsigned long flags;540 541 /*542 * No need to verify board pointer, it was already543 * verified in the interrupt routine.544 */545 546 if (port >= brd->nasync)547 return;548 549 ch = brd->channels[port];550 if (!ch)551 return;552 553 /* Here we try to figure out what caused the interrupt to happen */554 while (1) {555 isr = readb(&ch->ch_cls_uart->isr_fcr);556 557 /* Bail if no pending interrupt on port */558 if (isr & UART_IIR_NO_INT)559 break;560 561 /* Receive Interrupt pending */562 if (isr & (UART_IIR_RDI | UART_IIR_RDI_TIMEOUT)) {563 /* Read data from uart -> queue */564 cls_copy_data_from_uart_to_queue(ch);565 jsm_check_queue_flow_control(ch);566 }567 568 /* Transmit Hold register empty pending */569 if (isr & UART_IIR_THRI) {570 /* Transfer data (if any) from Write Queue -> UART. */571 spin_lock_irqsave(&ch->ch_lock, flags);572 ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);573 spin_unlock_irqrestore(&ch->ch_lock, flags);574 cls_copy_data_from_queue_to_uart(ch);575 }576 577 /*578 * CTS/RTS change of state:579 * Don't need to do anything, the cls_parse_modem580 * below will grab the updated modem signals.581 */582 583 /* Parse any modem signal changes */584 cls_parse_modem(ch, readb(&ch->ch_cls_uart->msr));585 }586}587 588/* Channel lock MUST be held before calling this function! */589static void cls_flush_uart_write(struct jsm_channel *ch)590{591 u8 tmp = 0;592 u8 i = 0;593 594 if (!ch)595 return;596 597 writeb((UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_XMIT),598 &ch->ch_cls_uart->isr_fcr);599 600 for (i = 0; i < 10; i++) {601 /* Check to see if the UART feels it completely flushed FIFO */602 tmp = readb(&ch->ch_cls_uart->isr_fcr);603 if (tmp & UART_FCR_CLEAR_XMIT) {604 jsm_dbg(IOCTL, &ch->ch_bd->pci_dev,605 "Still flushing TX UART... i: %d\n", i);606 udelay(10);607 } else608 break;609 }610 611 ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);612}613 614/* Channel lock MUST be held before calling this function! */615static void cls_flush_uart_read(struct jsm_channel *ch)616{617 if (!ch)618 return;619 620 /*621 * For complete POSIX compatibility, we should be purging the622 * read FIFO in the UART here.623 *624 * However, clearing the read FIFO (UART_FCR_CLEAR_RCVR) also625 * incorrectly flushes write data as well as just basically trashing the626 * FIFO.627 *628 * Presumably, this is a bug in this UART.629 */630 631 udelay(10);632}633 634static void cls_send_start_character(struct jsm_channel *ch)635{636 if (!ch)637 return;638 639 if (ch->ch_startc != __DISABLED_CHAR) {640 ch->ch_xon_sends++;641 writeb(ch->ch_startc, &ch->ch_cls_uart->txrx);642 }643}644 645static void cls_send_stop_character(struct jsm_channel *ch)646{647 if (!ch)648 return;649 650 if (ch->ch_stopc != __DISABLED_CHAR) {651 ch->ch_xoff_sends++;652 writeb(ch->ch_stopc, &ch->ch_cls_uart->txrx);653 }654}655 656/*657 * cls_param()658 * Send any/all changes to the line to the UART.659 */660static void cls_param(struct jsm_channel *ch)661{662 u8 lcr = 0;663 u8 uart_lcr = 0;664 u8 ier = 0;665 u32 baud = 9600;666 int quot = 0;667 struct jsm_board *bd;668 int i;669 unsigned int cflag;670 671 bd = ch->ch_bd;672 if (!bd)673 return;674 675 /*676 * If baud rate is zero, flush queues, and set mval to drop DTR.677 */678 if ((ch->ch_c_cflag & CBAUD) == B0) {679 ch->ch_r_head = 0;680 ch->ch_r_tail = 0;681 ch->ch_e_head = 0;682 ch->ch_e_tail = 0;683 684 cls_flush_uart_write(ch);685 cls_flush_uart_read(ch);686 687 /* The baudrate is B0 so all modem lines are to be dropped. */688 ch->ch_flags |= (CH_BAUD0);689 ch->ch_mostat &= ~(UART_MCR_RTS | UART_MCR_DTR);690 cls_assert_modem_signals(ch);691 return;692 }693 694 cflag = C_BAUD(ch->uart_port.state->port.tty);695 baud = 9600;696 for (i = 0; i < ARRAY_SIZE(baud_rates); i++) {697 if (baud_rates[i].cflag == cflag) {698 baud = baud_rates[i].rate;699 break;700 }701 }702 703 if (ch->ch_flags & CH_BAUD0)704 ch->ch_flags &= ~(CH_BAUD0);705 706 if (ch->ch_c_cflag & PARENB)707 lcr |= UART_LCR_PARITY;708 709 if (!(ch->ch_c_cflag & PARODD))710 lcr |= UART_LCR_EPAR;711 712 if (ch->ch_c_cflag & CMSPAR)713 lcr |= UART_LCR_SPAR;714 715 if (ch->ch_c_cflag & CSTOPB)716 lcr |= UART_LCR_STOP;717 718 lcr |= UART_LCR_WLEN(tty_get_char_size(ch->ch_c_cflag));719 720 ier = readb(&ch->ch_cls_uart->ier);721 uart_lcr = readb(&ch->ch_cls_uart->lcr);722 723 quot = ch->ch_bd->bd_dividend / baud;724 725 if (quot != 0) {726 writeb(UART_LCR_DLAB, &ch->ch_cls_uart->lcr);727 writeb((quot & 0xff), &ch->ch_cls_uart->txrx);728 writeb((quot >> 8), &ch->ch_cls_uart->ier);729 writeb(lcr, &ch->ch_cls_uart->lcr);730 }731 732 if (uart_lcr != lcr)733 writeb(lcr, &ch->ch_cls_uart->lcr);734 735 if (ch->ch_c_cflag & CREAD)736 ier |= (UART_IER_RDI | UART_IER_RLSI);737 738 ier |= (UART_IER_THRI | UART_IER_MSI);739 740 writeb(ier, &ch->ch_cls_uart->ier);741 742 if (ch->ch_c_cflag & CRTSCTS)743 cls_set_cts_flow_control(ch);744 else if (ch->ch_c_iflag & IXON) {745 /*746 * If start/stop is set to disable,747 * then we should disable flow control.748 */749 if ((ch->ch_startc == __DISABLED_CHAR) ||750 (ch->ch_stopc == __DISABLED_CHAR))751 cls_set_no_output_flow_control(ch);752 else753 cls_set_ixon_flow_control(ch);754 } else755 cls_set_no_output_flow_control(ch);756 757 if (ch->ch_c_cflag & CRTSCTS)758 cls_set_rts_flow_control(ch);759 else if (ch->ch_c_iflag & IXOFF) {760 /*761 * If start/stop is set to disable,762 * then we should disable flow control.763 */764 if ((ch->ch_startc == __DISABLED_CHAR) ||765 (ch->ch_stopc == __DISABLED_CHAR))766 cls_set_no_input_flow_control(ch);767 else768 cls_set_ixoff_flow_control(ch);769 } else770 cls_set_no_input_flow_control(ch);771 772 cls_assert_modem_signals(ch);773 774 /* get current status of the modem signals now */775 cls_parse_modem(ch, readb(&ch->ch_cls_uart->msr));776}777 778/*779 * cls_intr()780 *781 * Classic specific interrupt handler.782 */783static irqreturn_t cls_intr(int irq, void *voidbrd)784{785 struct jsm_board *brd = voidbrd;786 unsigned long lock_flags;787 unsigned char uart_poll;788 uint i = 0;789 790 /* Lock out the slow poller from running on this board. */791 spin_lock_irqsave(&brd->bd_intr_lock, lock_flags);792 793 /*794 * Check the board's global interrupt offset to see if we795 * acctually do have an interrupt pending on us.796 */797 uart_poll = readb(brd->re_map_membase + UART_CLASSIC_POLL_ADDR_OFFSET);798 799 jsm_dbg(INTR, &brd->pci_dev, "%s:%d uart_poll: %x\n",800 __FILE__, __LINE__, uart_poll);801 802 if (!uart_poll) {803 jsm_dbg(INTR, &brd->pci_dev,804 "Kernel interrupted to me, but no pending interrupts...\n");805 spin_unlock_irqrestore(&brd->bd_intr_lock, lock_flags);806 return IRQ_NONE;807 }808 809 /* At this point, we have at least SOMETHING to service, dig further. */810 811 /* Parse each port to find out what caused the interrupt */812 for (i = 0; i < brd->nasync; i++)813 cls_parse_isr(brd, i);814 815 spin_unlock_irqrestore(&brd->bd_intr_lock, lock_flags);816 817 return IRQ_HANDLED;818}819 820/* Inits UART */821static void cls_uart_init(struct jsm_channel *ch)822{823 unsigned char lcrb = readb(&ch->ch_cls_uart->lcr);824 unsigned char isr_fcr = 0;825 826 writeb(0, &ch->ch_cls_uart->ier);827 828 /*829 * The Enhanced Register Set may only be accessed when830 * the Line Control Register is set to 0xBFh.831 */832 writeb(UART_EXAR654_ENHANCED_REGISTER_SET, &ch->ch_cls_uart->lcr);833 834 isr_fcr = readb(&ch->ch_cls_uart->isr_fcr);835 836 /* Turn on Enhanced/Extended controls */837 isr_fcr |= (UART_EXAR654_EFR_ECB);838 839 writeb(isr_fcr, &ch->ch_cls_uart->isr_fcr);840 841 /* Write old LCR value back out, which turns enhanced access off */842 writeb(lcrb, &ch->ch_cls_uart->lcr);843 844 /* Clear out UART and FIFO */845 readb(&ch->ch_cls_uart->txrx);846 847 writeb((UART_FCR_ENABLE_FIFO|UART_FCR_CLEAR_RCVR|UART_FCR_CLEAR_XMIT),848 &ch->ch_cls_uart->isr_fcr);849 udelay(10);850 851 ch->ch_flags |= (CH_FIFO_ENABLED | CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);852 853 readb(&ch->ch_cls_uart->lsr);854 readb(&ch->ch_cls_uart->msr);855}856 857/*858 * Turns off UART.859 */860static void cls_uart_off(struct jsm_channel *ch)861{862 /* Stop all interrupts from accurring. */863 writeb(0, &ch->ch_cls_uart->ier);864}865 866/*867 * cls_send_break.868 * Starts sending a break thru the UART.869 *870 * The channel lock MUST be held by the calling function.871 */872static void cls_send_break(struct jsm_channel *ch)873{874 /* Tell the UART to start sending the break */875 if (!(ch->ch_flags & CH_BREAK_SENDING)) {876 u8 temp = readb(&ch->ch_cls_uart->lcr);877 878 writeb((temp | UART_LCR_SBC), &ch->ch_cls_uart->lcr);879 ch->ch_flags |= (CH_BREAK_SENDING);880 }881}882 883struct board_ops jsm_cls_ops = {884 .intr = cls_intr,885 .uart_init = cls_uart_init,886 .uart_off = cls_uart_off,887 .param = cls_param,888 .assert_modem_signals = cls_assert_modem_signals,889 .flush_uart_write = cls_flush_uart_write,890 .flush_uart_read = cls_flush_uart_read,891 .disable_receiver = cls_disable_receiver,892 .enable_receiver = cls_enable_receiver,893 .send_break = cls_send_break,894 .clear_break = cls_clear_break,895 .send_start_character = cls_send_start_character,896 .send_stop_character = cls_send_stop_character,897 .copy_data_from_queue_to_uart = cls_copy_data_from_queue_to_uart,898};899 900