示例#1
0
static int sa1100_console_wait_key(struct console *co)
{
	struct uart_port *port = sa1100_ports + co->index;
	unsigned long flags;
	u_int old_utcr3, status, ch;

	/*
	 * Save UTCR3 and disable interrupts
	 */
	save_flags(flags);
	cli();
	old_utcr3 = UART_GET_UTCR3(port);
	UART_PUT_UTCR3(port, old_utcr3 & ~(UTCR3_RIE | UTCR3_TIE));
	restore_flags(flags);

	/*
	 * Wait for a character
	 */
	do {
		status = UART_GET_UTSR1(port);
	} while (!(status & UTSR1_RNE));
	ch = UART_GET_CHAR(port);

	/*
	 * Restore UTCR3
	 */
	UART_PUT_UTCR3(port, old_utcr3);

	return ch;
}
示例#2
0
static void sa1100_shutdown(struct uart_port *port)
{
	struct sa1100_port *sport = (struct sa1100_port *)port;

	/*
	 * Stop our timer.
	 */
	del_timer_sync(&sport->timer);

	/*
	 * Free the interrupt
	 */
	free_irq(sport->port.irq, sport);

	/*
	 * If there is a specific "close" function (to unregister
	 * control line interrupts)
	 */
	if (sa1100_close)
		sa1100_close(port);

	/*
	 * Disable all interrupts, port and break condition.
	 */
	UART_PUT_UTCR3(sport, 0);
}
示例#3
0
static int sa1100_startup(struct uart_port *port)
{
	struct sa1100_port *sport = (struct sa1100_port *)port;
	int retval;

	/*
	 * Allocate the IRQ
	 */
	retval = request_irq(sport->port.irq, sa1100_int, 0,
			     "sa11x0-uart", sport);
	if (retval)
		return retval;

	/*
	 * If there is a specific "open" function
	 * (to register control line interrupts)
	 */
	if (sa1100_open) {
		retval = sa1100_open(port);
		if (retval) {
			free_irq(sport->port.irq, sport);
			return retval;
		}
	}

	/*
	 * Finally, clear and enable interrupts
	 */
	UART_PUT_UTSR0(sport, -1);
	UART_PUT_UTCR3(sport, UTCR3_RXE | UTCR3_TXE | UTCR3_RIE);

	return 0;
}
示例#4
0
static int sa1100_startup(struct uart_port *port, struct uart_info *info)
{
	int retval;

	/*
	 * Allocate the IRQ
	 */
	retval = request_irq(port->irq, sa1100_int, 0, "serial_sa1100", info);
	if (retval)
		return retval;

	/*
	 * If there is a specific "open" function (to register
	 * control line interrupts)
	 */
	if (sa1100_open) {
		retval = sa1100_open(port, info);
		if (retval) {
			free_irq(port->irq, info);
			return retval;
		}
	}

	/*
	 * Finally, clear and enable interrupts
	 */
	UART_PUT_UTSR0(port, -1);
	UART_PUT_UTCR3(port, UTCR3_RXE | UTCR3_TXE | UTCR3_RIE);

	return 0;
}
static int sa1100_startup(struct uart_port *port)
{
	struct sa1100_port *sport = (struct sa1100_port *)port;
	int retval;

	/*
	 * Allocate the IRQ
	 */
	retval = request_irq(sport->port.irq, sa1100_int, 0,
			     "sa11x0-uart", sport);
	if (retval)
		return retval;

	/*
	 * Finally, clear and enable interrupts
	 */
	UART_PUT_UTSR0(sport, -1);
	UART_PUT_UTCR3(sport, UTCR3_RXE | UTCR3_TXE | UTCR3_RIE);

	/*
	 * Enable modem status interrupts
	 */
	spin_lock_irq(&sport->port.lock);
	sa1100_enable_ms(&sport->port);
	spin_unlock_irq(&sport->port.lock);

	return 0;
}
/*
 * Interrupts enabled
 */
static void sa1100_stop_rx(struct uart_port *port)
{
	struct sa1100_port *sport = (struct sa1100_port *)port;
	u32 utcr3;

	utcr3 = UART_GET_UTCR3(sport);
	UART_PUT_UTCR3(sport, utcr3 & ~UTCR3_RIE);
}
示例#7
0
/*
 * interrupts disabled on entry
 */
