Exemplo n.º 1
0
AROS_UFH3(void, serialunit_receive_data,
          AROS_UFHA(APTR, iD, A1),
          AROS_UFHA(APTR, iC, A5),
          AROS_UFHA(struct ExecBase *, SysBase, A6))
{
    AROS_USERFUNC_INIT

    struct HIDDSerialUnitData * data = iD;
    int len = 0;
    UBYTE buffer[READBUFFER_SIZE];

    /*
    ** Read the data from the port ...
    */
    do
    {
        buffer[len++] = serial_inp(data, UART_RX);
    }
    while (serial_inp(data, UART_LSR) & UART_LSR_DR);

    /*
    ** ... and deliver them to whoever is interested.
    */

    if (NULL != data->DataReceivedCallBack)
        data->DataReceivedCallBack(buffer, len, data->unitnum, data->DataReceivedUserData);

    return;

    AROS_USERFUNC_EXIT
}
Exemplo n.º 2
0
static void common_serial_int_handler(HIDDT_IRQ_Handler *irq,
                                      HIDDT_IRQ_HwInfo *hw,
                                      ULONG unitnum)
{
    UBYTE code = UART_IIR_NO_INT;

    if (csd->units[unitnum])
        code = serial_inp(csd->units[unitnum], UART_IIR) & 0x07;

    switch (code)
    {
    case UART_IIR_RLSI:
        (void)serial_inp(csd->units[unitnum], UART_LSR);
        break;

    case UART_IIR_RDI:
        if (csd->units[unitnum]) {
            AROS_UFC3(void, serialunit_receive_data,
                      AROS_UFCA(APTR               , csd->units[unitnum], A1),
                      AROS_UFCA(APTR               , NULL   , A5),
                      AROS_UFCA(struct ExecBase *  , SysBase, A6));
        }
        break;

    case UART_IIR_MSI:
        (void)serial_inp(csd->units[unitnum], UART_MSR);
        break;

    case UART_IIR_THRI:
        if (csd->units[unitnum])
            if (0 == serialunit_write_more_data(csd->units[unitnum], NULL, SysBase))
                (void)serial_inp(csd->units[unitnum], UART_IIR);
        break;
    }
Exemplo n.º 3
0
/******* SerialUnit::Write() **********************************/
ULONG PCSerUnit__Hidd_SerialUnit__Write(OOP_Class *cl, OOP_Object *o, struct pHidd_SerialUnit_Write *msg)
{
    struct HIDDSerialUnitData * data = OOP_INST_DATA(cl, o);
    unsigned char status;
    ULONG len = msg->Length;
    ULONG count = 0;

    EnterFunc(bug("SerialUnit::Write()\n"));

    /*
     * If the output is currently stopped just don't do anything here.
     */
    if (TRUE == data->stopped)
        return 0;

    status = serial_inp(data, UART_LSR);

    if (status & UART_LSR_THRE)
    {
        /* write data into FIFO */
        do
        {
            serial_outp(data, UART_TX, msg->Outbuffer[count++]);
            len--;
        } while (len > 0 && serial_inp(data, UART_LSR & UART_LSR_TEMT));
    }

    ReturnInt("SerialUnit::Write()",ULONG, count);
}
Exemplo n.º 4
0
/*
 * This routine will shutdown a serial port; interrupts are disabled, and
 * DTR is dropped if the hangup on close termio flag is on.
 */
static void mshutdown(struct IsdnCardState *cs)
{

#ifdef SERIAL_DEBUG_OPEN
;
#endif
	
	/*
	 * clear delta_msr_wait queue to avoid mem leaks: we may free the irq
	 * here so the queue might never be waken up
	 */

	cs->hw.elsa.IER = 0;
	serial_outp(cs, UART_IER, 0x00);	/* disable all intrs */
	cs->hw.elsa.MCR &= ~UART_MCR_OUT2;
	
	/* disable break condition */
	serial_outp(cs, UART_LCR, serial_inp(cs, UART_LCR) & ~UART_LCR_SBC);
	
	cs->hw.elsa.MCR &= ~(UART_MCR_DTR|UART_MCR_RTS);
	serial_outp(cs, UART_MCR, cs->hw.elsa.MCR);

	/* disable FIFO's */	
	serial_outp(cs, UART_FCR, (UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT));
	serial_inp(cs, UART_RX);    /* read data port to reset things */
	
#ifdef SERIAL_DEBUG_OPEN
;
#endif
}
Exemplo n.º 5
0
static void rs_interrupt_elsa(struct IsdnCardState *cs)
{
	int status, iir, msr;
	int pass_counter = 0;
	
#ifdef SERIAL_DEBUG_INTR
;
#endif

	do {
		status = serial_inp(cs, UART_LSR);
		debugl1(cs,"rs LSR %02x", status);
#ifdef SERIAL_DEBUG_INTR
;
#endif
		if (status & UART_LSR_DR)
			receive_chars(cs, &status);
		if (status & UART_LSR_THRE)
			transmit_chars(cs, NULL);
		if (pass_counter++ > RS_ISR_PASS_LIMIT) {
;
			break;
		}
		iir = serial_inp(cs, UART_IIR);
		debugl1(cs,"rs IIR %02x", iir);
		if ((iir & 0xf) == 0) {
			msr = serial_inp(cs, UART_MSR);
			debugl1(cs,"rs MSR %02x", msr);
		}
	} while (!(iir & UART_IIR_NO_INT));
#ifdef SERIAL_DEBUG_INTR
;
#endif
}
Exemplo n.º 6
0
/*
 * This routine will shutdown a serial port; interrupts are disabled, and
 * DTR is dropped if the hangup on close termio flag is on.
 */
static void mshutdown(struct IsdnCardState *cs)
{
	unsigned long	flags;


#ifdef SERIAL_DEBUG_OPEN
	printk(KERN_DEBUG"Shutting down serial ....");
#endif
	
	save_flags(flags); cli(); /* Disable interrupts */

	/*
	 * clear delta_msr_wait queue to avoid mem leaks: we may free the irq
	 * here so the queue might never be waken up
	 */

	cs->hw.elsa.IER = 0;
	serial_outp(cs, UART_IER, 0x00);	/* disable all intrs */
	cs->hw.elsa.MCR &= ~UART_MCR_OUT2;
	
	/* disable break condition */
	serial_outp(cs, UART_LCR, serial_inp(cs, UART_LCR) & ~UART_LCR_SBC);
	
	cs->hw.elsa.MCR &= ~(UART_MCR_DTR|UART_MCR_RTS);
	serial_outp(cs, UART_MCR, cs->hw.elsa.MCR);

	/* disable FIFO's */	
	serial_outp(cs, UART_FCR, (UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT));
	serial_inp(cs, UART_RX);    /* read data port to reset things */
	
	restore_flags(flags);
#ifdef SERIAL_DEBUG_OPEN
	printk(" done\n");
#endif
}
Exemplo n.º 7
0
/* Check if there is a byte ready at the serial port */
static int get_serial_char(void)
{
	unsigned char ch;

	if (kdb_serial.iobase == 0)
		return -1;

	if (serial_inp(&kdb_serial, UART_LSR) & UART_LSR_DR) {
		ch = serial_inp(&kdb_serial, UART_RX);
		if (ch == 0x7f)
			ch = 8;
		return ch;
	}
	return -1;
}
Exemplo n.º 8
0
static irqreturn_t
elsa_interrupt_ipac(int intno, void *dev_id, struct pt_regs *regs)
{
	struct IsdnCardState *cs = dev_id;
	u8 val;

	if (!cs) {
		printk(KERN_WARNING "Elsa: Spurious interrupt!\n");
		return IRQ_NONE;
	}
	if (cs->subtyp == ELSA_QS1000PCI || cs->subtyp == ELSA_QS3000PCI) {
		val = bytein(cs->hw.elsa.cfg + 0x4c); /* PCI IRQ */
		if (!test_bit(FLG_BUGGY_PLX9050, &cs->HW_Flags) && 
		    !(val & ELSA_PCI_IRQ_MASK))
			return IRQ_NONE;
	}
#if ARCOFI_USE
	if (cs->hw.elsa.MFlag) {
		val = serial_inp(cs, UART_IIR);
		if (!(val & UART_IIR_NO_INT)) {
			debugl1(cs,"IIR %02x", val);
			spin_lock(&cs->lock);
			rs_interrupt_elsa(intno, cs);
			spin_unlock(&cs->lock);
		}
	}
#endif
	return ipac_irq(intno, dev_id, regs);
}
Exemplo n.º 9
0
/*
 * This routine is called to set the UART divisor registers to match
 * the specified baud rate for a serial port.
 */
static void change_speed(struct IsdnCardState *cs, int baud)
{
	int	quot = 0, baud_base;
	unsigned cval, fcr = 0;


	/* byte size and parity */
	cval = 0x03;
	/* Determine divisor based on baud rate */
	baud_base = BASE_BAUD;
	quot = baud_base / baud;
	/* If the quotient is ever zero, default to 9600 bps */
	if (!quot)
		quot = baud_base / 9600;

	/* Set up FIFO's */
	if ((baud_base / quot) < 2400)
		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1;
	else
		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_8;
	serial_outp(cs, UART_FCR, fcr);
	/* CTS flow control flag and modem status interrupts */
	cs->hw.elsa.IER &= ~UART_IER_MSI;
	cs->hw.elsa.IER |= UART_IER_MSI;
	serial_outp(cs, UART_IER, cs->hw.elsa.IER);

	debugl1(cs,"modem quot=0x%x", quot);
	serial_outp(cs, UART_LCR, cval | UART_LCR_DLAB);/* set DLAB */
	serial_outp(cs, UART_DLL, quot & 0xff);		/* LS of divisor */
	serial_outp(cs, UART_DLM, quot >> 8);		/* MS of divisor */
	serial_outp(cs, UART_LCR, cval);		/* reset DLAB */
	serial_inp(cs, UART_RX);
}
Exemplo n.º 10
0
Arquivo: elsa.c Projeto: nhanh0/hah
static void
elsa_interrupt_ipac(int intno, void *dev_id, struct pt_regs *regs)
{
	struct IsdnCardState *cs = dev_id;
	u_char ista,val;
	int icnt=5;

	if (!cs) {
		printk(KERN_WARNING "Elsa: Spurious interrupt!\n");
		return;
	}
	if (cs->subtyp == ELSA_QS1000PCI || cs->subtyp == ELSA_QS3000PCI) {
		val = bytein(cs->hw.elsa.cfg + 0x4c); /* PCI IRQ */
		if (!(val & ELSA_PCI_IRQ_MASK))
			return;
	}
#if ARCOFI_USE
	if (cs->hw.elsa.MFlag) {
		val = serial_inp(cs, UART_IIR);
		if (!(val & UART_IIR_NO_INT)) {
			debugl1(cs,"IIR %02x", val);
			rs_interrupt_elsa(intno, cs);
		}
	}
#endif
	ista = readreg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ISTA);
Start_IPAC:
	if (cs->debug & L1_DEB_IPAC)
		debugl1(cs, "IPAC ISTA %02X", ista);
	if (ista & 0x0f) {
		val = readreg(cs->hw.elsa.ale, cs->hw.elsa.hscx, HSCX_ISTA + 0x40);
		if (ista & 0x01)
			val |= 0x01;
		if (ista & 0x04)
			val |= 0x02;
		if (ista & 0x08)
			val |= 0x04;
		if (val)
			hscx_int_main(cs, val);
	}
	if (ista & 0x20) {
		val = 0xfe & readreg(cs->hw.elsa.ale, cs->hw.elsa.isac, ISAC_ISTA + 0x80);
		if (val) {
			isac_interrupt(cs, val);
		}
	}
	if (ista & 0x10) {
		val = 0x01;
		isac_interrupt(cs, val);
	}
	ista  = readreg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ISTA);
	if ((ista & 0x3f) && icnt) {
		icnt--;
		goto Start_IPAC;
	}
	if (!icnt)
		printk(KERN_WARNING "ELSA IRQ LOOP\n");
	writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_MASK, 0xFF);
	writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_MASK, 0xC0);
}
Exemplo n.º 11
0
static irqreturn_t
elsa_interrupt(int intno, void *dev_id, struct pt_regs *regs)
{
	struct IsdnCardState *cs = dev_id;
	u8 val;

	if ((cs->typ == ISDN_CTYPE_ELSA_PCMCIA) && (*cs->busy_flag == 1)) {
	/* The card tends to generate interrupts while being removed
	   causing us to just crash the kernel. bad. */
		printk(KERN_WARNING "Elsa: card not available!\n");
		return IRQ_NONE;
	}
#if ARCOFI_USE
	if (cs->hw.elsa.MFlag) {
		val = serial_inp(cs, UART_IIR);
		if (!(val & UART_IIR_NO_INT)) {
			debugl1(cs,"IIR %02x", val);
			spin_lock(&cs->lock);
			rs_interrupt_elsa(intno, cs);
			spin_unlock(&cs->lock);
		}
	}
#endif
	hscxisac_irq(intno, dev_id, regs);

	if (cs->hw.elsa.status & ELSA_TIMER_AKTIV) {
		if (!TimerRun(cs)) {
			/* Timer Restart */
			byteout(cs->hw.elsa.timer, 0);
			cs->hw.elsa.counter++;
		}
	}
#if ARCOFI_USE
	if (cs->hw.elsa.MFlag) {
		val = serial_inp(cs, UART_MCR);
		val ^= 0x8;
		serial_outp(cs, UART_MCR, val);
		val = serial_inp(cs, UART_MCR);
		val ^= 0x8;
		serial_outp(cs, UART_MCR, val);
	}
#endif
	if (cs->hw.elsa.trig)
		byteout(cs->hw.elsa.trig, 0x00);
	return IRQ_HANDLED;
}
Exemplo n.º 12
0
/****** SerialUnit::GetStatus ********************************/
UWORD PCSerUnit__Hidd_SerialUnit__GetStatus(OOP_Class * cl, OOP_Object *o, struct pHidd_SerialUnit_GetStatus *msg)
{
    struct HIDDSerialUnitData * data = OOP_INST_DATA(cl, o);
    UWORD status = 0;
    UBYTE msr = serial_inp(data, UART_MSR);
    UBYTE mcr = serial_inp(data, UART_MCR);

    if (msr & UART_MSR_DCD)
        status |= (1<<5);
    if (msr & UART_MSR_DSR)
        status |= (1<<3);
    if (msr & UART_MSR_CTS)
        status |= (1<<4);

    if (mcr & UART_MCR_DTR)
        status |= (1<<7);
    if (mcr & UART_MCR_RTS)
        status |= (1<<6);  /* old RKMs say 'ready to send' */
    return status;
}
Exemplo n.º 13
0
/*
 * This handles the interrupt from one port.
 */
