+
+// added by James 03-12-2004.
+/*
+ * mxser_rs_break() --- routine which turns the break handling on or off
+ */
+static void mxser_rs_break(struct tty_struct *tty, int break_state)
+{
+ struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
+ unsigned long flags;
+
+ spin_lock_irqsave(&info->slock, flags);
+ if (break_state == -1)
+ outb(inb(info->base + UART_LCR) | UART_LCR_SBC, info->base + UART_LCR);
+ else
+ outb(inb(info->base + UART_LCR) & ~UART_LCR_SBC, info->base + UART_LCR);
+ spin_unlock_irqrestore(&info->slock, flags);
+}
+
+// (above) added by James.
+
+
+/*
+ * This is the serial driver's generic interrupt routine
+ */
+static irqreturn_t mxser_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ int status, iir, i;
+ struct mxser_struct *info;
+ struct mxser_struct *port;
+ int max, irqbits, bits, msr;
+ int pass_counter = 0;
+ int handled = IRQ_NONE;
+
+ port = NULL;
+ //spin_lock(&gm_lock);
+
+ for (i = 0; i < MXSER_BOARDS; i++) {
+ if (dev_id == &(mxvar_table[i * MXSER_PORTS_PER_BOARD])) {
+ port = dev_id;
+ break;
+ }
+ }
+
+ if (i == MXSER_BOARDS) {
+ goto irq_stop;
+ }
+ if (port == 0) {
+ goto irq_stop;
+ }
+ max = mxser_numports[mxsercfg[i].board_type - 1];
+ while (1) {
+ irqbits = inb(port->vector) & port->vectormask;
+ if (irqbits == port->vectormask) {
+ break;
+ }
+
+ handled = IRQ_HANDLED;
+ for (i = 0, bits = 1; i < max; i++, irqbits |= bits, bits <<= 1) {
+ if (irqbits == port->vectormask) {
+ break;
+ }
+ if (bits & irqbits)
+ continue;
+ info = port + i;
+
+ // following add by Victor Yu. 09-13-2002
+ iir = inb(info->base + UART_IIR);
+ if (iir & UART_IIR_NO_INT)
+ continue;
+ iir &= MOXA_MUST_IIR_MASK;
+ if (!info->tty) {
+ status = inb(info->base + UART_LSR);
+ outb(0x27, info->base + UART_FCR);
+ inb(info->base + UART_MSR);
+ continue;
+ }
+ // above add by Victor Yu. 09-13-2002
+ /*
+ if ( info->tty->flip.count < TTY_FLIPBUF_SIZE/4 ){
+ info->IER |= MOXA_MUST_RECV_ISR;
+ outb(info->IER, info->base + UART_IER);
+ }
+ */
+
+
+ /* mask by Victor Yu. 09-13-2002
+ if ( !info->tty ||
+ (inb(info->base + UART_IIR) & UART_IIR_NO_INT) )
+ continue;
+ */
+ /* mask by Victor Yu. 09-02-2002
+ status = inb(info->base + UART_LSR) & info->read_status_mask;
+ */
+
+ // following add by Victor Yu. 09-02-2002
+ status = inb(info->base + UART_LSR);
+
+ if (status & UART_LSR_PE) {
+ info->err_shadow |= NPPI_NOTIFY_PARITY;
+ }
+ if (status & UART_LSR_FE) {
+ info->err_shadow |= NPPI_NOTIFY_FRAMING;
+ }
+ if (status & UART_LSR_OE) {
+ info->err_shadow |= NPPI_NOTIFY_HW_OVERRUN;
+ }
+ if (status & UART_LSR_BI)
+ info->err_shadow |= NPPI_NOTIFY_BREAK;
+
+ if (info->IsMoxaMustChipFlag) {
+ /*
+ if ( (status & 0x02) && !(status & 0x01) ) {
+ outb(info->base+UART_FCR, 0x23);
+ continue;
+ }
+ */
+ if (iir == MOXA_MUST_IIR_GDA || iir == MOXA_MUST_IIR_RDA || iir == MOXA_MUST_IIR_RTO || iir == MOXA_MUST_IIR_LSR)
+ mxser_receive_chars(info, &status);
+
+ } else {
+ // above add by Victor Yu. 09-02-2002
+
+ status &= info->read_status_mask;
+ if (status & UART_LSR_DR)
+ mxser_receive_chars(info, &status);
+ }
+ msr = inb(info->base + UART_MSR);
+ if (msr & UART_MSR_ANY_DELTA) {
+ mxser_check_modem_status(info, msr);
+ }
+ // following add by Victor Yu. 09-13-2002
+ if (info->IsMoxaMustChipFlag) {
+ if ((iir == 0x02) && (status & UART_LSR_THRE)) {
+ mxser_transmit_chars(info);
+ }
+ } else {
+ // above add by Victor Yu. 09-13-2002
+
+ if (status & UART_LSR_THRE) {
+/* 8-2-99 by William
+ if ( info->x_char || (info->xmit_cnt > 0) )
+*/
+ mxser_transmit_chars(info);
+ }
+ }
+ }
+ if (pass_counter++ > MXSER_ISR_PASS_LIMIT) {
+ break; /* Prevent infinite loops */
+ }
+ }
+
+ irq_stop:
+ //spin_unlock(&gm_lock);
+ return handled;
+}
+
+static void mxser_receive_chars(struct mxser_struct *info, int *status)