static void sa1100_stop_tx(struct uart_port *port, unsigned int tty_stop)
{
	struct sa1100_port *sport = (struct sa1100_port *)port;
	u32 utcr3;

	utcr3 = UART_GET_UTCR3(sport);
	UART_PUT_UTCR3(sport, utcr3 & ~UTCR3_TIE);
	sport->port.read_status_mask &= ~UTSR0_TO_SM(UTSR0_TFS);
}
/*
 * port locked and interrupts disabled
 */
static void sa1100_start_tx(struct uart_port *port)
{
	struct sa1100_port *sport = (struct sa1100_port *)port;
	u32 utcr3;

	utcr3 = UART_GET_UTCR3(sport);
	sport->port.read_status_mask |= UTSR0_TO_SM(UTSR0_TFS);
	UART_PUT_UTCR3(sport, utcr3 | UTCR3_TIE);
}
示例#9
0
static void
sa1100_console_write(struct console *co, const char *s, unsigned int count)
{
	struct sa1100_port *sport = &sa1100_ports[co->index];
	unsigned int old_utcr3, status;

	
	old_utcr3 = UART_GET_UTCR3(sport);
	UART_PUT_UTCR3(sport, (old_utcr3 & ~(UTCR3_RIE | UTCR3_TIE)) |
				UTCR3_TXE);

	uart_console_write(&sport->port, s, count, sa1100_console_putchar);

	
	do {
		status = UART_GET_UTSR1(sport);
	} while (status & UTSR1_TBY);
	UART_PUT_UTCR3(sport, old_utcr3);
}
示例#10
0
/*
 * Interrupts always disabled.
 */
static void sa1100_break_ctl(struct uart_port *port, int break_state)
{
	u_int utcr3;

	utcr3 = UART_GET_UTCR3(port);
	if (break_state == -1)
		utcr3 |= UTCR3_BRK;
	else
		utcr3 &= ~UTCR3_BRK;
	UART_PUT_UTCR3(port, utcr3);
}
示例#11
0
/*
 * interrupts may not be disabled on entry
 */
static void sa1100_start_tx(struct uart_port *port, unsigned int tty_start)
{
	struct sa1100_port *sport = (struct sa1100_port *)port;
	unsigned long flags;
	u32 utcr3;

	spin_lock_irqsave(&sport->port.lock, flags);
	utcr3 = UART_GET_UTCR3(sport);
	sport->port.read_status_mask |= UTSR0_TO_SM(UTSR0_TFS);
	UART_PUT_UTCR3(sport, utcr3 | UTCR3_TIE);
	spin_unlock_irqrestore(&sport->port.lock, flags);
}
示例#12
0
/*
 * interrupts may not be disabled on entry
 */
static void sa1100_start_tx(struct uart_port *port, u_int nonempty, u_int from_tty)
{
	if (nonempty) {
		unsigned long flags;
		u32 utcr3;

		local_irq_save(flags);
		utcr3 = UART_GET_UTCR3(port);
		port->read_status_mask |= UTSR0_TO_SM(UTSR0_TFS);
		UART_PUT_UTCR3(port, utcr3 | UTCR3_TIE);
		local_irq_restore(flags);
	}
}
示例#13
0
static void sa1100_shutdown(struct uart_port *port)
{
	struct sa1100_port *sport = (struct sa1100_port *)port;

	
	del_timer_sync(&sport->timer);

	
	free_irq(sport->port.irq, sport);

	
	UART_PUT_UTCR3(sport, 0);
}
/*
 * Interrupts are disabled on entering
 */