static inline void
serial8250_handle_port(struct uart_8250_port *up, struct pt_regs *regs)
{
	unsigned int status = serial_inp(up, UART_LSR);

	DEBUG_INTR("status = %x...", status);

	if (status & UART_LSR_DR)
		receive_chars(up, &status, regs);
	check_modem_status(up);
	if (status & UART_LSR_THRE)
		transmit_chars(up);
}
Exemplo n.º 14
0
/* Check if there is a byte ready at the serial port */
static int get_serial_char(void)
{
	if (!kdb_tty_driver) {
	  kdb_tty_driver = tty_find_polling_driver("ttyS0", &kdb_tty_line);
	  if (!kdb_tty_driver) return -1;
	}
	return kdb_tty_driver->ops->poll_get_char(kdb_tty_driver, kdb_tty_line);

#if 0
	if (kdb_serial.iobase == 0)
		return -1;


	if (serial_inp(&kdb_serial, UART_LSR) & UART_LSR_DR) {
		ch = serial_inp(&kdb_serial, UART_RX);
		if (ch == 0x7f)
			ch = 8;
		return ch;
	}
	return -1;
#endif
}
Exemplo n.º 15
0
static void serial8250_shutdown(struct uart_port *port)
{
	struct uart_8250_port *up = (struct uart_8250_port *)port;
	unsigned long flags;

	/*
	 * Disable interrupts from this port
	 */
	up->ier = 0;
	serial_outp(up, UART_IER, 0);

	spin_lock_irqsave(&up->port.lock, flags);
	if (up->port.flags & UPF_FOURPORT) {
		/* reset interrupts on the AST Fourport board */
		inb((up->port.iobase & 0xfe0) | 0x1f);
		up->port.mctrl |= TIOCM_OUT1;
	} else
		up->port.mctrl &= ~TIOCM_OUT2;

	serial8250_set_mctrl(&up->port, up->port.mctrl);
	spin_unlock_irqrestore(&up->port.lock, flags);

	/*
	 * Disable break condition and FIFOs
	 */
	serial_out(up, UART_LCR, serial_inp(up, UART_LCR) & ~UART_LCR_SBC);
	serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO |
				  UART_FCR_CLEAR_RCVR |
				  UART_FCR_CLEAR_XMIT);
	serial_outp(up, UART_FCR, 0);

	/*
	 * Read data port to reset things, and then unlink from
	 * the IRQ chain.
	 */
	(void) serial_in(up, UART_RX);

	if (!is_real_interrupt(up->port.irq))
		del_timer_sync(&up->timer);
	else
		serial_unlink_irq_chain(up);
}
Exemplo n.º 16
0
static inline void receive_chars(struct IsdnCardState *cs,
				 int *status)
{
	unsigned char ch;
	struct sk_buff *skb;

	do {
		ch = serial_in(cs, UART_RX);
		if (cs->hw.elsa.rcvcnt >= MAX_MODEM_BUF)
			break;
		cs->hw.elsa.rcvbuf[cs->hw.elsa.rcvcnt++] = ch;
#ifdef SERIAL_DEBUG_INTR
		printk("DR%02x:%02x...", ch, *status);
#endif
		if (*status & (UART_LSR_BI | UART_LSR_PE |
			       UART_LSR_FE | UART_LSR_OE)) {
					
#ifdef SERIAL_DEBUG_INTR
;
#endif
		}
		*status = serial_inp(cs, UART_LSR);
	} while (*status & UART_LSR_DR);
	if (cs->hw.elsa.MFlag == 2) {
		if (!(skb = dev_alloc_skb(cs->hw.elsa.rcvcnt)))
;
		else {
			memcpy(skb_put(skb, cs->hw.elsa.rcvcnt), cs->hw.elsa.rcvbuf, 
				cs->hw.elsa.rcvcnt);
			skb_queue_tail(& cs->hw.elsa.bcs->rqueue, skb);
		}
		schedule_event(cs->hw.elsa.bcs, B_RCVBUFREADY);
	} else {
		char tmp[128];
		char *t = tmp;

		t += sprintf(t, "modem read cnt %d", cs->hw.elsa.rcvcnt);
		QuickHex(t, cs->hw.elsa.rcvbuf, cs->hw.elsa.rcvcnt);
		debugl1(cs, tmp);
	}
	cs->hw.elsa.rcvcnt = 0;
}
Exemplo n.º 17
0
static int serial8250_startup(struct uart_port *port)
{
	struct uart_8250_port *up = (struct uart_8250_port *)port;
	unsigned long flags;
	int retval;

	/*
	 * Clear the FIFO buffers and disable them.
	 * (they will be reeanbled in set_termios())
	 */
	if (uart_config[up->port.type].flags & UART_CLEAR_FIFO) {
		serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
		serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO |
				UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
		serial_outp(up, UART_FCR, 0);
	}

	/*
	 * Clear the interrupt registers.
	 */
	(void) serial_inp(up, UART_LSR);
	(void) serial_inp(up, UART_RX);
	(void) serial_inp(up, UART_IIR);
	(void) serial_inp(up, UART_MSR);

	/*
	 * At this point, there's no way the LSR could still be 0xff;
	 * if it is, then bail out, because there's likely no UART
	 * here.
	 */
	if (!(up->port.flags & UPF_BUGGY_UART) &&
	    (serial_inp(up, UART_LSR) == 0xff)) {
		printk("ttyS%d: LSR safety check engaged!\n", up->port.line);
		return -ENODEV;
	}

	retval = serial_link_irq_chain(up);
		if (retval)
			return retval;

	/*
	 * Now, initialize the UART
	 */
	serial_outp(up, UART_LCR, UART_LCR_WLEN8);

	spin_lock_irqsave(&up->port.lock, flags);
	if (up->port.flags & UPF_FOURPORT) {
		if (!is_real_interrupt(up->port.irq))
			up->port.mctrl |= TIOCM_OUT1;
	} else
		/*
		 * Most PC uarts need OUT2 raised to enable interrupts.
		 */
		if (is_real_interrupt(up->port.irq))
			up->port.mctrl |= TIOCM_OUT2;

	serial8250_set_mctrl(&up->port, up->port.mctrl);
	spin_unlock_irqrestore(&up->port.lock, flags);

	/*
	 * Finally, enable interrupts.  Note: Modem status interrupts
	 * are set via set_termios(), which will be occurring imminently
	 * anyway, so we don't enable them here.
	 */
	up->ier = UART_IER_RLSI | UART_IER_RDI;
	serial_outp(up, UART_IER, up->ier);

	if (up->port.flags & UPF_FOURPORT) {
		unsigned int icp;
		/*
		 * Enable interrupts on the AST Fourport board
		 */
		icp = (up->port.iobase & 0xfe0) | 0x01f;
		outb_p(0x80, icp);
		(void) inb_p(icp);
	}

	/*
	 * And clear the interrupt registers again for luck.
	 */
	(void) serial_inp(up, UART_LSR);
	(void) serial_inp(up, UART_RX);
	(void) serial_inp(up, UART_IIR);
	(void) serial_inp(up, UART_MSR);

	return 0;
}
Exemplo n.º 18
0
static _INLINE_ void
receive_chars(struct uart_8250_port *up, int *status, struct pt_regs *regs)
{
	struct tty_struct *tty = up->port.info->tty;
	unsigned char ch;
	int max_count = 256;

	do {
		if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) {
			tty->flip.work.func((void *)tty);
			if (tty->flip.count >= TTY_FLIPBUF_SIZE)
				return; // if TTY_DONT_FLIP is set
		}
		ch = serial_inp(up, UART_RX);
		*tty->flip.char_buf_ptr = ch;
		*tty->flip.flag_buf_ptr = TTY_NORMAL;
		up->port.icount.rx++;

		if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE |
				       UART_LSR_FE | UART_LSR_OE))) {
			/*
			 * For statistics only
			 */
			if (*status & UART_LSR_BI) {
				*status &= ~(UART_LSR_FE | UART_LSR_PE);
				up->port.icount.brk++;
				/*
				 * We do the SysRQ and SAK checking
				 * here because otherwise the break
				 * may get masked by ignore_status_mask
				 * or read_status_mask.
				 */
				if (uart_handle_break(&up->port))
					goto ignore_char;
			} else if (*status & UART_LSR_PE)
				up->port.icount.parity++;
			else if (*status & UART_LSR_FE)
				up->port.icount.frame++;
			if (*status & UART_LSR_OE)
				up->port.icount.overrun++;

			/*
			 * Mask off conditions which should be ingored.
			 */
			*status &= up->port.read_status_mask;

#ifdef CONFIG_SERIAL_AU1X00_CONSOLE
			if (up->port.line == up->port.cons->index) {
				/* Recover the break flag from console xmit */
				*status |= up->lsr_break_flag;
				up->lsr_break_flag = 0;
			}
#endif
			if (*status & UART_LSR_BI) {
				DEBUG_INTR("handling break....");
				*tty->flip.flag_buf_ptr = TTY_BREAK;
			} else if (*status & UART_LSR_PE)
				*tty->flip.flag_buf_ptr = TTY_PARITY;
			else if (*status & UART_LSR_FE)
				*tty->flip.flag_buf_ptr = TTY_FRAME;
		}
		if (uart_handle_sysrq_char(&up->port, ch, regs))
			goto ignore_char;
		if ((*status & up->port.ignore_status_mask) == 0) {
			tty->flip.flag_buf_ptr++;
			tty->flip.char_buf_ptr++;
			tty->flip.count++;
		}
		if ((*status & UART_LSR_OE) &&
		    tty->flip.count < TTY_FLIPBUF_SIZE) {
			/*
			 * Overrun is special, since it's reported
			 * immediately, and doesn't affect the current
			 * character.
			 */
			*tty->flip.flag_buf_ptr = TTY_OVERRUN;
			tty->flip.flag_buf_ptr++;
			tty->flip.char_buf_ptr++;
			tty->flip.count++;
		}
	ignore_char:
		*status = serial_inp(up, UART_LSR);
	} while ((*status & UART_LSR_DR) && (max_count-- > 0));
	spin_unlock(&up->port.lock);
	tty_flip_buffer_push(tty);
	spin_lock(&up->port.lock);
}
Exemplo n.º 19
0
static irqreturn_t
elsa_interrupt_ipac(int intno, void *dev_id)
{
	struct IsdnCardState *cs = dev_id;
	u_long flags;
	u_char ista,val;
	int icnt=5;

	spin_lock_irqsave(&cs->lock, flags);
	if (cs->subtyp == ELSA_QS1000PCI || cs->subtyp == ELSA_QS3000PCI) {
		val = bytein(cs->hw.elsa.cfg + 0x4c); /* PCI IRQ */
		if (!(val & ELSA_PCI_IRQ_MASK)) {
			spin_unlock_irqrestore(&cs->lock, flags);
			return IRQ_NONE;
		}
	}
#if ARCOFI_USE
	if (cs->hw.elsa.MFlag) {
		val = serial_inp(cs, UART_IIR);
		if (!(val & UART_IIR_NO_INT)) {
			debugl1(cs,"IIR %02x", val);
			rs_interrupt_elsa(cs);
		}
	}
#endif
	ista = readreg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ISTA);
