blob: 69a97425ed13bb983c17aa505e30271605baa441 [file] [log] [blame]
/******************************************************************************
* *
* License Agreement *
* *
* Copyright (c) 2006 Altera Corporation, San Jose, California, USA. *
* All rights reserved. *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
* copy of this software and associated documentation files (the "Software"), *
* to deal in the Software without restriction, including without limitation *
* the rights to use, copy, modify, merge, publish, distribute, sublicense, *
* and/or sell copies of the Software, and to permit persons to whom the *
* Software is furnished to do so, subject to the following conditions: *
* *
* The above copyright notice and this permission notice shall be included in *
* all copies or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *
* DEALINGS IN THE SOFTWARE. *
* *
* *
******************************************************************************/
#include <fcntl.h>
#include <string.h>
#include "sys/alt_irq.h"
#include "sys/ioctl.h"
#include "sys/alt_errno.h"
#include "altera_avalon_uart_regs.h"
#include "altera_avalon_uart.h"
#if !defined(ALT_USE_SMALL_DRIVERS) && !defined(ALTERA_AVALON_UART_SMALL)
/* ----------------------------------------------------------- */
/* ------------------------- FAST DRIVER --------------------- */
/* ----------------------------------------------------------- */
/*
* To reduce the code footprint of this driver, the ioctl() function is not
* included by default. If you wish to use the ioctl features provided
* below, you can do so by adding the option : -DALTERA_AVALON_UART_USE_IOCTL
* to CPPFLAGS in the Makefile (or through the Eclipse IDE).
*/
#ifdef ALTERA_AVALON_UART_USE_IOCTL
/*
* altera_avalon_uart_ioctl() is called by the system ioctl() function to handle
* ioctl requests for the UART. The only ioctl requests supported are TIOCMGET
* and TIOCMSET.
*
* TIOCMGET returns a termios structure that describes the current device
* configuration.
*
* TIOCMSET sets the device (if possible) to match the requested configuration.
* The requested configuration is described using a termios structure passed
* through the input argument "arg".
*/
static int altera_avalon_uart_tiocmget(altera_avalon_uart_state* sp,
struct termios* term);
static int altera_avalon_uart_tiocmset(altera_avalon_uart_state* sp,
struct termios* term);
int
altera_avalon_uart_ioctl(altera_avalon_uart_state* sp, int req, void* arg)
{
int rc = -ENOTTY;
switch (req)
{
case TIOCMGET:
rc = altera_avalon_uart_tiocmget(sp, (struct termios*) arg);
break;
case TIOCMSET:
rc = altera_avalon_uart_tiocmset(sp, (struct termios*) arg);
break;
default:
break;
}
return rc;
}
/*
* altera_avalon_uart_tiocmget() is used by altera_avalon_uart_ioctl() to fill
* in the input termios structure with the current device configuration.
*
* See termios.h for further details on the contents of the termios structure.
*/
static int
altera_avalon_uart_tiocmget(altera_avalon_uart_state* sp,
struct termios* term)
{
memcpy (term, &sp->termios, sizeof (struct termios));
return 0;
}
/*
* altera_avalon_uart_tiocmset() is used by altera_avalon_uart_ioctl() to
* configure the device according to the settings in the input termios
* structure. In practice the only configuration that can be changed is the
* baud rate, and then only if the hardware is configured to have a writable
* baud register.
*/
static int
altera_avalon_uart_tiocmset(altera_avalon_uart_state* sp,
struct termios* term)
{
speed_t speed;
speed = sp->termios.c_ispeed;
/* Update the settings if the hardware supports it */
if (!(sp->flags & ALT_AVALON_UART_FB))
{
sp->termios.c_ispeed = sp->termios.c_ospeed = term->c_ispeed;
}
/*
* If the request was for an unsupported setting, return an error.
*/
if (memcmp(term, &sp->termios, sizeof (struct termios)))
{
sp->termios.c_ispeed = sp->termios.c_ospeed = speed;
return -EIO;
}
/*
* Otherwise, update the hardware.
*/
IOWR_ALTERA_AVALON_UART_DIVISOR(sp->base,
((sp->freq/sp->termios.c_ispeed) - 1));
return 0;
}
#endif /* ALTERA_AVALON_UART_USE_IOCTL */
#endif /* fast driver */