static void
sa1100_console_write(struct console *co, const char *s, unsigned int count)
{
    struct sa1100_port *sport = &sa1100_ports[co->index];
    unsigned int old_utcr3, status, i;

    /*
     *	First, save UTCR3 and then disable interrupts
     */
    old_utcr3 = UART_GET_UTCR3(sport);
    UART_PUT_UTCR3(sport, (old_utcr3 & ~(UTCR3_RIE | UTCR3_TIE)) |
                   UTCR3_TXE);

    /*
     *	Now, do each character
     */
    for (i = 0; i < count; i++) {
        do {
            status = UART_GET_UTSR1(sport);
        } while (!(status & UTSR1_TNF));
        UART_PUT_CHAR(sport, s[i]);
        if (s[i] == '\n') {
            do {
                status = UART_GET_UTSR1(sport);
            } while (!(status & UTSR1_TNF));
            UART_PUT_CHAR(sport, '\r');
        }
    }

    /*
     *	Finally, wait for transmitter to become empty
     *	and restore UTCR3
     */
    do {
        status = UART_GET_UTSR1(sport);
    } while (status & UTSR1_TBY);
    UART_PUT_UTCR3(sport, old_utcr3);
}
示例#15
0
/*
 * Interrupts are disabled on entering
 */
static void
sa1100_console_write(struct console *co, const char *s, unsigned int count)
{
	struct sa1100_port *sport = &sa1100_ports[co->index];
	unsigned int old_utcr3, status;

	/*
	 *	First, save UTCR3 and then disable interrupts
	 */
	old_utcr3 = UART_GET_UTCR3(sport);
	UART_PUT_UTCR3(sport, (old_utcr3 & ~(UTCR3_RIE | UTCR3_TIE)) |
				UTCR3_TXE);

	uart_console_write(&sport->port, s, count, sa1100_console_putchar);

	/*
	 *	Finally, wait for transmitter to become empty
	 *	and restore UTCR3
	 */
	do {
		status = UART_GET_UTSR1(sport);
	} while (status & UTSR1_TBY);
	UART_PUT_UTCR3(sport, old_utcr3);
}
示例#16
0
/*
 * Interrupts always disabled.
 */
