brintos

brintos / linux-shallow public Read only

0
0
Text · 22.5 KiB · 6e40792 Raw
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