Start_IPAC:
	if (cs->debug & L1_DEB_IPAC)
		debugl1(cs, "IPAC ISTA %02X", ista);
	if (ista & 0x0f) {
		val = readreg(cs->hw.elsa.ale, cs->hw.elsa.hscx, HSCX_ISTA + 0x40);
		if (ista & 0x01)
			val |= 0x01;
		if (ista & 0x04)
			val |= 0x02;
		if (ista & 0x08)
			val |= 0x04;
		if (val)
			hscx_int_main(cs, val);
	}
	if (ista & 0x20) {
		val = 0xfe & readreg(cs->hw.elsa.ale, cs->hw.elsa.isac, ISAC_ISTA + 0x80);
		if (val) {
			isac_interrupt(cs, val);
		}
	}
	if (ista & 0x10) {
		val = 0x01;
		isac_interrupt(cs, val);
	}
	ista  = readreg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ISTA);
	if ((ista & 0x3f) && icnt) {
		icnt--;
		goto Start_IPAC;
	}
	if (!icnt)
#ifdef CONFIG_DEBUG_PRINTK
		printk(KERN_WARNING "ELSA IRQ LOOP\n");
#else
		;
#endif
	writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_MASK, 0xFF);
	writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_MASK, 0xC0);
	spin_unlock_irqrestore(&cs->lock, flags);
	return IRQ_HANDLED;
}
Exemplo n.º 20
0
static int mstartup(struct IsdnCardState *cs)
{
	int	retval=0;

	/*
	 * Clear the FIFO buffers and disable them
	 * (they will be reenabled in change_speed())
	 */
	serial_outp(cs, UART_FCR, (UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT));

	/*
	 * At this point there's no way the LSR could still be 0xFF;
	 * if it is, then bail out, because there's likely no UART
	 * here.
	 */
	if (serial_inp(cs, UART_LSR) == 0xff) {
		retval = -ENODEV;
		goto errout;
	}
	
	/*
	 * Clear the interrupt registers.
	 */
	(void) serial_inp(cs, UART_RX);
	(void) serial_inp(cs, UART_IIR);
	(void) serial_inp(cs, UART_MSR);

	/*
	 * Now, initialize the UART 
	 */
	serial_outp(cs, UART_LCR, UART_LCR_WLEN8);	/* reset DLAB */

	cs->hw.elsa.MCR = 0;
	cs->hw.elsa.MCR = UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2;
	serial_outp(cs, UART_MCR, cs->hw.elsa.MCR);
	
	/*
	 * Finally, enable interrupts
	 */
	cs->hw.elsa.IER = UART_IER_MSI | UART_IER_RLSI | UART_IER_RDI;
	serial_outp(cs, UART_IER, cs->hw.elsa.IER);	/* enable interrupts */
	
	/*
	 * And clear the interrupt registers again for luck.
	 */
	(void)serial_inp(cs, UART_LSR);
	(void)serial_inp(cs, UART_RX);
	(void)serial_inp(cs, UART_IIR);
	(void)serial_inp(cs, UART_MSR);

	cs->hw.elsa.transcnt = cs->hw.elsa.transp = 0;
	cs->hw.elsa.rcvcnt = cs->hw.elsa.rcvp =0;

	/*
	 * and set the speed of the serial port
	 */
	change_speed(cs, BASE_BAUD);
	cs->hw.elsa.MFlag = 1;
errout:
	return retval;
}
Exemplo n.º 21
0
static irqreturn_t
elsa_interrupt(int intno, void *dev_id, struct pt_regs *regs)
{
	struct IsdnCardState *cs = dev_id;
	u_long flags;
	u_char val;
	int icnt=5;

	if ((cs->typ == ISDN_CTYPE_ELSA_PCMCIA) && (*cs->busy_flag == 1)) {
	/* The card tends to generate interrupts while being removed
	   causing us to just crash the kernel. bad. */
		printk(KERN_WARNING "Elsa: card not available!\n");
		return IRQ_NONE;
	}
	spin_lock_irqsave(&cs->lock, flags);
#if ARCOFI_USE
	if (cs->hw.elsa.MFlag) {
		val = serial_inp(cs, UART_IIR);
		if (!(val & UART_IIR_NO_INT)) {
			debugl1(cs,"IIR %02x", val);
			rs_interrupt_elsa(intno, cs);
		}
	}
#endif
	val = readreg(cs->hw.elsa.ale, cs->hw.elsa.hscx, HSCX_ISTA + 0x40);
      Start_HSCX:
	if (val) {
		hscx_int_main(cs, val);
	}
	val = readreg(cs->hw.elsa.ale, cs->hw.elsa.isac, ISAC_ISTA);
      Start_ISAC:
	if (val) {
		isac_interrupt(cs, val);
	}
	val = readreg(cs->hw.elsa.ale, cs->hw.elsa.hscx, HSCX_ISTA + 0x40);
	if (val && icnt) {
		if (cs->debug & L1_DEB_HSCX)
			debugl1(cs, "HSCX IntStat after IntRoutine");
		icnt--;
		goto Start_HSCX;
	}
	val = readreg(cs->hw.elsa.ale, cs->hw.elsa.isac, ISAC_ISTA);
	if (val && icnt) {
		if (cs->debug & L1_DEB_ISAC)
			debugl1(cs, "ISAC IntStat after IntRoutine");
		icnt--;
		goto Start_ISAC;
	}
	if (!icnt)
		printk(KERN_WARNING"ELSA IRQ LOOP\n");
	writereg(cs->hw.elsa.ale, cs->hw.elsa.hscx, HSCX_MASK, 0xFF);
	writereg(cs->hw.elsa.ale, cs->hw.elsa.hscx, HSCX_MASK + 0x40, 0xFF);
	writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, ISAC_MASK, 0xFF);
	if (cs->hw.elsa.status & ELSA_TIMER_AKTIV) {
		if (!TimerRun(cs)) {
			/* Timer Restart */
			byteout(cs->hw.elsa.timer, 0);
			cs->hw.elsa.counter++;
		}
	}
