Exemplo n.º 1
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.º 2
0
static inline void transmit_chars(struct IsdnCardState *cs, int *intr_done)
{
	int count;
	
	debugl1(cs, "transmit_chars: p(%x) cnt(%x)", cs->hw.elsa.transp, 
		cs->hw.elsa.transcnt);
	
	if (cs->hw.elsa.transcnt <= 0) {
		cs->hw.elsa.IER &= ~UART_IER_THRI;
		serial_out(cs, UART_IER, cs->hw.elsa.IER);
		return;
	}
	count = 16;
	do {
		serial_outp(cs, UART_TX, cs->hw.elsa.transbuf[cs->hw.elsa.transp++]);
		if (cs->hw.elsa.transp >= MAX_MODEM_BUF)
			cs->hw.elsa.transp=0;
		if (--cs->hw.elsa.transcnt <= 0)
			break;
	} while (--count > 0);
	if ((cs->hw.elsa.transcnt < WAKEUP_CHARS) && (cs->hw.elsa.MFlag==2))
		modem_fill(cs->hw.elsa.bcs);

#ifdef SERIAL_DEBUG_INTR
;
#endif
	if (intr_done)
		*intr_done = 0;
	if (cs->hw.elsa.transcnt <= 0) {
		cs->hw.elsa.IER &= ~UART_IER_THRI;
		serial_outp(cs, UART_IER, cs->hw.elsa.IER);
	}
}
Exemplo n.º 3
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.º 4
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.º 5
0
static void
modem_write_cmd(struct IsdnCardState *cs, u_char *buf, int len) {
	int count, fp;
	u_char *msg = buf;
	
	if (!len)
		return;
	if (len > (MAX_MODEM_BUF - cs->hw.elsa.transcnt)) {
		return;
	}
	fp = cs->hw.elsa.transcnt + cs->hw.elsa.transp;
	fp &= (MAX_MODEM_BUF -1);
	count = len;
	if (count > MAX_MODEM_BUF - fp) {
		count = MAX_MODEM_BUF - fp;
		memcpy(cs->hw.elsa.transbuf + fp, msg, count);
		cs->hw.elsa.transcnt += count;
		msg += count;
		count = len - count;
		fp = 0;
	}
	memcpy(cs->hw.elsa.transbuf + fp, msg, count);
	cs->hw.elsa.transcnt += count;
	if (cs->hw.elsa.transcnt && 
	    !(cs->hw.elsa.IER & UART_IER_THRI)) {
		cs->hw.elsa.IER |= UART_IER_THRI;
		serial_outp(cs, UART_IER, cs->hw.elsa.IER);
	}
}
Exemplo n.º 6
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.º 7
0
static _INLINE_ void transmit_chars(struct uart_8250_port *up)
{
	struct circ_buf *xmit = &up->port.info->xmit;
	int count;

	if (up->port.x_char) {
		serial_outp(up, UART_TX, up->port.x_char);
		up->port.icount.tx++;
		up->port.x_char = 0;
		return;
	}
	if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
		serial8250_stop_tx(&up->port);
		return;
	}

	count = up->port.fifosize;
	do {
		serial_out(up, UART_TX, xmit->buf[xmit->tail]);
		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
		up->port.icount.tx++;
		if (uart_circ_empty(xmit))
			break;
	} while (--count > 0);

	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
		uart_write_wakeup(&up->port);

	DEBUG_INTR("THRE...");

	if (uart_circ_empty(xmit))
		serial8250_stop_tx(&up->port);
}
Exemplo n.º 8
0
void
modem_write_cmd(struct IsdnCardState *cs, u8 *buf, u_int len) {
	u_int count, fp;
	u8 *msg = buf;
	unsigned long flags;
	
	if (!len)
		return;
	spin_lock_irqsave(&elsa_ser_lock, flags);
	if (len > (MAX_MODEM_BUF - cs->hw.elsa.transcnt)) {
		spin_unlock_irqrestore(&elsa_ser_lock, flags);
		return;
	}
	fp = cs->hw.elsa.transcnt + cs->hw.elsa.transp;
	fp &= (MAX_MODEM_BUF -1);
	count = len;
	if (count > MAX_MODEM_BUF - fp) {
		count = MAX_MODEM_BUF - fp;
		memcpy(cs->hw.elsa.transbuf + fp, msg, count);
		cs->hw.elsa.transcnt += count;
		msg += count;
		count = len - count;
		fp = 0;
	}
	memcpy(cs->hw.elsa.transbuf + fp, msg, count);
	cs->hw.elsa.transcnt += count;
	if (cs->hw.elsa.transcnt && 
	    !(cs->hw.elsa.IER & UART_IER_THRI)) {
		cs->hw.elsa.IER |= UART_IER_THRI;
		serial_outp(cs, UART_IER, cs->hw.elsa.IER);
	}
	spin_unlock_irqrestore(&elsa_ser_lock, flags);
}
Exemplo n.º 9
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.º 10
0
/*
 * This routine is called by rs_init() to initialize a specific serial
 * port.  It determines what type of UART chip this serial port is
 * using: 8250, 16450, 16550, 16550A.  The important question is
 * whether or not this UART is a 16550A or not, since this will
 * determine whether or not we can use its FIFO features or not.
 */