static void sa1100_break_ctl(struct uart_port *port, int break_state)
{
	struct sa1100_port *sport = (struct sa1100_port *)port;
	unsigned long flags;
	unsigned int utcr3;

	spin_lock_irqsave(&sport->port.lock, flags);
	utcr3 = UART_GET_UTCR3(sport);
	if (break_state == -1)
		utcr3 |= UTCR3_BRK;
	else
		utcr3 &= ~UTCR3_BRK;
	UART_PUT_UTCR3(sport, utcr3);
	spin_unlock_irqrestore(&sport->port.lock, flags);
}
示例#17
0
static void sa1100_shutdown(struct uart_port *port)
{
	struct sa1100_port *sport = (struct sa1100_port *)port;

	/*
	 * Stop our timer.
	 */
	del_timer_sync(&sport->timer);

	/*
	 * Free the interrupt
	 */
	free_irq(sport->port.irq, sport);

	/*
	 * Disable all interrupts, port and break condition.
	 */
	UART_PUT_UTCR3(sport, 0);
}
示例#18
0
static void sa1100_shutdown(struct uart_port *port, struct uart_info *info)
{
	/*
	 * Free the interrupt
	 */
	free_irq(port->irq, info);

	/*
	 * If there is a specific "close" function (to unregister
	 * control line interrupts)
	 */
	if (sa1100_close)
		sa1100_close(port, info);

	/*
	 * Disable all interrupts, port and break condition.
	 */
	UART_PUT_UTCR3(port, 0);
}
示例#19
0
static int sa1100_startup(struct uart_port *port)
{
	struct sa1100_port *sport = (struct sa1100_port *)port;
	int retval;

	
	retval = request_irq(sport->port.irq, sa1100_int, 0,
			     "sa11x0-uart", sport);
	if (retval)
		return retval;

	
	UART_PUT_UTSR0(sport, -1);
	UART_PUT_UTCR3(sport, UTCR3_RXE | UTCR3_TXE | UTCR3_RIE);

	
	spin_lock_irq(&sport->port.lock);
	sa1100_enable_ms(&sport->port);
	spin_unlock_irq(&sport->port.lock);

	return 0;
}
示例#20
0
static void sa1100_change_speed(struct uart_port *port, unsigned int cflag, unsigned int iflag, unsigned int quot)
{
	struct sa1100_port *sport = (struct sa1100_port *)port;
	unsigned long flags;
	unsigned int utcr0, old_utcr3;

	if ((cflag & CSIZE) == CS8)
		utcr0 = UTCR0_DSS;
	else
		utcr0 = 0;

	if (cflag & CSTOPB)
		utcr0 |= UTCR0_SBS;
	if (cflag & PARENB) {
		utcr0 |= UTCR0_PE;
		if (!(cflag & PARODD))
			utcr0 |= UTCR0_OES;
	}

	spin_lock_irqsave(&sport->port.lock, flags);

	sport->port.read_status_mask &= UTSR0_TO_SM(UTSR0_TFS);
	sport->port.read_status_mask |= UTSR1_TO_SM(UTSR1_ROR);
	if (iflag & INPCK)
		sport->port.read_status_mask |=
				UTSR1_TO_SM(UTSR1_FRE | UTSR1_PRE);
	if (iflag & (BRKINT | PARMRK))
		sport->port.read_status_mask |=
				UTSR0_TO_SM(UTSR0_RBB | UTSR0_REB);

	/*
	 * Characters to ignore
	 */
	sport->port.ignore_status_mask = 0;
	if (iflag & IGNPAR)
		sport->port.ignore_status_mask |=
				UTSR1_TO_SM(UTSR1_FRE | UTSR1_PRE);
	if (iflag & IGNBRK) {
		sport->port.ignore_status_mask |=
				UTSR0_TO_SM(UTSR0_RBB | UTSR0_REB);
		/*
		 * If we're ignoring parity and break indicators,
		 * ignore overruns too (for real raw support).
		 */
		if (iflag & IGNPAR)
			sport->port.ignore_status_mask |=
				UTSR1_TO_SM(UTSR1_ROR);
	}

	del_timer_sync(&sport->timer);

	/*
	 * disable interrupts and drain transmitter
	 */
	old_utcr3 = UART_GET_UTCR3(sport);
	UART_PUT_UTCR3(sport, old_utcr3 & ~(UTCR3_RIE | UTCR3_TIE));

	while (UART_GET_UTSR1(sport) & UTSR1_TBY)
		barrier();

	/* then, disable everything */
	UART_PUT_UTCR3(sport, 0);

	/* set the parity, stop bits and data size */
	UART_PUT_UTCR0(sport, utcr0);

	/* set the baud rate */
	quot -= 1;
	UART_PUT_UTCR1(sport, ((quot & 0xf00) >> 8));
	UART_PUT_UTCR2(sport, (quot & 0xff));

	UART_PUT_UTSR0(sport, -1);

	UART_PUT_UTCR3(sport, old_utcr3);

	if (UART_ENABLE_MS(&sport->port, cflag))
		sa1100_enable_ms(&sport->port);

	spin_unlock_irqrestore(&sport->port.lock, flags);
}
示例#21
0
static void
sa1100_set_termios(struct uart_port *port, struct ktermios *termios,
		   struct ktermios *old)
{
	struct sa1100_port *sport = (struct sa1100_port *)port;
	unsigned long flags;
	unsigned int utcr0, old_utcr3, baud, quot;
	unsigned int old_csize = old ? old->c_cflag & CSIZE : CS8;

	/*
	 * We only support CS7 and CS8.
	 */
	while ((termios->c_cflag & CSIZE) != CS7 &&
	       (termios->c_cflag & CSIZE) != CS8) {
		termios->c_cflag &= ~CSIZE;
		termios->c_cflag |= old_csize;
		old_csize = CS8;
	}

	if ((termios->c_cflag & CSIZE) == CS8)
		utcr0 = UTCR0_DSS;
	else
		utcr0 = 0;

	if (termios->c_cflag & CSTOPB)
		utcr0 |= UTCR0_SBS;
	if (termios->c_cflag & PARENB) {
		utcr0 |= UTCR0_PE;
		if (!(termios->c_cflag & PARODD))
			utcr0 |= UTCR0_OES;
	}

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

	spin_lock_irqsave(&sport->port.lock, flags);

	sport->port.read_status_mask &= UTSR0_TO_SM(UTSR0_TFS);
	sport->port.read_status_mask |= UTSR1_TO_SM(UTSR1_ROR);
	if (termios->c_iflag & INPCK)
		sport->port.read_status_mask |=
				UTSR1_TO_SM(UTSR1_FRE | UTSR1_PRE);
	if (termios->c_iflag & (BRKINT | PARMRK))
		sport->port.read_status_mask |=
				UTSR0_TO_SM(UTSR0_RBB | UTSR0_REB);

