/* * drivers/input/serio/gscps2.c * * Copyright (c) 2004-2006 Helge Deller <deller@gmx.de> * Copyright (c) 2002 Laurent Canet <canetl@esiee.fr> * Copyright (c) 2002 Thibaut Varene <varenet@parisc-linux.org> * * Pieces of code based on linux-2.4's hp_mouse.c & hp_keyb.c * Copyright (c) 1999 Alex deVries <alex@onefishtwo.ca> * Copyright (c) 1999-2000 Philipp Rumpf <prumpf@tux.org> * Copyright (c) 2000 Xavier Debacker <debackex@esiee.fr> * Copyright (c) 2000-2001 Thomas Marteau <marteaut@esiee.fr> * * HP GSC PS/2 port driver, found in PA/RISC Workstations * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * * TODO: * - Dino testing (did HP ever shipped a machine on which this port * was usable/enabled ?)
*/
/* various constants */ #define ENABLE 1 #define DISABLE 0
#define GSC_DINO_OFFSET 0x0800 /* offset for DINO controller versus LASI one */
/* PS/2 IO port offsets */ #define GSC_ID 0x00 /* device ID offset (see: GSC_ID_XXX) */ #define GSC_RESET 0x00 /* reset port offset */ #define GSC_RCVDATA 0x04 /* receive port offset */ #define GSC_XMTDATA 0x04 /* transmit port offset */ #define GSC_CONTROL 0x08 /* see: Control register bits */ #define GSC_STATUS 0x0C /* see: Status register bits */
/* Control register bits */ #define GSC_CTRL_ENBL 0x01 /* enable interface */ #define GSC_CTRL_LPBXR 0x02 /* loopback operation */ #define GSC_CTRL_DIAG 0x20 /* directly control clock/data line */ #define GSC_CTRL_DATDIR 0x40 /* data line direct control */ #define GSC_CTRL_CLKDIR 0x80 /* clock line direct control */
/* Status register bits */ #define GSC_STAT_RBNE 0x01 /* Receive Buffer Not Empty */ #define GSC_STAT_TBNE 0x02 /* Transmit Buffer Not Empty */ #define GSC_STAT_TERR 0x04 /* Timeout Error */ #define GSC_STAT_PERR 0x08 /* Parity Error */ #define GSC_STAT_CMPINTR 0x10 /* Composite Interrupt = irq on any port */ #define GSC_STAT_DATSHD 0x40 /* Data Line Shadow */ #define GSC_STAT_CLKSHD 0x80 /* Clock Line Shadow */
/* IDs returned by GSC_ID port register */ #define GSC_ID_KEYBOARD 0 /* device ID values */ #define GSC_ID_MOUSE 1
/* * wait_TBE() - wait for Transmit Buffer Empty
*/
staticint wait_TBE(char __iomem *addr)
{ int timeout = 25000; /* device is expected to react within 250 msec */ while (gscps2_readb_status(addr) & GSC_STAT_TBNE) { if (!--timeout) return 0; /* This should not happen */
udelay(10);
} return 1;
}
/* this is ugly, but due to timing of the port it seems to be necessary. */
mdelay(6);
/* make sure any received data is returned as fast as possible */ /* this is important e.g. when we set the LEDs on the keyboard */
gscps2_interrupt(0, NULL);
return 1;
}
/* * gscps2_enable() - enables or disables the port
*/
staticvoid gscps2_enable(struct gscps2port *ps2port, int enable)
{
u8 data;
/* now enable/disable the port */
scoped_guard(spinlock_irqsave, &ps2port->lock) {
gscps2_flush(ps2port);
data = gscps2_readb_control(ps2port->addr); if (enable)
data |= GSC_CTRL_ENBL; else
data &= ~GSC_CTRL_ENBL;
gscps2_writeb_control(data, ps2port->addr);
}
while (ps2port->act != ps2port->append) { /* * Did new data arrived while we read existing data ? * If yes, exit now and let the new irq handler start * over again.
*/ if (gscps2_readb_status(ps2port->addr) & GSC_STAT_CMPINTR) returntrue;
status = ps2port->buffer[ps2port->act].str;
data = ps2port->buffer[ps2port->act].data;
/** * gscps2_interrupt() - Interruption service routine * @irq: interrupt number which triggered (unused) * @dev: device pointer (unused) * * This function reads received PS/2 bytes and processes them on * all interfaces. * The problematic part here is, that the keyboard and mouse PS/2 port * share the same interrupt and it's not possible to send data if any * one of them holds input data. To solve this problem we try to receive * the data as fast as possible and handle the reporting to the upper layer * later.
*/
/* all data was read from the ports - now report the data to upper layer */
list_for_each_entry(ps2port, &ps2port_list, node) { if (gscps2_report_data(ps2port)) { /* More data ready - break early to restart interrupt */ break;
}
}
return IRQ_HANDLED;
}
/* * gscps2_write() - send a byte out through the aux interface.
*/
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.23Bemerkung:
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.