static void autoconfig(struct uart_8250_port *up, unsigned int probeflags)
{
	unsigned char save_lcr, save_mcr;
	unsigned long flags;

	if (!up->port.iobase && !up->port.mapbase && !up->port.membase)
		return;

	DEBUG_AUTOCONF("ttyS%d: autoconf (0x%04x, 0x%08lx): ",
			up->port.line, up->port.iobase, up->port.membase);

	/*
	 * We really do need global IRQs disabled here - we're going to
	 * be frobbing the chips IRQ enable register to see if it exists.
	 */
	spin_lock_irqsave(&up->port.lock, flags);
//	save_flags(flags); cli();

	save_mcr = serial_in(up, UART_MCR);
	save_lcr = serial_in(up, UART_LCR);

	up->port.type = PORT_16550A;
	serial_outp(up, UART_LCR, save_lcr);

	up->port.fifosize = uart_config[up->port.type].dfl_xmit_fifo_size;

	if (up->port.type == PORT_UNKNOWN)
		goto out;

	/*
	 * Reset the UART.
	 */
	serial_outp(up, UART_MCR, save_mcr);
	serial_outp(up, UART_FCR, (UART_FCR_ENABLE_FIFO |
				     UART_FCR_CLEAR_RCVR |
				     UART_FCR_CLEAR_XMIT));
	serial_outp(up, UART_FCR, 0);
	(void)serial_in(up, UART_RX);
	serial_outp(up, UART_IER, 0);

 out:	
	spin_unlock_irqrestore(&up->port.lock, flags);
//	restore_flags(flags);
	DEBUG_AUTOCONF("type=%s\n", uart_config[up->port.type].name);
}
Exemplo n.º 11
0
BOOL set_baudrate(struct HIDDSerialUnitData * data, ULONG speed)
{
    int quot;

    if (!(speed >= 50 && speed <= 115200))
        return FALSE;

    quot = CRYSTAL_SPEED / (speed << 4);

    /* set the speed on the UART now */
    serial_outp(data, UART_LCR, get_lcr(data) | UART_LCR_DLAB);
    serial_outp(data, UART_DLL, quot & 0xff);
    serial_outp(data, UART_DLM, quot >> 8);
    serial_outp(data, UART_LCR, get_lcr(data));
    serial_outp(data, UART_FCR, get_fcr(speed) | UART_FCR_ENABLE_FIFO);

    return TRUE;
}
Exemplo n.º 12
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.º 13
0
/******* SerialUnit::Dispose() ***********************************/
OOP_Object *PCSerUnit__Root__Dispose(OOP_Class *cl, OOP_Object *obj, OOP_Msg msg)
{
    struct HIDDSerialUnitData * data;
    EnterFunc(bug("SerialUnit::Dispose()\n"));

    data = OOP_INST_DATA(cl, obj);

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

    /* stop all interrupts */
    serial_outp(data, UART_IER, 0);

    OOP_DoSuperMethod(cl, obj, (OOP_Msg)msg);
    ReturnPtr("SerialUnit::Dispose()", OOP_Object *, obj);
}
Exemplo n.º 14
0
inline int
write_modem(struct BCState *bcs) {
	int ret=0;
	struct IsdnCardState *cs = bcs->cs;
	int count, len, fp;
	long flags;
	
	if (!bcs->tx_skb)
		return 0;
	if (bcs->tx_skb->len <= 0)
		return 0;
	save_flags(flags);
	cli();
	len = bcs->tx_skb->len;
	if (len > MAX_MODEM_BUF - cs->hw.elsa.transcnt)
		len = MAX_MODEM_BUF - cs->hw.elsa.transcnt;
	fp = cs->hw.elsa.transcnt + cs->hw.elsa.transp;
	fp &= (MAX_MODEM_BUF -1);
	count = len;
	if (count > MAX_MODEM_BUF - fp) {
		count = MAX_MODEM_BUF - fp;
		memcpy(cs->hw.elsa.transbuf + fp, bcs->tx_skb->data, count);
		skb_pull(bcs->tx_skb, count);
		cs->hw.elsa.transcnt += count;
		ret = count;
		count = len - count;
		fp = 0;
	}
	memcpy((cs->hw.elsa.transbuf + fp), bcs->tx_skb->data, count);
	skb_pull(bcs->tx_skb, count);
	cs->hw.elsa.transcnt += count;
	ret += count;
	
	if (cs->hw.elsa.transcnt && 
	    !(cs->hw.elsa.IER & UART_IER_THRI)) {
			cs->hw.elsa.IER |= UART_IER_THRI;
		serial_outp(cs, UART_IER, cs->hw.elsa.IER);
	}
	restore_flags(flags);
	return(ret);
}
Exemplo n.º 15
0
static inline int
write_modem(struct BCState *bcs) {
	int ret=0;
	struct IsdnCardState *cs = bcs->cs;
	int count, len, fp;
	
	if (!bcs->tx_skb)
		return 0;
	if (bcs->tx_skb->len <= 0)
		return 0;
	len = bcs->tx_skb->len;
	if (len > MAX_MODEM_BUF - cs->hw.elsa.transcnt)
		len = MAX_MODEM_BUF - cs->hw.elsa.transcnt;
	fp = cs->hw.elsa.transcnt + cs->hw.elsa.transp;
	fp &= (MAX_MODEM_BUF -1);
	count = len;
	if (count > MAX_MODEM_BUF - fp) {
		count = MAX_MODEM_BUF - fp;
		skb_copy_from_linear_data(bcs->tx_skb,
					  cs->hw.elsa.transbuf + fp, count);
		skb_pull(bcs->tx_skb, count);
		cs->hw.elsa.transcnt += count;
		ret = count;
		count = len - count;
		fp = 0;
	}
	skb_copy_from_linear_data(bcs->tx_skb,
				  cs->hw.elsa.transbuf + fp, count);
	skb_pull(bcs->tx_skb, count);
	cs->hw.elsa.transcnt += count;
	ret += count;
	
	if (cs->hw.elsa.transcnt && 
	    !(cs->hw.elsa.IER & UART_IER_THRI)) {
			cs->hw.elsa.IER |= UART_IER_THRI;
		serial_outp(cs, UART_IER, cs->hw.elsa.IER);
	}
	return(ret);
}
Exemplo n.º 16
0
static void
serial8250_set_termios(struct uart_port *port, struct termios *termios,
		       struct termios *old)
{
	struct uart_8250_port *up = (struct uart_8250_port *)port;
	unsigned char cval, fcr = 0;
	unsigned long flags;
	unsigned int baud, quot;