	/*
	 * Characters to ignore
	 */
	sport->port.ignore_status_mask = 0;
	if (termios->c_iflag & IGNPAR)
		sport->port.ignore_status_mask |=
				UTSR1_TO_SM(UTSR1_FRE | UTSR1_PRE);
	if (termios->c_iflag & IGNBRK) {
		sport->port.ignore_status_mask |=
				UTSR0_TO_SM(UTSR0_RBB | UTSR0_REB);
		/*
		 * If we're ignoring parity and break indicators,
		 * ignore overruns too (for real raw support).
		 */
		if (termios->c_iflag & IGNPAR)
			sport->port.ignore_status_mask |=
				UTSR1_TO_SM(UTSR1_ROR);
	}

	del_timer_sync(&sport->timer);

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

	/*
	 * disable interrupts and drain transmitter
	 */
	old_utcr3 = UART_GET_UTCR3(sport);
	UART_PUT_UTCR3(sport, old_utcr3 & ~(UTCR3_RIE | UTCR3_TIE));

	while (UART_GET_UTSR1(sport) & UTSR1_TBY)
		barrier();

	/* then, disable everything */
	UART_PUT_UTCR3(sport, 0);

	/* set the parity, stop bits and data size */
	UART_PUT_UTCR0(sport, utcr0);

	/* set the baud rate */
	quot -= 1;
	UART_PUT_UTCR1(sport, ((quot & 0xf00) >> 8));
	UART_PUT_UTCR2(sport, (quot & 0xff));

	UART_PUT_UTSR0(sport, -1);

	UART_PUT_UTCR3(sport, old_utcr3);

	if (UART_ENABLE_MS(&sport->port, termios->c_cflag))
		sa1100_enable_ms(&sport->port);

	spin_unlock_irqrestore(&sport->port.lock, flags);
}
示例#22
0
/*
 * Interrupts enabled
 */
static void sa1100_stop_rx(struct uart_port *port)
{
	u32 utcr3 = UART_GET_UTCR3(port);
	UART_PUT_UTCR3(port, utcr3 & ~UTCR3_RIE);
}
示例#23
0
static void sa1100_change_speed(struct uart_port *port, u_int cflag, u_int iflag, u_int quot)
{
	unsigned long flags;
	u_int utcr0, old_utcr3;

	/* byte size and parity */
	switch (cflag & CSIZE) {
	case CS7:	utcr0 = 0;		break;
	default:	utcr0 = UTCR0_DSS;	break;
	}
	if (cflag & CSTOPB)
		utcr0 |= UTCR0_SBS;
	if (cflag & PARENB) {
		utcr0 |= UTCR0_PE;
		if (!(cflag & PARODD))
			utcr0 |= UTCR0_OES;
	}

	port->read_status_mask &= UTSR0_TO_SM(UTSR0_TFS);
	port->read_status_mask |= UTSR1_TO_SM(UTSR1_ROR);
	if (iflag & INPCK)
		port->read_status_mask |= UTSR1_TO_SM(UTSR1_FRE | UTSR1_PRE);
	if (iflag & (BRKINT | PARMRK))
		port->read_status_mask |= UTSR0_TO_SM(UTSR0_RBB | UTSR0_REB);

	/*
	 * Characters to ignore
	 */
	port->ignore_status_mask = 0;
	if (iflag & IGNPAR)
		port->ignore_status_mask |= UTSR1_TO_SM(UTSR1_FRE | UTSR1_PRE);
	if (iflag & IGNBRK) {
		port->ignore_status_mask |= UTSR0_TO_SM(UTSR0_RBB | UTSR0_REB);
		/*
		 * If we're ignoring parity and break indicators,
		 * ignore overruns too (for real raw support).
		 */
		if (iflag & IGNPAR)
			port->ignore_status_mask |= UTSR1_TO_SM(UTSR1_ROR);
	}

	/* first, disable interrupts and drain transmitter */
	local_irq_save(flags);
	old_utcr3 = UART_GET_UTCR3(port);
	UART_PUT_UTCR3(port, old_utcr3 & ~(UTCR3_RIE | UTCR3_TIE));
	local_irq_restore(flags);
	while (UART_GET_UTSR1(port) & UTSR1_TBY);

	/* then, disable everything */
	UART_PUT_UTCR3(port, 0);

	/* set the parity, stop bits and data size */
	UART_PUT_UTCR0(port, utcr0);

	/* set the baud rate */
	quot -= 1;
	UART_PUT_UTCR1(port, ((quot & 0xf00) >> 8));
	UART_PUT_UTCR2(port, (quot & 0xff));

	UART_PUT_UTSR0(port, -1);

	UART_PUT_UTCR3(port, old_utcr3);
}
示例#24
0
/*
 * interrupts disabled on entry
 */
