1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
|
/* Hey EMACS -*- linux-c -*- */
/* $Id: linux_ioports.c 899 2005-03-14 09:41:20Z roms $ */
/* libticables - Ti Link Cable library, a part of the TiLP project
* Copyright (C) 1999-2004 Romain Lievin
* Copyright (c) 2002, Kevin Kofler for the __MINGW32__ & __GNUC__ extensions.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*
* This unit manages direct low-level I/O operations depending on a
* I/O method.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <errno.h>
#include <unistd.h>
#include <termios.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#if defined(__I386__) && defined(HAVE_SYS_PERM_H)
#include <sys/perm.h>
#endif
#if defined(__I386__) && defined(HAVE_SYS_IO_H)
#include <sys/io.h>
#elif defined(__I386__) && defined(HAVE_ASM_IO_H)
#include <asm/io.h>
#endif
#include "gettext.h"
#include "cabl_err.h"
#include "externs.h"
#include "printl.h"
/* Variables */
static int dev_fd; // TTY handle for Linux ioctl calls (API)
static int tty_use = 0; // open TTY just once
/* Function pointers */
int (*io_rd) (unsigned int addr);
void (*io_wr) (unsigned int addr, int data);
/* I/O thru assembly code */
static int linux_asm_read_io(unsigned int addr)
{
#if defined(__I386__) && defined(HAVE_ASM_IO_H) && defined(HAVE_SYS_PERM_H)
return inb(addr);
#else
return 0;
#endif
}
static void linux_asm_write_io(unsigned int addr, int data)
{
#if defined(__I386__) && defined(HAVE_ASM_IO_H) && defined(HAVE_SYS_PERM_H)
outb(data, addr);
#endif
}
/* I/O thru ioctl() calls */
static int linux_ioctl_read_io(unsigned int addr)
{
#ifdef HAVE_TERMIOS_H
unsigned int flags;
if (ioctl(dev_fd, TIOCMGET, &flags) == -1) {
printl1(2, _("ioctl failed in linux_ioctl_read_io !\n"));
return ERR_IOCTL;
}
return (flags & TIOCM_CTS ? 1 : 0) | (flags & TIOCM_DSR ? 2 : 0);
#endif
}
static void linux_ioctl_write_io(unsigned int address, int data)
{
#ifdef HAVE_TERMIOS_H
unsigned int flags = 0;
flags |= (data & 2) ? TIOCM_RTS : 0;
flags |= (data & 1) ? TIOCM_DTR : 0;
if (ioctl(dev_fd, TIOCMSET, &flags) == -1) {
printl1(2, _("ioctl failed in linux_ioctl_write_io !\n"));
//return ERR_IOCTL;
}
#endif
}
/* Functions used for initializing the I/O routines */
int io_open(unsigned long from, unsigned long num)
{
if (method & IOM_ASM) {
#if defined(__I386__) && defined(HAVE_ASM_IO_H) && defined(HAVE_SYS_PERM_H)
io_rd = linux_asm_read_io;
io_wr = linux_asm_write_io;
return (ioperm(from, num, 1) ? ERR_ROOT : 0);
#else
return ERR_ROOT;
#endif
}
else if (method & IOM_IOCTL) {
struct termios termset;
if (tty_use)
return 0;
if ((dev_fd = open(io_device, O_RDWR | O_SYNC)) == -1) {
if(errno == EACCES)
printl1(2, _("unable to open this serial port: %s (wrong permissions).\n"), io_device);
else
printl1(2, _("unable to open this serial port: %s\n"), io_device);
return ERR_OPEN_SER_DEV;
}
tcgetattr(dev_fd, &termset);
cfmakeraw(&termset);
io_rd = linux_ioctl_read_io;
io_wr = linux_ioctl_write_io;
tty_use++;
} else {
printl1(2, "bad argument (invalid method).\n");
return ERR_ILLEGAL_ARG;
}
return 0;
}
int io_close(unsigned long from, unsigned long num)
{
if (method & IOM_ASM) {
#if defined(__I386__) && defined(HAVE_ASM_IO_H) && defined(HAVE_SYS_PERM_H)
return (ioperm(from, num, 0) ? ERR_ROOT : 0);
#else
return 0;
#endif
}
else if (method & IOM_IOCTL) {
if (tty_use) {
close(dev_fd);
tty_use--;
}
} else {
printl1(2, "bad argument (invalid method).\n");
return ERR_ILLEGAL_ARG;
}
return 0;
}
|