	switch (termios->c_cflag & CSIZE) {
	case CS5:
		cval = UART_LCR_WLEN5;
		break;
	case CS6:
		cval = UART_LCR_WLEN6;
		break;
	case CS7:
		cval = UART_LCR_WLEN7;
		break;
	default:
	case CS8:
		cval = UART_LCR_WLEN8;
		break;
	}

	if (termios->c_cflag & CSTOPB)
		cval |= UART_LCR_STOP;
	if (termios->c_cflag & PARENB)
		cval |= UART_LCR_PARITY;
	if (!(termios->c_cflag & PARODD))
		cval |= UART_LCR_EPAR;
#ifdef CMSPAR
	if (termios->c_cflag & CMSPAR)
		cval |= UART_LCR_SPAR;
#endif

	/*
	 * Ask the core to calculate the divisor for us.
	 */
	baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); 
	quot = serial8250_get_divisor(port, baud);
	quot = 0x35; /* FIXME */

	/*
	 * Work around a bug in the Oxford Semiconductor 952 rev B
	 * chip which causes it to seriously miscalculate baud rates
	 * when DLL is 0.
	 */
	if ((quot & 0xff) == 0 && up->port.type == PORT_16C950 &&
	    up->rev == 0x5201)
		quot ++;

	if (uart_config[up->port.type].flags & UART_USE_FIFO) {
		if (baud < 2400)
			fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIGGER_1;
		else
			fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIGGER_8;
	}

	/*
	 * Ok, we're now changing the port state.  Do it with
	 * interrupts disabled.
	 */
	spin_lock_irqsave(&up->port.lock, flags);

	/*
	 * Update the per-port timeout.
	 */
	uart_update_timeout(port, termios->c_cflag, baud);

	up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
	if (termios->c_iflag & INPCK)
		up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE;
	if (termios->c_iflag & (BRKINT | PARMRK))
		up->port.read_status_mask |= UART_LSR_BI;

	/*
	 * Characteres to ignore
	 */
	up->port.ignore_status_mask = 0;
	if (termios->c_iflag & IGNPAR)
		up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
	if (termios->c_iflag & IGNBRK) {
		up->port.ignore_status_mask |= UART_LSR_BI;
		/*
		 * If we're ignoring parity and break indicators,
		 * ignore overruns too (for real raw support).
		 */
		if (termios->c_iflag & IGNPAR)
			up->port.ignore_status_mask |= UART_LSR_OE;
	}

	/*
	 * ignore all characters if CREAD is not set
	 */
	if ((termios->c_cflag & CREAD) == 0)
		up->port.ignore_status_mask |= UART_LSR_DR;

	/*
	 * CTS flow control flag and modem status interrupts
	 */
	up->ier &= ~UART_IER_MSI;
	if (UART_ENABLE_MS(&up->port, termios->c_cflag))
		up->ier |= UART_IER_MSI;

	serial_out(up, UART_IER, up->ier);
	serial_outp(up, 0x28, quot & 0xffff);
	up->lcr = cval;					/* Save LCR */
	if (up->port.type != PORT_16750) {
		if (fcr & UART_FCR_ENABLE_FIFO) {
			/* emulated UARTs (Lucent Venus 167x) need two steps */
			serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
		}
		serial_outp(up, UART_FCR, fcr);		/* set fcr */
	}
	spin_unlock_irqrestore(&up->port.lock, flags);
}
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
/******* SerialUnit::SetParameters() **********************************/
BOOL PCSerUnit__Hidd_SerialUnit__SetParameters(OOP_Class *cl, OOP_Object *o, struct pHidd_SerialUnit_SetParameters *msg)
{
    struct HIDDSerialUnitData * data = OOP_INST_DATA(cl, o);
    BOOL valid = TRUE;
    int i = 0;
    struct TagItem * tags = msg->tags;

    while (TAG_END != tags[i].ti_Tag && TRUE == valid)
    {
        switch (tags[i].ti_Tag)
        {
        case TAG_DATALENGTH:
            if ((BYTE)tags[i].ti_Data >= 5 && (BYTE)tags[i].ti_Data <= 8)
                data->datalength = tags[i].ti_Data;
            else
                valid = FALSE;
            break;

        case TAG_STOP_BITS: /* 3 means 1.5 stopbits (if supported) */
            if (1 == tags[i].ti_Data ||
                    2 == tags[i].ti_Data ||
                    3 == tags[i].ti_Data)
                data->stopbits = tags[i].ti_Data;
            else
                valid = FALSE;
            break;

        case TAG_PARITY:
            if (PARITY_0    == tags[i].ti_Data ||
                    PARITY_1    == tags[i].ti_Data ||
                    PARITY_EVEN == tags[i].ti_Data ||
                    PARITY_ODD  == tags[i].ti_Data)
            {
                data->parity     = TRUE;
                data->paritytype = tags[i].ti_Data;
            }
            else
                valid = FALSE;
            break;

        case TAG_PARITY_OFF:
            data->parity = FALSE;
            break;

        case TAG_SET_MCR:
            serial_outp(data, UART_MCR, (tags[i].ti_Data & 0x0f) | 0x08);
            break;

        case TAG_SKIP:
        case TAG_IGNORE:
            break;

        default:
            valid = FALSE;
        }
        i++;
    }

    if (TRUE == valid)
        serial_outp(data, UART_LCR, get_lcr(data));

    return valid;
}
Exemplo n.º 19
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);
}
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;
}