static void sa1100_stop_tx(struct uart_port *port, u_int from_tty)
{
	u32 utcr3 = UART_GET_UTCR3(port);
	UART_PUT_UTCR3(port, utcr3 & ~UTCR3_TIE);
	port->read_status_mask &= ~UTSR0_TO_SM(UTSR0_TFS);
}
示例#25
0
static void
sa1100_set_termios(struct uart_port *port, struct ktermios *termios,
		   struct ktermios *old)
{
	struct sa1100_port *sport = (struct sa1100_port *)port;
	unsigned long flags;
	unsigned int utcr0, old_utcr3, baud, quot;
	unsigned int old_csize = old ? old->c_cflag & CSIZE : CS8;

	
	while ((termios->c_cflag & CSIZE) != CS7 &&
	       (termios->c_cflag & CSIZE) != CS8) {
		termios->c_cflag &= ~CSIZE;
		termios->c_cflag |= old_csize;
		old_csize = CS8;
	}

	if ((termios->c_cflag & CSIZE) == CS8)
		utcr0 = UTCR0_DSS;
	else
		utcr0 = 0;

	if (termios->c_cflag & CSTOPB)
		utcr0 |= UTCR0_SBS;
	if (termios->c_cflag & PARENB) {
		utcr0 |= UTCR0_PE;
		if (!(termios->c_cflag & PARODD))
			utcr0 |= UTCR0_OES;
	}

	
	baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); 
	quot = uart_get_divisor(port, baud);

	spin_lock_irqsave(&sport->port.lock, flags);

	sport->port.read_status_mask &= UTSR0_TO_SM(UTSR0_TFS);
	sport->port.read_status_mask |= UTSR1_TO_SM(UTSR1_ROR);
	if (termios->c_iflag & INPCK)
		sport->port.read_status_mask |=
				UTSR1_TO_SM(UTSR1_FRE | UTSR1_PRE);
	if (termios->c_iflag & (BRKINT | PARMRK))
		sport->port.read_status_mask |=
				UTSR0_TO_SM(UTSR0_RBB | UTSR0_REB);

	
	sport->port.ignore_status_mask = 0;
	if (termios->c_iflag & IGNPAR)
		sport->port.ignore_status_mask |=
				UTSR1_TO_SM(UTSR1_FRE | UTSR1_PRE);
	if (termios->c_iflag & IGNBRK) {
		sport->port.ignore_status_mask |=
				UTSR0_TO_SM(UTSR0_RBB | UTSR0_REB);
		
		if (termios->c_iflag & IGNPAR)
			sport->port.ignore_status_mask |=
				UTSR1_TO_SM(UTSR1_ROR);
	}

	del_timer_sync(&sport->timer);

	
	uart_update_timeout(port, termios->c_cflag, baud);

	
	old_utcr3 = UART_GET_UTCR3(sport);
	UART_PUT_UTCR3(sport, old_utcr3 & ~(UTCR3_RIE | UTCR3_TIE));

	while (UART_GET_UTSR1(sport) & UTSR1_TBY)
		barrier();

	
	UART_PUT_UTCR3(sport, 0);

	
	UART_PUT_UTCR0(sport, utcr0);

	
	quot -= 1;
	UART_PUT_UTCR1(sport, ((quot & 0xf00) >> 8));
	UART_PUT_UTCR2(sport, (quot & 0xff));

	UART_PUT_UTSR0(sport, -1);

	UART_PUT_UTCR3(sport, old_utcr3);

	if (UART_ENABLE_MS(&sport->port, termios->c_cflag))
		sa1100_enable_ms(&sport->port);

	spin_unlock_irqrestore(&sport->port.lock, flags);
}