#if ARCOFI_USE
	if (cs->hw.elsa.MFlag) {
		val = serial_inp(cs, UART_MCR);
		val ^= 0x8;
		serial_outp(cs, UART_MCR, val);
		val = serial_inp(cs, UART_MCR);
		val ^= 0x8;
		serial_outp(cs, UART_MCR, val);
	}
#endif
	if (cs->hw.elsa.trig)
		byteout(cs->hw.elsa.trig, 0x00);
	writereg(cs->hw.elsa.ale, cs->hw.elsa.hscx, HSCX_MASK, 0x0);
	writereg(cs->hw.elsa.ale, cs->hw.elsa.hscx, HSCX_MASK + 0x40, 0x0);
	writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, ISAC_MASK, 0x0);
	spin_unlock_irqrestore(&cs->lock, flags);
	return IRQ_HANDLED;
}
Exemplo n.º 22
0
/******* SerialUnit::New() ***********************************/
OOP_Object *PCSerUnit__Root__New(OOP_Class *cl, OOP_Object *obj, struct pRoot_New *msg)
{
    struct HIDDSerialUnitData * data;
    struct TagItem *tag, *tstate;
    ULONG unitnum = 0;

    EnterFunc(bug("SerialUnit::New()\n"));

    tstate = msg->attrList;
    while ((tag = NextTagItem((const struct TagItem **)&tstate)))
    {
        ULONG idx;

#define csd CSD(cl->UserData)
        if (IS_HIDDSERIALUNIT_ATTR(tag->ti_Tag, idx))
#undef csd
        {
            switch (idx)
            {
            case aoHidd_SerialUnit_Unit:
                unitnum = (ULONG)tag->ti_Data;
                break;
            }
        }

    } /* while (tags to process) */

    obj = (OOP_Object *)OOP_DoSuperMethod(cl, obj, (OOP_Msg)msg);

    if (obj)
    {
        struct IntuitionBase * IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",0);
        data = OOP_INST_DATA(cl, obj);

        data->baseaddr = bases[unitnum];

        if (NULL != IntuitionBase) {
            struct Preferences prefs;
            GetPrefs(&prefs,sizeof(prefs));
            data->baudrate      = prefs.BaudRate;
            adapt_data(data, &prefs);
            CloseLibrary((struct Library *)IntuitionBase);
        } else {
            data->datalength = 8;
            data->parity     = FALSE;
            data->baudrate   = 9600; /* will be initialize in set_baudrate() */
        }
        data->unitnum    = unitnum;

        Disable();
        CSD(cl->UserData)->units[data->unitnum] = data;
        Enable();

        D(bug("Unit %d at 0x0%x\n", data->unitnum, data->baseaddr));

        /* Wake up UART */
        serial_outp(data, UART_LCR, 0xBF);
        serial_outp(data, UART_EFR, UART_EFR_ECB);
        serial_outp(data, UART_IER, 0);
        serial_outp(data, UART_EFR, 0);
        serial_outp(data, UART_LCR, 0);

        /* clear the FIFOs */
        serial_outp(data, UART_FCR, (UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT));

        /* clear the interrupt registers */
        (void)serial_inp(data, UART_RX);
        (void)serial_inp(data, UART_IIR);
        (void)serial_inp(data, UART_MSR);

        /* initilize the UART */
        serial_outp(data, UART_LCR, get_lcr(data));

        serial_outp(data, UART_MCR, UART_MCR_OUT2 | UART_MCR_DTR | UART_MCR_RTS);
        serial_outp(data, UART_IER, UART_IER_RDI | UART_IER_THRI | UART_IER_RLSI | UART_IER_MSI);

        /* clear the interrupt registers again ... */
        (void)serial_inp(data, UART_LSR);
        (void)serial_inp(data, UART_RX);
        (void)serial_inp(data, UART_IIR);
        (void)serial_inp(data, UART_MSR);

        set_baudrate(data, data->baudrate);
    } /* if (obj) */

    ReturnPtr("SerialUnit::New()", OOP_Object *, obj);
}