You can subscribe to this list here.
| 2001 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(135) |
Nov
(123) |
Dec
(83) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2002 |
Jan
(244) |
Feb
(72) |
Mar
(221) |
Apr
(91) |
May
(104) |
Jun
(93) |
Jul
(78) |
Aug
(1) |
Sep
(1) |
Oct
(29) |
Nov
(98) |
Dec
(20) |
| 2003 |
Jan
|
Feb
(21) |
Mar
|
Apr
(1) |
May
|
Jun
|
Jul
|
Aug
(18) |
Sep
(18) |
Oct
(23) |
Nov
(12) |
Dec
(6) |
| 2004 |
Jan
(2) |
Feb
(32) |
Mar
|
Apr
(12) |
May
(11) |
Jun
(11) |
Jul
|
Aug
(9) |
Sep
|
Oct
(15) |
Nov
|
Dec
|
| 2005 |
Jan
|
Feb
(2) |
Mar
(11) |
Apr
(6) |
May
(1) |
Jun
(9) |
Jul
(7) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(1) |
| 2006 |
Jan
|
Feb
(1) |
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
| 2007 |
Jan
|
Feb
(2) |
Mar
|
Apr
(25) |
May
(2) |
Jun
|
Jul
(5) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
| 2008 |
Jan
|
Feb
|
Mar
(1) |
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
| 2009 |
Jan
|
Feb
(1) |
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
| 2010 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
(13) |
Oct
|
Nov
(2) |
Dec
(2) |
| 2011 |
Jan
|
Feb
|
Mar
(10) |
Apr
(10) |
May
(1) |
Jun
(6) |
Jul
|
Aug
(2) |
Sep
(5) |
Oct
|
Nov
|
Dec
|
|
From: <sk...@us...> - 2010-09-23 11:41:19
|
Revision: 2385
http://linuxconsole.svn.sourceforge.net/linuxconsole/?rev=2385&view=rev
Author: skitt
Date: 2010-09-23 11:41:12 +0000 (Thu, 23 Sep 2010)
Log Message:
-----------
Update inputattach to Dmitry Torokhov's version.
Modified Paths:
--------------
trunk/utils/inputattach.c
Added Paths:
-----------
trunk/utils/serio-ids.h
Modified: trunk/utils/inputattach.c
===================================================================
--- trunk/utils/inputattach.c 2007-07-17 18:50:21 UTC (rev 2384)
+++ trunk/utils/inputattach.c 2010-09-23 11:41:12 UTC (rev 2385)
@@ -16,18 +16,18 @@
/*
* 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
+ * 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
- *
+ *
* Should you need to contact me, the author, you can do so either by
* e-mail - mail your message to <vo...@uc...>, or by paper mail:
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
@@ -46,29 +46,33 @@
#include <fcntl.h>
#include <termios.h>
#include <string.h>
+#include <errno.h>
#include <assert.h>
#include <ctype.h>
-int readchar(int fd, unsigned char *c, int timeout)
+#include "serio-ids.h"
+
+static int readchar(int fd, unsigned char *c, int timeout)
{
struct timeval tv;
fd_set set;
-
+
tv.tv_sec = 0;
tv.tv_usec = timeout * 1000;
FD_ZERO(&set);
FD_SET(fd, &set);
- if (!select(fd+1, &set, NULL, NULL, &tv)) return -1;
- if (read(fd, c, 1) != 1) return -1;
+ if (!select(fd + 1, &set, NULL, NULL, &tv))
+ return -1;
+ if (read(fd, c, 1) != 1)
+ return -1;
+
return 0;
}
-
-
-void setline(int fd, int flags, int speed)
+static void setline(int fd, int flags, int speed)
{
struct termios t;
@@ -87,10 +91,11 @@
tcsetattr(fd, TCSANOW, &t);
}
-int logitech_command(int fd, char *c)
+static int logitech_command(int fd, char *c)
{
int i;
unsigned char d;
+
for (i = 0; c[i]; i++) {
write(fd, c + i, 1);
if (readchar(fd, &d, 1000))
@@ -101,27 +106,32 @@
return 0;
}
-int magellan_init(int fd, long *id, long *extra)
+static int magellan_init(int fd, unsigned long *id, unsigned long *extra)
{
write(fd, "m3\rpBB\rz\r", 9);
return 0;
}
-int warrior_init(int fd, long *id, long *extra)
+static int warrior_init(int fd, unsigned long *id, unsigned long *extra)
{
- if (logitech_command(fd, "*S")) return -1;
+ if (logitech_command(fd, "*S"))
+ return -1;
+
setline(fd, CS8, B4800);
return 0;
}
-int spaceball_waitchar(int fd, unsigned char c, unsigned char *d, int timeout)
+static int spaceball_waitchar(int fd, unsigned char c, unsigned char *d,
+ int timeout)
{
unsigned char b = 0;
while (!readchar(fd, &b, timeout)) {
- if (b == 0x0a) continue;
+ if (b == 0x0a)
+ continue;
*d++ = b;
- if (b == c) break;
+ if (b == c)
+ break;
}
*d = 0;
@@ -129,7 +139,7 @@
return -(b != c);
}
-int spaceball_waitcmd(int fd, char c, char *d)
+static int spaceball_waitcmd(int fd, char c, char *d)
{
int i;
@@ -143,7 +153,7 @@
return -1;
}
-int spaceball_cmd(int fd, char *c, char *d)
+static int spaceball_cmd(int fd, char *c, char *d)
{
int i;
@@ -161,9 +171,9 @@
#define SPACEBALL_2003C 4
#define SPACEBALL_3003C 7
#define SPACEBALL_4000FLX 8
-#define SPACEBALL_4000FLX_L 9
+#define SPACEBALL_4000FLX_L 9
-int spaceball_init(int fd, long *id, long *extra)
+static int spaceball_init(int fd, unsigned long *id, unsigned long *extra)
{
char r[64];
@@ -172,13 +182,13 @@
return -1;
if (spaceball_waitcmd(fd, '@', r))
- return -1;
+ return -1;
if (strncmp("@1 Spaceball alive", r, 18))
return -1;
if (spaceball_waitcmd(fd, '@', r))
- return -1;
+ return -1;
if (spaceball_cmd(fd, "hm", r))
return -1;
@@ -199,7 +209,7 @@
return -1;
if (spaceball_waitcmd(fd, '"', r))
- return -1;
+ return -1;
if (strstr(r, " L "))
*id = SPACEBALL_4000FLX_L;
@@ -207,13 +217,13 @@
*id = SPACEBALL_4000FLX;
if (spaceball_waitcmd(fd, '"', r))
- return -1;
+ return -1;
if (spaceball_cmd(fd, "YS", r))
- return -1;
+ return -1;
if (spaceball_cmd(fd, "M", r))
- return -1;
+ return -1;
return 0;
}
@@ -226,70 +236,79 @@
return 0;
}
-int stinger_init(int fd, long *id, long *extra)
+static int stinger_init(int fd, unsigned long *id, unsigned long *extra)
{
int i;
unsigned char c;
unsigned char *response = "\r\n0600520058C272";
if (write(fd, " E5E5", 5) != 5) /* Enable command */
- return -1;
+ return -1;
for (i = 0; i < 16; i++) /* Check for Stinger */
- if (readchar(fd, &c, 200) || (c != response[i]))
+ if (readchar(fd, &c, 200) || c != response[i])
return -1;
return 0;
}
-int mzp_init(int fd, long *id, long *extra)
+static int mzp_init(int fd, unsigned long *id, unsigned long *extra)
{
- if (logitech_command(fd, "*X*q")) return -1;
+ if (logitech_command(fd, "*X*q"))
+ return -1;
+
setline(fd, CS8, B9600);
return 0;
}
-int newton_init(int fd, long *id, long *extra)
+static int newton_init(int fd, unsigned long *id, unsigned long *extra)
{
- int i;
- unsigned char c;
- unsigned char response[35] =
- { 0x16, 0x10, 0x02, 0x64, 0x5f, 0x69, 0x64, 0x00,
- 0x00, 0x00, 0x0c, 0x6b, 0x79, 0x62, 0x64, 0x61,
- 0x70, 0x70, 0x6c, 0x00, 0x00, 0x00, 0x01, 0x6e,
- 0x6f, 0x66, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x10,
- 0x03, 0xdd, 0xe7 };
+ int i;
+ unsigned char c;
+ unsigned char response[35] = {
+ 0x16, 0x10, 0x02, 0x64, 0x5f, 0x69, 0x64, 0x00,
+ 0x00, 0x00, 0x0c, 0x6b, 0x79, 0x62, 0x64, 0x61,
+ 0x70, 0x70, 0x6c, 0x00, 0x00, 0x00, 0x01, 0x6e,
+ 0x6f, 0x66, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x10,
+ 0x03, 0xdd, 0xe7
+ };
- for (i = 0; i < 35; i++)
- if (readchar(fd, &c, 400) || (c != response[i]))
- return -1;
+ for (i = 0; i < sizeof(response); i++)
+ if (readchar(fd, &c, 400) || c != response[i])
+ return -1;
- return 0;
+ return 0;
}
-int twiddler_init(int fd, long *id, long *extra)
+static int twiddler_init(int fd, unsigned long *id, unsigned long *extra)
{
unsigned char c[10];
int count, line;
/* Turn DTR off, otherwise the Twiddler won't send any data. */
- if (ioctl(fd, TIOCMGET, &line)) return -1;
+ if (ioctl(fd, TIOCMGET, &line))
+ return -1;
line &= ~TIOCM_DTR;
- if (ioctl(fd, TIOCMSET, &line)) return -1;
+ if (ioctl(fd, TIOCMSET, &line))
+ return -1;
- /* Check whether the device on the serial line is the Twiddler.
+ /*
+ * Check whether the device on the serial line is the Twiddler.
*
* The Twiddler sends data packets of 5 bytes which have the following
* properties: the MSB is 0 on the first and 1 on all other bytes, and
* the high order nibble of the last byte is always 0x8.
*
* We read and check two of those 5 byte packets to be sure that we
- * are indeed talking to a Twiddler. */
+ * are indeed talking to a Twiddler.
+ */
/* Read at most 5 bytes until we find one with the MSB set to 0 */
for (count = 0; count < 5; count++) {
- if (readchar(fd, c+0, 500)) return -1;
- if ((c[0] & 0x80) == 0) break;
+ if (readchar(fd, c, 500))
+ return -1;
+ if ((c[0] & 0x80) == 0)
+ break;
}
if (count == 5) {
@@ -298,16 +317,16 @@
}
/* Read remaining 4 bytes plus the full next data packet */
- for (count = 1; count < 10; count++) {
- if (readchar(fd, c+count, 500)) return -1;
- }
+ for (count = 1; count < 10; count++)
+ if (readchar(fd, c + count, 500))
+ return -1;
/* Check whether the bytes of both data packets obey the rules */
for (count = 1; count < 10; count++) {
- if ((count % 5 == 0 && (c[count] & 0x80) != 0)
- || (count % 5 == 4 && (c[count] & 0xF0) != 0x80)
- || (count % 5 != 0 && (c[count] & 0x80) != 0x80)) {
- /* Invalid byte in data packet */
+ if ((count % 5 == 0 && (c[count] & 0x80) != 0x00) ||
+ (count % 5 == 4 && (c[count] & 0xF0) != 0x80) ||
+ (count % 5 != 0 && (c[count] & 0x80) != 0x80)) {
+ /* Invalid byte in data packet */
return -1;
}
}
@@ -315,8 +334,36 @@
return 0;
}
-int dump_init(int fd, long *id, long *extra)
+static int fujitsu_init(int fd, unsigned long *id, unsigned long *extra)
{
+ unsigned char cmd, data;
+
+ /* Wake up the touchscreen */
+ cmd = 0xff; /* Dummy data */;
+ if (write(fd, &cmd, 1) != 1)
+ return -1;
+
+ /* Wait to settle down */
+ usleep(100 * 1000); /* 100 ms */
+
+ /* Reset the touchscreen */
+ cmd = 0x81; /* Cold reset */
+ if (write(fd, &cmd, 1) != 1)
+ return -1;
+
+ /* Read ACK */
+ if (readchar(fd, &data, 100) || (data & 0xbf) != 0x90)
+ return -1;
+
+ /* Read status */
+ if (readchar(fd, &data, 100) || data != 0x00)
+ return -1;
+
+ return 0;
+}
+
+static int dump_init(int fd, unsigned long *id, unsigned long *extra)
+{
unsigned char c, o = 0;
c = 0x80;
@@ -337,136 +384,237 @@
}
struct input_types {
- char name[16];
- char name2[16];
+ const char *name;
+ const char *name2;
+ const char *desc;
int speed;
int flags;
unsigned long type;
unsigned long id;
unsigned long extra;
int flush;
- int (*init)(int fd, long *id, long *extra);
+ int (*init)(int fd, unsigned long *id, unsigned long *extra);
};
-struct input_types input_types[] = {
+static struct input_types input_types[] = {
+{ "--sunkbd", "-skb", "Sun Type 4 and Type 5 keyboards",
+ B1200, CS8,
+ SERIO_SUNKBD, 0x00, 0x00, 1, NULL },
+{ "--lkkbd", "-lk", "DEC LK201 / LK401 keyboards",
+ B4800, CS8|CSTOPB,
+ SERIO_LKKBD, 0x00, 0x00, 1, NULL },
+{ "--vsxxx-aa", "-vs",
+ "DEC VSXXX-AA / VSXXX-GA mouse and VSXXX-A tablet",
+ B4800, CS8|CSTOPB|PARENB|PARODD,
+ SERIO_VSXXXAA, 0x00, 0x00, 1, NULL },
+{ "--spaceorb", "-orb", "SpaceOrb 360 / SpaceBall Avenger",
+ B9600, CS8,
+ SERIO_SPACEORB, 0x00, 0x00, 1, NULL },
+{ "--spaceball", "-sbl", "SpaceBall 2003 / 3003 / 4000 FLX",
+ B9600, CS8,
+ SERIO_SPACEBALL, 0x00, 0x00, 0, spaceball_init },
+{ "--magellan", "-mag", "Magellan / SpaceMouse",
+ B9600, CS8 | CSTOPB | CRTSCTS,
+ SERIO_MAGELLAN, 0x00, 0x00, 1, magellan_init },
+{ "--warrior", "-war", "WingMan Warrior",
+ B1200, CS7 | CSTOPB,
+ SERIO_WARRIOR, 0x00, 0x00, 1, warrior_init },
+{ "--stinger", "-sting", "Gravis Stinger",
+ B1200, CS8,
+ SERIO_STINGER, 0x00, 0x00, 1, stinger_init },
+{ "--mousesystems", "-msc", "3-button Mouse Systems mouse",
+ B1200, CS8,
+ SERIO_MSC, 0x00, 0x01, 1, NULL },
+{ "--sunmouse", "-sun", "3-button Sun mouse",
+ B1200, CS8,
+ SERIO_SUN, 0x00, 0x01, 1, NULL },
+{ "--microsoft", "-bare", "2-button Microsoft mouse",
+ B1200, CS7,
+ SERIO_MS, 0x00, 0x00, 1, NULL },
+{ "--mshack", "-ms", "3-button mouse in Microsoft mode",
+ B1200, CS7,
+ SERIO_MS, 0x00, 0x01, 1, NULL },
+{ "--mouseman", "-mman", "3-button Logitech / Genius mouse",
+ B1200, CS7,
+ SERIO_MP, 0x00, 0x01, 1, NULL },
+{ "--intellimouse", "-ms3", "Microsoft IntelliMouse",
+ B1200, CS7,
+ SERIO_MZ, 0x00, 0x11, 1, NULL },
+{ "--mmwheel", "-mmw",
+ "Logitech mouse with 4-5 buttons or a wheel",
+ B1200, CS7 | CSTOPB,
+ SERIO_MZP, 0x00, 0x13, 1, mzp_init },
+{ "--iforce", "-ifor", "I-Force joystick or wheel",
+ B38400, CS8,
+ SERIO_IFORCE, 0x00, 0x00, 0, NULL },
+{ "--newtonkbd", "-newt", "Newton keyboard",
+ B9600, CS8,
+ SERIO_NEWTON, 0x00, 0x00, 1, newton_init },
+{ "--h3600ts", "-ipaq", "Ipaq h3600 touchscreen",
+ B115200, CS8,
+ SERIO_H3600, 0x00, 0x00, 0, NULL },
+{ "--stowawaykbd", "-ipaqkbd", "Stowaway keyboard",
+ B115200, CS8,
+ SERIO_STOWAWAY, 0x00, 0x00, 1, NULL },
+{ "--ps2serkbd", "-ps2ser", "PS/2 via serial keyboard",
+ B1200, CS8,
+ SERIO_PS2SER, 0x00, 0x00, 1, NULL },
+{ "--twiddler", "-twid", "Handykey Twiddler chording keyboard",
+ B2400, CS8,
+ SERIO_TWIDKBD, 0x00, 0x00, 0, twiddler_init },
+{ "--twiddler-joy", "-twidjoy", "Handykey Twiddler used as a joystick",
+ B2400, CS8,
+ SERIO_TWIDJOY, 0x00, 0x00, 0, twiddler_init },
+{ "--elotouch", "-elo", "ELO touchscreen, 10-byte mode",
+ B9600, CS8 | CRTSCTS,
+ SERIO_ELO, 0x00, 0x00, 0, NULL },
+{ "--elo4002", "-elo6b", "ELO touchscreen, 6-byte mode",
+ B9600, CS8 | CRTSCTS,
+ SERIO_ELO, 0x01, 0x00, 0, NULL },
+{ "--elo271-140", "-elo4b", "ELO touchscreen, 4-byte mode",
+ B9600, CS8 | CRTSCTS,
+ SERIO_ELO, 0x02, 0x00, 0, NULL },
+{ "--elo261-280", "-elo3b", "ELO Touchscreen, 3-byte mode",
+ B9600, CS8 | CRTSCTS,
+ SERIO_ELO, 0x03, 0x00, 0, NULL },
+{ "--mtouch", "-mtouch", "MicroTouch (3M) touchscreen",
+ B9600, CS8 | CRTSCTS,
+ SERIO_MICROTOUCH, 0x00, 0x00, 0, NULL },
+{ "--touchright", "-tr", "Touchright serial touchscreen",
+ B9600, CS8 | CRTSCTS,
+ SERIO_TOUCHRIGHT, 0x00, 0x00, 0, NULL },
+{ "--touchwin", "-tw", "Touchwindow serial touchscreen",
+ B4800, CS8 | CRTSCTS,
+ SERIO_TOUCHWIN, 0x00, 0x00, 0, NULL },
+{ "--penmount", "-pm", "Penmount touchscreen",
+ B19200, CS8 | CRTSCTS,
+ SERIO_PENMOUNT, 0x00, 0x00, 0, NULL },
+{ "--fujitsu", "-fjt", "Fujitsu serial touchscreen",
+ B9600, CS8,
+ SERIO_FUJITSU, 0x00, 0x00, 1, fujitsu_init },
+{ "--dump", "-dump", "Just enable device",
+ B2400, CS8,
+ 0, 0x00, 0x00, 0, dump_init },
+{ NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, NULL }
+};
-{ "--sunkbd", "-skb", B1200, CS8, SERIO_SUNKBD, 0, 0, 1, NULL },
-{ "--lkkbd", "-lk", B4800, CS8|CSTOPB, SERIO_LKKBD, 0, 0, 1, NULL },
-{ "--vsxxx-aa", "-vs", B4800, CS8|CSTOPB|PARENB|PARODD,SERIO_VSXXXAA, 0, 0, 1, NULL },
-{ "--spaceorb", "-orb", B9600, CS8, SERIO_SPACEORB, 0, 0, 1, NULL },
-{ "--spaceball", "-sbl", B9600, CS8, SERIO_SPACEBALL,0, 0, 0, spaceball_init },
-{ "--magellan", "-mag", B9600, CS8 | CSTOPB | CRTSCTS, SERIO_MAGELLAN, 0, 0, 1, magellan_init },
-{ "--warrior", "-war", B1200, CS7 | CSTOPB, SERIO_WARRIOR, 0, 0, 1, warrior_init },
-{ "--stinger", "-sting", B1200, CS8, SERIO_STINGER, 0, 0, 1, stinger_init },
-{ "--mousesystems", "-msc", B1200, CS8, SERIO_MSC, 0, 0x01, 1, NULL },
-{ "--sunmouse", "-sun", B1200, CS8, SERIO_SUN, 0, 0x01, 1, NULL },
-{ "--microsoft", "-bare", B1200, CS7, SERIO_MS, 0, 0, 1, NULL },
-{ "--mshack", "-ms", B1200, CS7, SERIO_MS, 0, 0x01, 1, NULL },
-{ "--mouseman", "-mman", B1200, CS7, SERIO_MP, 0, 0x01, 1, NULL },
-{ "--intellimouse", "-ms3", B1200, CS7, SERIO_MZ, 0, 0x11, 1, NULL },
-{ "--mmwheel", "-mmw", B1200, CS7 | CSTOPB, SERIO_MZP, 0, 0x13, 1, mzp_init },
-{ "--iforce", "-ifor", B38400, CS8, SERIO_IFORCE, 0, 0, 0, NULL },
-{ "--newtonkbd", "-newt", B9600, CS8, SERIO_NEWTON, 0, 0, 0, newton_init },
-{ "--h3600ts", "-ipaq", B115200, CS8, SERIO_H3600, 0, 0, 0, NULL },
-{ "--stowawaykbd", "-ipaqkbd", B115200, CS8, SERIO_STOWAWAY, 0, 0, 0, NULL },
-{ "--ps2serkbd", "-ps2ser", B1200, CS8, SERIO_PS2SER, 0, 0, 1, NULL },
-{ "--twiddler", "-twid", B2400, CS8, SERIO_TWIDKBD, 0, 0, 0, twiddler_init },
-{ "--twiddler-joy", "-twidjoy", B2400, CS8, SERIO_TWIDJOY, 0, 0, 0, twiddler_init },
-{ "--elotouch", "-elo", B9600, CS8 | CRTSCTS, SERIO_ELO, 0, 0, 0, NULL },
-{ "--elo4002", "-elo6b", B9600, CS8 | CRTSCTS, SERIO_ELO, 1, 0, 0, NULL },
-{ "--elo271-140", "-elo4b", B9600, CS8 | CRTSCTS, SERIO_ELO, 2, 0, 0, NULL },
-{ "--elo261-280", "-elo3b", B9600, CS8 | CRTSCTS, SERIO_ELO, 3, 0, 0, NULL },
-{ "--dump", "-dump", B2400, CS8, 0, 0, 0, 0, dump_init },
-{ "", "", 0, 0 }
+static void show_help(void)
+{
+ struct input_types *type;
-};
+ puts("");
+ puts("Usage: inputattach [--daemon] <mode> <device>");
+ puts("");
+ puts("Modes:");
+ for (type = input_types; type->name; type++)
+ printf(" %-16s %-8s %s\n",
+ type->name, type->name2, type->desc);
+
+ puts("");
+}
+
int main(int argc, char **argv)
{
unsigned long devt;
int ldisc;
- int type;
- long id, extra;
- int fd;
+ struct input_types *type = NULL;
+ const char *device = NULL;
+ int daemon_mode = 0;
+ int need_device = 0;
+ unsigned long id, extra;
+ int fd;
+ int i;
char c;
+ int retval;
- if (argc < 2 || argc > 3 || !strcmp("--help", argv[1])) {
- puts("");
- puts("Usage: inputttach <mode> <device>");
- puts("");
- puts("Modes:");
- puts(" --sunkbd -skb Sun Type 4 and Type 5 keyboards");
- puts(" --lkkbd -lk DEC LK201 / LK401 keyboards");
- puts(" --vsxxx-aa -vs DEC VSXXX-AA / VSXXX-GA mouse and VSXXX-AB tablet");
- puts(" --spaceorb -orb SpaceOrb 360 / SpaceBall Avenger");
- puts(" --spaceball -sbl SpaceBall 2003 / 3003 / 4000 FLX");
- puts(" --magellan -mag Magellan / SpaceMouse");
- puts(" --warrior -war WingMan Warrior");
- puts(" --stinger -stng Gravis Stinger");
- puts(" --mousesystems -msc 3-button Mouse Systems mice");
- puts(" --sunmouse -sun 3-button Sun mice");
- puts(" --microsoft -bare 2-button Microsoft mice");
- puts(" --mshack -ms 3-button mice in Microsoft mode");
- puts(" --mouseman -mman 3-button Logitech and Genius mice");
- puts(" --intellimouse -ms3 Microsoft IntelliMouse");
- puts(" --mmwheel -mmw Logitech mice with 4-5 buttons or wheel");
- puts(" --iforce -ifor I-Force joysticks and wheels");
- puts(" --h3600ts -ipaq Ipaq h3600 touchscreen");
- puts(" --stowawaykbd -ipaqkbd Stowaway keyboard");
- puts(" --ps2serkbd -ps2ser PS/2 via serial keyboard");
- puts(" --twiddler -twid Handykey Twiddler chording keyboard");
- puts(" --twiddler-joy -twidjoy Handykey Twiddler used as a joystick");
- puts("");
- return 1;
- }
+ for (i = 1; i < argc; i++) {
+ if (!strcasecmp(argv[i], "--help")) {
+ show_help();
+ return EXIT_SUCCESS;
+ } else if (!strcasecmp(argv[i], "--daemon")) {
+ daemon_mode = 1;
+ } else if (need_device) {
+ device = argv[i];
+ need_device = 0;
+ } else {
+ if (type && type->name) {
+ fprintf(stderr,
+ "inputattach: '%s' - "
+ "only one mode allowed\n", argv[i]);
+ return EXIT_FAILURE;
+ }
+ for (type = input_types; type->name; type++) {
+ if (!strcasecmp(argv[i], type->name) ||
+ !strcasecmp(argv[i], type->name2)) {
+ break;
+ }
+ }
+ if (!type->name) {
+ fprintf(stderr,
+ "inputattach: invalid mode '%s'\n",
+ argv[i]);
+ return EXIT_FAILURE;
+ }
+ need_device = 1;
+ }
+ }
- for (type = 0; input_types[type].speed; type++) {
- if (!strncasecmp(argv[1], input_types[type].name, 16) ||
- !strncasecmp(argv[1], input_types[type].name2, 16))
- break;
+ if (!type || !type->name) {
+ fprintf(stderr, "inputattach: must specify mode\n");
+ return EXIT_FAILURE;
}
- if (!input_types[type].speed) {
- fprintf(stderr, "inputattach: invalid mode\n");
- return 1;
+ if (need_device) {
+ fprintf(stderr, "inputattach: must specify device\n");
+ return EXIT_FAILURE;
}
- if ((fd = open(argv[2], O_RDWR | O_NOCTTY | O_NONBLOCK)) < 0) {
- perror("inputattach");
+ fd = open(device, O_RDWR | O_NOCTTY | O_NONBLOCK);
+ if (fd < 0) {
+ fprintf(stderr, "inputattach: '%s' - %s\n",
+ device, strerror(errno));
return 1;
}
- setline(fd, input_types[type].flags, input_types[type].speed);
+ setline(fd, type->flags, type->speed);
- if (input_types[type].flush)
- while (!readchar(fd, &c, 100));
+ if (type->flush)
+ while (!readchar(fd, &c, 100))
+ /* empty */;
- id = input_types[type].id;
- extra = input_types[type].extra;
+ id = type->id;
+ extra = type->extra;
- if (input_types[type].init && input_types[type].init(fd, &id, &extra)) {
+ if (type->init && type->init(fd, &id, &extra)) {
fprintf(stderr, "inputattach: device initialization failed\n");
- return 1;
+ return EXIT_FAILURE;
}
ldisc = N_MOUSE;
- if(ioctl(fd, TIOCSETD, &ldisc)) {
- fprintf(stderr, "inputattach: can't set line discipline\n");
- return 1;
+ if (ioctl(fd, TIOCSETD, &ldisc)) {
+ fprintf(stderr, "inputattach: can't set line discipline\n");
+ return EXIT_FAILURE;
}
- devt = input_types[type].type | (id << 8) | (extra << 16);
+ devt = type->type | (id << 8) | (extra << 16);
- if(ioctl(fd, SPIOCSTYPE, &devt)) {
+ if (ioctl(fd, SPIOCSTYPE, &devt)) {
fprintf(stderr, "inputattach: can't set device type\n");
- return 1;
+ return EXIT_FAILURE;
}
+ retval = EXIT_SUCCESS;
+ if (daemon_mode && daemon(0, 0) < 0) {
+ perror("inputattach");
+ retval = EXIT_FAILURE;
+ }
+
read(fd, NULL, 0);
ldisc = 0;
ioctl(fd, TIOCSETD, &ldisc);
close(fd);
- return 0;
+ return retval;
}
Added: trunk/utils/serio-ids.h
===================================================================
--- trunk/utils/serio-ids.h (rev 0)
+++ trunk/utils/serio-ids.h 2010-09-23 11:41:12 UTC (rev 2385)
@@ -0,0 +1,111 @@
+#ifndef _SERIO_IDS_H
+#define _SERIO_IDS_H
+
+#ifndef SERIO_RS232
+# define SERIO_RS232 0x02
+#endif
+
+/*
+ * Serio types
+ */
+#ifndef SERIO_UNKNOWN
+# define SERIO_UNKNOWN 0x00
+#endif
+#ifndef SERIO_MSC
+# define SERIO_MSC 0x01
+#endif
+#ifndef SERIO_SUN
+# define SERIO_SUN 0x02
+#endif
+#ifndef SERIO_MS
+# define SERIO_MS 0x03
+#endif
+#ifndef SERIO_MP
+# define SERIO_MP 0x04
+#endif
+#ifndef SERIO_MZ
+# define SERIO_MZ 0x05
+#endif
+#ifndef SERIO_MZP
+# define SERIO_MZP 0x06
+#endif
+#ifndef SERIO_MZPP
+# define SERIO_MZPP 0x07
+#endif
+#ifndef SERIO_VSXXXAA
+# define SERIO_VSXXXAA 0x08
+#endif
+#ifndef SERIO_SUNKBD
+# define SERIO_SUNKBD 0x10
+#endif
+#ifndef SERIO_WARRIOR
+# define SERIO_WARRIOR 0x18
+#endif
+#ifndef SERIO_SPACEORB
+# define SERIO_SPACEORB 0x19
+#endif
+#ifndef SERIO_MAGELLAN
+# define SERIO_MAGELLAN 0x1a
+#endif
+#ifndef SERIO_SPACEBALL
+# define SERIO_SPACEBALL 0x1b
+#endif
+#ifndef SERIO_GUNZE
+# define SERIO_GUNZE 0x1c
+#endif
+#ifndef SERIO_IFORCE
+# define SERIO_IFORCE 0x1d
+#endif
+#ifndef SERIO_STINGER
+# define SERIO_STINGER 0x1e
+#endif
+#ifndef SERIO_NEWTON
+# define SERIO_NEWTON 0x1f
+#endif
+#ifndef SERIO_STOWAWAY
+# define SERIO_STOWAWAY 0x20
+#endif
+#ifndef SERIO_H3600
+# define SERIO_H3600 0x21
+#endif
+#ifndef SERIO_PS2SER
+# define SERIO_PS2SER 0x22
+#endif
+#ifndef SERIO_TWIDKBD
+# define SERIO_TWIDKBD 0x23
+#endif
+#ifndef SERIO_TWIDJOY
+# define SERIO_TWIDJOY 0x24
+#endif
+#ifndef SERIO_HIL
+# define SERIO_HIL 0x25
+#endif
+#ifndef SERIO_SNES232
+# define SERIO_SNES232 0x26
+#endif
+#ifndef SERIO_SEMTECH
+# define SERIO_SEMTECH 0x27
+#endif
+#ifndef SERIO_LKKBD
+# define SERIO_LKKBD 0x28
+#endif
+#ifndef SERIO_ELO
+# define SERIO_ELO 0x29
+#endif
+#ifndef SERIO_MICROTOUCH
+# define SERIO_MICROTOUCH 0x30
+#endif
+#ifndef SERIO_PENMOUNT
+# define SERIO_PENMOUNT 0x31
+#endif
+#ifndef SERIO_TOUCHRIGHT
+# define SERIO_TOUCHRIGHT 0x32
+#endif
+#ifndef SERIO_TOUCHWIN
+# define SERIO_TOUCHWIN 0x33
+#endif
+#ifndef SERIO_FUJITSU
+# define SERIO_FUJITSU 0x34
+#endif
+
+#endif
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <jsi...@us...> - 2007-07-17 18:50:29
|
Revision: 2384
http://linuxconsole.svn.sourceforge.net/linuxconsole/?rev=2384&view=rev
Author: jsimmons
Date: 2007-07-17 11:50:21 -0700 (Tue, 17 Jul 2007)
Log Message:
-----------
pm is obsolete
Modified Paths:
--------------
branches/ruby-2.6.21/ruby-2.6/include/linux/vt_kern.h
Modified: branches/ruby-2.6.21/ruby-2.6/include/linux/vt_kern.h
===================================================================
--- branches/ruby-2.6.21/ruby-2.6/include/linux/vt_kern.h 2007-07-16 18:14:58 UTC (rev 2383)
+++ branches/ruby-2.6.21/ruby-2.6/include/linux/vt_kern.h 2007-07-17 18:50:21 UTC (rev 2384)
@@ -6,7 +6,6 @@
*/
#include <linux/module.h>
-#include <linux/pm.h>
#include <linux/vt.h>
#include <linux/mutex.h>
#include <linux/kbd_kern.h>
@@ -244,7 +243,6 @@
int blank_timer_expired;
struct timer_list timer; /* Timer for VT blanking */
struct timer_list beep; /* Timer for adjusting console beeping */
- struct pm_dev *pm_con; /* power management */
/*
* This is a temporary buffer used to prepare a tty console write
* so that we can easily avoid touching user space while holding the
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <jsi...@us...> - 2007-07-16 18:14:59
|
Revision: 2383
http://linuxconsole.svn.sourceforge.net/linuxconsole/?rev=2383&view=rev
Author: jsimmons
Date: 2007-07-16 11:14:58 -0700 (Mon, 16 Jul 2007)
Log Message:
-----------
update to 2.6.22
Modified Paths:
--------------
branches/ruby-2.6.21/ruby-2.6/arch/x86_64/kernel/setup.c
branches/ruby-2.6.21/ruby-2.6/drivers/char/Kconfig
branches/ruby-2.6.21/ruby-2.6/drivers/char/Makefile
branches/ruby-2.6.21/ruby-2.6/drivers/char/consolemap.c
branches/ruby-2.6.21/ruby-2.6/drivers/char/decvte.c
branches/ruby-2.6.21/ruby-2.6/drivers/char/keyboard.c
branches/ruby-2.6.21/ruby-2.6/drivers/char/selection.c
branches/ruby-2.6.21/ruby-2.6/drivers/char/sysrq.c
branches/ruby-2.6.21/ruby-2.6/drivers/char/tty_io.c
branches/ruby-2.6.21/ruby-2.6/drivers/char/vc_screen.c
branches/ruby-2.6.21/ruby-2.6/drivers/char/vt.c
branches/ruby-2.6.21/ruby-2.6/drivers/char/vt_ioctl.c
branches/ruby-2.6.21/ruby-2.6/drivers/video/console/vgacon.c
branches/ruby-2.6.21/ruby-2.6/fs/compat_ioctl.c
branches/ruby-2.6.21/ruby-2.6/include/linux/console.h
branches/ruby-2.6.21/ruby-2.6/include/linux/tty.h
branches/ruby-2.6.21/ruby-2.6/include/linux/vt_kern.h
Added Paths:
-----------
branches/ruby-2.6.21/AGAINST-2.6.22
Removed Paths:
-------------
branches/ruby-2.6.21/AGAINST-2.6.12
branches/ruby-2.6.21/AGAINST-2.6.21
branches/ruby-2.6.21/ruby-2.6/drivers/input/
Deleted: branches/ruby-2.6.21/AGAINST-2.6.12
===================================================================
--- branches/ruby-2.6.21/AGAINST-2.6.12 2007-07-16 15:52:23 UTC (rev 2382)
+++ branches/ruby-2.6.21/AGAINST-2.6.12 2007-07-16 18:14:58 UTC (rev 2383)
@@ -1 +0,0 @@
-
Deleted: branches/ruby-2.6.21/AGAINST-2.6.21
===================================================================
--- branches/ruby-2.6.21/AGAINST-2.6.21 2007-07-16 15:52:23 UTC (rev 2382)
+++ branches/ruby-2.6.21/AGAINST-2.6.21 2007-07-16 18:14:58 UTC (rev 2383)
@@ -1 +0,0 @@
-
Copied: branches/ruby-2.6.21/AGAINST-2.6.22 (from rev 2380, branches/ruby-2.6.21/AGAINST-2.6.21)
===================================================================
--- branches/ruby-2.6.21/AGAINST-2.6.22 (rev 0)
+++ branches/ruby-2.6.21/AGAINST-2.6.22 2007-07-16 18:14:58 UTC (rev 2383)
@@ -0,0 +1 @@
+
Modified: branches/ruby-2.6.21/ruby-2.6/arch/x86_64/kernel/setup.c
===================================================================
--- branches/ruby-2.6.21/ruby-2.6/arch/x86_64/kernel/setup.c 2007-07-16 15:52:23 UTC (rev 2382)
+++ branches/ruby-2.6.21/ruby-2.6/arch/x86_64/kernel/setup.c 2007-07-16 18:14:58 UTC (rev 2383)
@@ -78,6 +78,8 @@
unsigned long saved_video_mode;
+int force_mwait __cpuinitdata;
+
/*
* Early DMI memory
*/
@@ -204,10 +206,10 @@
* there is a real-mode segmented pointer pointing to the
* 4K EBDA area at 0x40E
*/
- ebda_addr = *(unsigned short *)EBDA_ADDR_POINTER;
+ ebda_addr = *(unsigned short *)__va(EBDA_ADDR_POINTER);
ebda_addr <<= 4;
- ebda_size = *(unsigned short *)(unsigned long)ebda_addr;
+ ebda_size = *(unsigned short *)__va(ebda_addr);
/* Round EBDA up to pages */
if (ebda_size == 0)
@@ -273,8 +275,6 @@
dmi_scan_machine();
- zap_low_mappings(0);
-
#ifdef CONFIG_ACPI
/*
* Initialize the ACPI boot-time table parser (gets the RSDP and SDT).
@@ -328,15 +328,8 @@
#endif
#ifdef CONFIG_SMP
- /*
- * But first pinch a few for the stack/trampoline stuff
- * FIXME: Don't need the extra page at 4K, but need to fix
- * trampoline before removing it. (see the GDT stuff)
- */
- reserve_bootmem_generic(PAGE_SIZE, PAGE_SIZE);
-
/* Reserve SMP trampoline */
- reserve_bootmem_generic(SMP_TRAMPOLINE_BASE, PAGE_SIZE);
+ reserve_bootmem_generic(SMP_TRAMPOLINE_BASE, 2*PAGE_SIZE);
#endif
#ifdef CONFIG_ACPI_SLEEP
@@ -603,6 +596,10 @@
/* RDTSC can be speculated around */
clear_bit(X86_FEATURE_SYNC_RDTSC, &c->x86_capability);
+
+ /* Family 10 doesn't support C states in MWAIT so don't use it */
+ if (c->x86 == 0x10 && !force_mwait)
+ clear_bit(X86_FEATURE_MWAIT, &c->x86_capability);
}
static void __cpuinit detect_ht(struct cpuinfo_x86 *c)
@@ -885,9 +882,7 @@
#ifdef CONFIG_X86_MCE
mcheck_init(c);
#endif
- if (c == &boot_cpu_data)
- mtrr_bp_init();
- else
+ if (c != &boot_cpu_data)
mtrr_ap_init();
#ifdef CONFIG_NUMA
numa_add_cpu(smp_processor_id());
@@ -978,9 +973,8 @@
"stc",
"100mhzsteps",
"hwpstate",
- NULL, /* tsc invariant mapped to constant_tsc */
- NULL,
- /* nothing */ /* constant_tsc - moved to flags */
+ "", /* tsc invariant mapped to constant_tsc */
+ /* nothing */
};
Modified: branches/ruby-2.6.21/ruby-2.6/drivers/char/Kconfig
===================================================================
--- branches/ruby-2.6.21/ruby-2.6/drivers/char/Kconfig 2007-07-16 15:52:23 UTC (rev 2382)
+++ branches/ruby-2.6.21/ruby-2.6/drivers/char/Kconfig 2007-07-16 18:14:58 UTC (rev 2383)
@@ -6,6 +6,7 @@
config VT
bool "Virtual terminal" if EMBEDDED
+ depends on !S390
select INPUT
default y if !VIOCONS
---help---
@@ -88,6 +89,7 @@
config SERIAL_NONSTANDARD
bool "Non-standard serial port support"
+ depends on HAS_IOMEM
---help---
Say Y here if you have any non-standard serial boards -- boards
which aren't supported using the standard "dumb" serial driver.
@@ -134,7 +136,7 @@
config CYCLADES
tristate "Cyclades async mux support"
- depends on SERIAL_NONSTANDARD
+ depends on SERIAL_NONSTANDARD && (PCI || ISA)
---help---
This driver supports Cyclades Z and Y multiserial boards.
You would need something like this to connect more than two modems to
@@ -638,7 +640,8 @@
config HVC_ISERIES
bool "iSeries Hypervisor Virtual Console support"
- depends on PPC_ISERIES && !VIOCONS
+ depends on PPC_ISERIES
+ default y
select HVC_DRIVER
help
iSeries machines support a hypervisor virtual console.
@@ -771,7 +774,7 @@
config RTC
tristate "Enhanced Real Time Clock Support"
- depends on !PPC && !PARISC && !IA64 && !M68K && (!SPARC || PCI) && !FRV && !ARM && !SUPERH
+ depends on !PPC && !PARISC && !IA64 && !M68K && (!SPARC || PCI) && !FRV && !ARM && !SUPERH && !S390
---help---
If you say Y here and create a character special file /dev/rtc with
major number 10 and minor number 135 using mknod ("man mknod"), you
@@ -819,7 +822,7 @@
config GEN_RTC
tristate "Generic /dev/rtc emulation"
- depends on RTC!=y && !IA64 && !ARM && !M32R && !SPARC && !FRV
+ depends on RTC!=y && !IA64 && !ARM && !M32R && !SPARC && !FRV && !S390 && !SUPERH
---help---
If you say Y here and create a character special file /dev/rtc with
major number 10 and minor number 135 using mknod ("man mknod"), you
@@ -864,6 +867,7 @@
config DTLK
tristate "Double Talk PC internal speech card support"
+ depends on ISA
help
This driver is for the DoubleTalk PC, a speech synthesizer
manufactured by RC Systems (<http://www.rcsys.com/>). It is also
@@ -912,8 +916,8 @@
To compile this driver as a module, choose M here: the
module will be called sonypi.
-config TANBAC_TB0219
- tristate "TANBAC TB0219 base board support"
+config GPIO_TB0219
+ tristate "TANBAC TB0219 GPIO support"
depends on TANBAC_TB022X
select GPIO_VR41XX
@@ -1049,7 +1053,7 @@
config HANGCHECK_TIMER
tristate "Hangcheck timer"
- depends on X86 || IA64 || PPC64
+ depends on X86 || IA64 || PPC64 || S390
help
The hangcheck-timer module detects when the system has gone
out to lunch past a certain margin. It can reboot the system
@@ -1078,5 +1082,13 @@
/sys/devices/platform/telco_clock, with a number of files for
controlling the behavior of this hardware.
+config DEVPORT
+ bool
+ depends on !M68K
+ depends on ISA || PCI
+ default y
+
+source "drivers/s390/char/Kconfig"
+
endmenu
Modified: branches/ruby-2.6.21/ruby-2.6/drivers/char/Makefile
===================================================================
--- branches/ruby-2.6.21/ruby-2.6/drivers/char/Makefile 2007-07-16 15:52:23 UTC (rev 2382)
+++ branches/ruby-2.6.21/ruby-2.6/drivers/char/Makefile 2007-07-16 18:14:58 UTC (rev 2383)
@@ -91,7 +91,7 @@
obj-$(CONFIG_NSC_GPIO) += nsc_gpio.o
obj-$(CONFIG_CS5535_GPIO) += cs5535_gpio.o
obj-$(CONFIG_GPIO_VR41XX) += vr41xx_giu.o
-obj-$(CONFIG_TANBAC_TB0219) += tb0219.o
+obj-$(CONFIG_GPIO_TB0219) += tb0219.o
obj-$(CONFIG_TELCLOCK) += tlclk.o
obj-$(CONFIG_WATCHDOG) += watchdog/
Modified: branches/ruby-2.6.21/ruby-2.6/drivers/char/consolemap.c
===================================================================
--- branches/ruby-2.6.21/ruby-2.6/drivers/char/consolemap.c 2007-07-16 15:52:23 UTC (rev 2382)
+++ branches/ruby-2.6.21/ruby-2.6/drivers/char/consolemap.c 2007-07-16 18:14:58 UTC (rev 2383)
@@ -622,10 +622,10 @@
/* Only 16-bit codes supported at this time */
if (ucs > 0xffff)
- ucs = 0xfffd; /* U+FFFD: REPLACEMENT CHARACTER */
- else if (ucs < 0x20 || ucs >= 0xfffe)
+ return -4; /* Not found */
+ else if (ucs < 0x20)
return -1; /* Not a printable character */
- else if (ucs == 0xfeff || (ucs >= 0x200a && ucs <= 0x200f))
+ else if (ucs == 0xfeff || (ucs >= 0x200b && ucs <= 0x200f))
return -2; /* Zero-width space */
/*
* UNI_DIRECT_BASE indicates the start of the region in the User Zone
Modified: branches/ruby-2.6.21/ruby-2.6/drivers/char/decvte.c
===================================================================
--- branches/ruby-2.6.21/ruby-2.6/drivers/char/decvte.c 2007-07-16 15:52:23 UTC (rev 2382)
+++ branches/ruby-2.6.21/ruby-2.6/drivers/char/decvte.c 2007-07-16 18:14:58 UTC (rev 2383)
@@ -295,6 +295,9 @@
case 2: /* faint or decreased intensity */
vc->vc_intensity = 0;
break;
+ case 3: /* italic intensity */
+ vc->vc_italic = 1;
+ break;
case 4: /* singly underlined. */
vc->vc_underline = 1;
break;
@@ -338,6 +341,9 @@
case 22: /* normal intensity */
vc->vc_intensity = 1;
break;
+ case 23:
+ vc->vc_italic = 0;
+ break;
case 24: /* not underlined (neither singly nor doubly) */
vc->vc_underline = 0;
break;
@@ -912,6 +918,7 @@
vc->vc_saved_x = vc->vc_x;
vc->vc_saved_y = vc->vc_y;
vc->vc_s_intensity = vc->vc_intensity;
+ vc->vc_s_italic = vc->vc_italic;
vc->vc_s_underline = vc->vc_underline;
vc->vc_s_blink = vc->vc_blink;
vc->vc_s_reverse = vc->vc_reverse;
@@ -930,6 +937,7 @@
{
gotoxy(vc, vc->vc_saved_x, vc->vc_saved_y);
vc->vc_intensity = vc->vc_s_intensity;
+ vc->vc_italic = vc->vc_s_italic;
vc->vc_underline = vc->vc_s_underline;
vc->vc_blink = vc->vc_s_blink;
vc->vc_reverse = vc->vc_s_reverse;
@@ -974,7 +982,7 @@
vc->vc_charset = 0;
vc->vc_need_wrap = 0;
vc->vc_report_mouse = 0;
- vc->vc_utf = 0;
+ vc->vc_utf = default_utf8;
vc->vc_utf_count = 0;
vc->vc_disp_ctrl = 0;
Modified: branches/ruby-2.6.21/ruby-2.6/drivers/char/keyboard.c
===================================================================
--- branches/ruby-2.6.21/ruby-2.6/drivers/char/keyboard.c 2007-07-16 15:52:23 UTC (rev 2382)
+++ branches/ruby-2.6.21/ruby-2.6/drivers/char/keyboard.c 2007-07-16 18:14:58 UTC (rev 2383)
@@ -84,7 +84,7 @@
const int NR_TYPES = ARRAY_SIZE(max_vals);
struct vt_spawn_console vt_spawn_con = {
- .lock = SPIN_LOCK_UNLOCKED,
+ .lock = __SPIN_LOCK_UNLOCKED(vt_spawn_con.lock),
.pid = NULL,
.sig = 0,
};
Modified: branches/ruby-2.6.21/ruby-2.6/drivers/char/selection.c
===================================================================
--- branches/ruby-2.6.21/ruby-2.6/drivers/char/selection.c 2007-07-16 15:52:23 UTC (rev 2382)
+++ branches/ruby-2.6.21/ruby-2.6/drivers/char/selection.c 2007-07-16 18:14:58 UTC (rev 2383)
@@ -307,7 +307,7 @@
pasted += count;
}
remove_wait_queue(&vc->paste_wait, &wait);
- set_current_state(TASK_RUNNING);
+ __set_current_state(TASK_RUNNING);
tty_ldisc_deref(ld);
return 0;
}
Modified: branches/ruby-2.6.21/ruby-2.6/drivers/char/sysrq.c
===================================================================
--- branches/ruby-2.6.21/ruby-2.6/drivers/char/sysrq.c 2007-07-16 15:52:23 UTC (rev 2382)
+++ branches/ruby-2.6.21/ruby-2.6/drivers/char/sysrq.c 2007-07-16 18:14:58 UTC (rev 2383)
@@ -23,7 +23,6 @@
#include <linux/reboot.h>
#include <linux/sysrq.h>
#include <linux/quotaops.h>
-#include <linux/smp_lock.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/suspend.h>
Modified: branches/ruby-2.6.21/ruby-2.6/drivers/char/tty_io.c
===================================================================
--- branches/ruby-2.6.21/ruby-2.6/drivers/char/tty_io.c 2007-07-16 15:52:23 UTC (rev 2382)
+++ branches/ruby-2.6.21/ruby-2.6/drivers/char/tty_io.c 2007-07-16 18:14:58 UTC (rev 2383)
@@ -138,8 +138,6 @@
static int ptmx_open(struct inode *, struct file *);
#endif
-extern void disable_early_printk(void);
-
static void initialize_tty_struct(struct tty_struct *tty);
static ssize_t tty_read(struct file *, char __user *, size_t, loff_t *);
@@ -150,10 +148,16 @@
static int tty_release(struct inode *, struct file *);
int tty_ioctl(struct inode * inode, struct file * file,
unsigned int cmd, unsigned long arg);
+#ifdef CONFIG_COMPAT
+static long tty_compat_ioctl(struct file * file, unsigned int cmd,
+ unsigned long arg);
+#else
+#define tty_compat_ioctl NULL
+#endif
static int tty_fasync(int fd, struct file * filp, int on);
static void release_tty(struct tty_struct *tty, int idx);
-static struct pid *__proc_set_tty(struct task_struct *tsk,
- struct tty_struct *tty);
+static void __proc_set_tty(struct task_struct *tsk, struct tty_struct *tty);
+static void proc_set_tty(struct task_struct *tsk, struct tty_struct *tty);
/**
* alloc_tty_struct - allocate a tty object
@@ -362,6 +366,29 @@
}
/**
+ * tty_buffer_flush - flush full tty buffers
+ * @tty: tty to flush
+ *
+ * flush all the buffers containing receive data
+ *
+ * Locking: none
+ */
+
+static void tty_buffer_flush(struct tty_struct *tty)
+{
+ struct tty_buffer *thead;
+ unsigned long flags;
+
+ spin_lock_irqsave(&tty->buf.lock, flags);
+ while((thead = tty->buf.head) != NULL) {
+ tty->buf.head = thead->next;
+ tty_buffer_free(tty, thead);
+ }
+ tty->buf.tail = NULL;
+ spin_unlock_irqrestore(&tty->buf.lock, flags);
+}
+
+/**
* tty_buffer_find - find a free tty buffer
* @tty: tty owning the buffer
* @size: characters wanted
@@ -933,13 +960,6 @@
return -EINVAL;
/*
- * No more input please, we are switching. The new ldisc
- * will update this value in the ldisc open function
- */
-
- tty->receive_room = 0;
-
- /*
* Problem: What do we do if this blocks ?
*/
@@ -950,6 +970,13 @@
return 0;
}
+ /*
+ * No more input please, we are switching. The new ldisc
+ * will update this value in the ldisc open function
+ */
+
+ tty->receive_room = 0;
+
o_ldisc = tty->ldisc;
o_tty = tty->link;
@@ -1118,7 +1145,8 @@
return 0;
if (is_current_pgrp_orphaned())
return -EIO;
- (void) kill_pgrp(task_pgrp(current), SIGTTOU, 1);
+ kill_pgrp(task_pgrp(current), SIGTTOU, 1);
+ set_thread_flag(TIF_SIGPENDING);
return -ERESTARTSYS;
}
@@ -1148,12 +1176,19 @@
return cmd == TIOCSPGRP ? -ENOTTY : -EIO;
}
+static long hung_up_tty_compat_ioctl(struct file * file,
+ unsigned int cmd, unsigned long arg)
+{
+ return cmd == TIOCSPGRP ? -ENOTTY : -EIO;
+}
+
static const struct file_operations tty_fops = {
.llseek = no_llseek,
.read = tty_read,
.write = tty_write,
.poll = tty_poll,
.ioctl = tty_ioctl,
+ .compat_ioctl = tty_compat_ioctl,
.open = tty_open,
.release = tty_release,
.fasync = tty_fasync,
@@ -1166,6 +1201,7 @@
.write = tty_write,
.poll = tty_poll,
.ioctl = tty_ioctl,
+ .compat_ioctl = tty_compat_ioctl,
.open = ptmx_open,
.release = tty_release,
.fasync = tty_fasync,
@@ -1178,6 +1214,7 @@
.write = redirected_tty_write,
.poll = tty_poll,
.ioctl = tty_ioctl,
+ .compat_ioctl = tty_compat_ioctl,
.open = tty_open,
.release = tty_release,
.fasync = tty_fasync,
@@ -1189,6 +1226,7 @@
.write = hung_up_tty_write,
.poll = hung_up_tty_poll,
.ioctl = hung_up_tty_ioctl,
+ .compat_ioctl = hung_up_tty_compat_ioctl,
.release = tty_release,
};
@@ -1237,6 +1275,7 @@
ld->flush_buffer(tty);
tty_ldisc_deref(ld);
}
+ tty_buffer_flush(tty);
}
EXPORT_SYMBOL_GPL(tty_ldisc_flush);
@@ -1531,10 +1570,9 @@
}
spin_lock_irq(¤t->sighand->siglock);
- tty_pgrp = current->signal->tty_old_pgrp;
+ put_pid(current->signal->tty_old_pgrp);
current->signal->tty_old_pgrp = NULL;
spin_unlock_irq(¤t->sighand->siglock);
- put_pid(tty_pgrp);
mutex_lock(&tty_mutex);
/* It is possible that do_tty_hangup has free'd this tty */
@@ -1559,13 +1597,25 @@
unlock_kernel();
}
+/**
+ *
+ * no_tty - Ensure the current process does not have a controlling tty
+ */
+void no_tty(void)
+{
+ struct task_struct *tsk = current;
+ if (tsk->signal->leader)
+ disassociate_ctty(0);
+ proc_clear_tty(tsk);
+}
+
/**
- * stop_tty - propogate flow control
+ * stop_tty - propagate flow control
* @tty: tty to stop
*
* Perform flow control to the driver. For PTY/TTY pairs we
- * must also propogate the TIOCKPKT status. May be called
+ * must also propagate the TIOCKPKT status. May be called
* on an already stopped device and will not re-call the driver
* method.
*
@@ -1595,11 +1645,11 @@
EXPORT_SYMBOL(stop_tty);
/**
- * start_tty - propogate flow control
+ * start_tty - propagate flow control
* @tty: tty to start
*
* Start a tty that has been stopped if at all possible. Perform
- * any neccessary wakeups and propogate the TIOCPKT status. If this
+ * any neccessary wakeups and propagate the TIOCPKT status. If this
* is the tty was previous stopped and is being started then the
* driver start method is invoked and the line discipline woken.
*
@@ -2505,7 +2555,6 @@
int index;
dev_t device = inode->i_rdev;
unsigned short saved_flags = filp->f_flags;
- struct pid *old_pgrp;
nonseekable_open(inode, filp);
@@ -2609,17 +2658,15 @@
goto retry_open;
}
- old_pgrp = NULL;
mutex_lock(&tty_mutex);
spin_lock_irq(¤t->sighand->siglock);
if (!noctty &&
current->signal->leader &&
!current->signal->tty &&
tty->session == NULL)
- old_pgrp = __proc_set_tty(current, tty);
+ __proc_set_tty(current, tty);
spin_unlock_irq(¤t->sighand->siglock);
mutex_unlock(&tty_mutex);
- put_pid(old_pgrp);
return 0;
}
@@ -3294,9 +3341,7 @@
case TIOCNOTTY:
if (current->signal->tty != tty)
return -ENOTTY;
- if (current->signal->leader)
- disassociate_ctty(0);
- proc_clear_tty(current);
+ no_tty();
return 0;
case TIOCSCTTY:
return tiocsctty(tty, arg);
@@ -3343,6 +3388,15 @@
case TIOCMBIC:
case TIOCMBIS:
return tty_tiocmset(tty, file, cmd, p);
+ case TCFLSH:
+ switch (arg) {
+ case TCIFLUSH:
+ case TCIOFLUSH:
+ /* flush tty buffer and allow ldisc to process ioctl */
+ tty_buffer_flush(tty);
+ break;
+ }
+ break;
}
if (tty->driver->ioctl) {
retval = (tty->driver->ioctl)(tty, file, cmd, arg);
@@ -3360,7 +3414,33 @@
return retval;
}
+#ifdef CONFIG_COMPAT
+static long tty_compat_ioctl(struct file * file, unsigned int cmd,
+ unsigned long arg)
+{
+ struct inode *inode = file->f_dentry->d_inode;
+ struct tty_struct *tty = file->private_data;
+ struct tty_ldisc *ld;
+ int retval = -ENOIOCTLCMD;
+ if (tty_paranoia_check(tty, inode, "tty_ioctl"))
+ return -EINVAL;
+
+ if (tty->driver->compat_ioctl) {
+ retval = (tty->driver->compat_ioctl)(tty, file, cmd, arg);
+ if (retval != -ENOIOCTLCMD)
+ return retval;
+ }
+
+ ld = tty_ldisc_ref_wait(tty);
+ if (ld->compat_ioctl)
+ retval = ld->compat_ioctl(tty, file, cmd, arg);
+ tty_ldisc_deref(ld);
+
+ return retval;
+}
+#endif
+
/*
* This implements the "Secure Attention Key" --- the idea is to
* prevent trojan horses by killing all processes associated with this
@@ -3692,6 +3772,7 @@
driver->write_room = op->write_room;
driver->chars_in_buffer = op->chars_in_buffer;
driver->ioctl = op->ioctl;
+ driver->compat_ioctl = op->compat_ioctl;
driver->set_termios = op->set_termios;
driver->throttle = op->throttle;
driver->unthrottle = op->unthrottle;
@@ -3727,11 +3808,10 @@
if (driver->flags & TTY_DRIVER_INSTALLED)
return 0;
- if (!(driver->flags & TTY_DRIVER_DEVPTS_MEM)) {
- p = kmalloc(driver->num * 3 * sizeof(void *), GFP_KERNEL);
+ if (!(driver->flags & TTY_DRIVER_DEVPTS_MEM) && driver->num) {
+ p = kzalloc(driver->num * 3 * sizeof(void *), GFP_KERNEL);
if (!p)
return -ENOMEM;
- memset(p, 0, driver->num * 3 * sizeof(void *));
}
if (!driver->major) {
@@ -3774,7 +3854,9 @@
if (!driver->put_char)
driver->put_char = tty_default_put_char;
+ mutex_lock(&tty_mutex);
list_add(&driver->tty_drivers, &tty_drivers);
+ mutex_unlock(&tty_mutex);
if ( !(driver->flags & TTY_DRIVER_DYNAMIC_DEV) ) {
for(i = 0; i < driver->num; i++)
@@ -3800,8 +3882,9 @@
unregister_chrdev_region(MKDEV(driver->major, driver->minor_start),
driver->num);
-
+ mutex_lock(&tty_mutex);
list_del(&driver->tty_drivers);
+ mutex_unlock(&tty_mutex);
/*
* Free the termios and termios_locked structures because
@@ -3846,9 +3929,8 @@
}
EXPORT_SYMBOL(proc_clear_tty);
-static struct pid *__proc_set_tty(struct task_struct *tsk, struct tty_struct *tty)
+static void __proc_set_tty(struct task_struct *tsk, struct tty_struct *tty)
{
- struct pid *old_pgrp;
if (tty) {
/* We should not have a session or pgrp to here but.... */
put_pid(tty->session);
@@ -3856,21 +3938,16 @@
tty->session = get_pid(task_session(tsk));
tty->pgrp = get_pid(task_pgrp(tsk));
}
- old_pgrp = tsk->signal->tty_old_pgrp;
+ put_pid(tsk->signal->tty_old_pgrp);
tsk->signal->tty = tty;
tsk->signal->tty_old_pgrp = NULL;
- return old_pgrp;
}
-void proc_set_tty(struct task_struct *tsk, struct tty_struct *tty)
+static void proc_set_tty(struct task_struct *tsk, struct tty_struct *tty)
{
- struct pid *old_pgrp;
-
spin_lock_irq(&tsk->sighand->siglock);
- old_pgrp = __proc_set_tty(tsk, tty);
+ __proc_set_tty(tsk, tty);
spin_unlock_irq(&tsk->sighand->siglock);
-
- put_pid(old_pgrp);
}
struct tty_struct *get_current_tty(void)
@@ -3905,9 +3982,6 @@
* set up the console device so that later boot sequences can
* inform about problems etc..
*/
-#ifdef CONFIG_EARLY_PRINTK
- disable_early_printk();
-#endif
call = __con_initcall_start;
while (call < __con_initcall_end) {
(*call)();
Modified: branches/ruby-2.6.21/ruby-2.6/drivers/char/vc_screen.c
===================================================================
--- branches/ruby-2.6.21/ruby-2.6/drivers/char/vc_screen.c 2007-07-16 15:52:23 UTC (rev 2382)
+++ branches/ruby-2.6.21/ruby-2.6/drivers/char/vc_screen.c 2007-07-16 18:14:58 UTC (rev 2383)
@@ -31,8 +31,8 @@
#include <linux/vt_kern.h>
#include <linux/selection.h>
#include <linux/console.h>
-#include <linux/smp_lock.h>
#include <linux/device.h>
+
#include <asm/uaccess.h>
#include <asm/byteorder.h>
#include <asm/unaligned.h>
@@ -90,11 +90,11 @@
long attr = iminor(inode) & 128;
int size;
- down(&vc->display_fg->lock);
+ mutex_lock(&vc->display_fg->lock);
size = vcs_size(vc, attr);
switch (orig) {
default:
- up(&vc->display_fg->lock);
+ mutex_unlock(&vc->display_fg->lock);
return -EINVAL;
case 2:
offset += size;
@@ -105,11 +105,11 @@
break;
}
if (offset < 0 || offset > size) {
- up(&vc->display_fg->lock);
+ mutex_unlock(&vc->display_fg->lock);
return -EINVAL;
}
file->f_pos = offset;
- up(&vc->display_fg->lock);
+ mutex_unlock(&vc->display_fg->lock);
return file->f_pos;
}
@@ -127,7 +127,7 @@
if (!vc)
return ret;
- down(&vc->display_fg->lock);
+ mutex_lock(&vc->display_fg->lock);
pos = *ppos;
/*
@@ -276,7 +276,7 @@
ret = read;
unlock_out:
release_console_sem();
- up(&vc->display_fg->lock);
+ mutex_unlock(&vc->display_fg->lock);
return ret;
}
@@ -294,7 +294,7 @@
if (!vc)
return ret;
- down(&vc->display_fg->lock);
+ mutex_lock(&vc->display_fg->lock);
/*
* Select the proper current console and verify
@@ -455,7 +455,7 @@
unlock_out:
release_console_sem();
- up(&vc->display_fg->lock);
+ mutex_unlock(&vc->display_fg->lock);
return ret;
}
Modified: branches/ruby-2.6.21/ruby-2.6/drivers/char/vt.c
===================================================================
--- branches/ruby-2.6.21/ruby-2.6/drivers/char/vt.c 2007-07-16 15:52:23 UTC (rev 2382)
+++ branches/ruby-2.6.21/ruby-2.6/drivers/char/vt.c 2007-07-16 18:14:58 UTC (rev 2383)
@@ -147,6 +147,8 @@
static int kmsg_redirect = 0; /* kmsg_redirect is the VC for printk */
static int printable; /* Is console ready for printing? */
#endif
+static int default_utf8;
+module_param(default_utf8, int, S_IRUGO | S_IWUSR);
/*
* the default colour table, for colour systems
@@ -161,6 +163,10 @@
0x55,0x55,0x55,0x55,0xff,0xff,0xff,0xff
};
+module_param_array(default_red, int, NULL, S_IRUGO | S_IWUSR);
+module_param_array(default_grn, int, NULL, S_IRUGO | S_IWUSR);
+module_param_array(default_blu, int, NULL, S_IRUGO | S_IWUSR);
+
unsigned char color_table[] = { 0, 4, 2, 6, 1, 5, 3, 7,
8,12,10,14, 9,13,11,15
};
@@ -366,6 +372,7 @@
void default_attr(struct vc_data *vc)
{
vc->vc_intensity = 1;
+ vc->vc_italic = 0;
vc->vc_underline = 0;
vc->vc_reverse = 0;
vc->vc_blink = 0;
@@ -383,19 +390,24 @@
* Bit 3 : reverse
* Bit 7 : blink
*/
-static u8 build_attr(struct vc_data *vc, u8 _color, u8 _intensity, u8 _blink, u8 _underline, u8 _reverse)
+static u8 build_attr(struct vc_data *vc, u8 _color, u8 _intensity, u8 _blink,
+ u8 _underline, u8 _reverse, u8 _italic)
{
if (sw->con_build_attr)
- return sw->con_build_attr(vc, _color, _intensity, _blink, _underline, _reverse);
+ return sw->con_build_attr(vc, _color, _intensity, _blink,
+ _underline, _reverse, _italic);
#ifndef VT_BUF_VRAM_ONLY
{
u8 a = vc->vc_color;
if (!vc->vc_can_do_color)
return _intensity |
- (_underline ? 4 : 0) |
- (_reverse ? 8 : 0) |
- (_blink ? 0x80 : 0);
- if (_underline)
+ (_italic ? 2 : 0) |
+ (_underline ? 4 : 0) |
+ (_reverse ? 8 : 0) |
+ (_blink ? 0x80 : 0);
+ if (_italic)
+ a = (a & 0xF0) | vc->vc_itcolor;
+ else if (_underline)
a = (a & 0xf0) | vc->vc_ulcolor;
else if (_intensity == 0)
a = (a & 0xf0) | vc->vc_halfcolor;
@@ -417,8 +429,9 @@
void update_attr(struct vc_data *vc)
{
vc->vc_attr = build_attr(vc, vc->vc_color, vc->vc_intensity, vc->vc_blink,
- vc->vc_underline, vc->vc_reverse ^ vc->vc_decscnm);
- vc->vc_video_erase_char = (build_attr(vc, vc->vc_color, vc->vc_intensity, 0, 0, vc->vc_decscnm) << 8) | ' ';
+ vc->vc_underline, vc->vc_reverse ^ vc->vc_decscnm,
+ vc->vc_italic);
+ vc->vc_video_erase_char = (build_attr(vc, vc->vc_color, 1, vc->vc_blink, 0, vc->vc_decscnm, 0) << 8) | ' ';
}
static void clear_buffer_attributes(struct vc_data *vc)
@@ -952,14 +965,20 @@
vc->vc_screenbuf_size = vc->vc_rows * vc->vc_size_row;
}
+static int default_italic_color = 2; // green (ASCII)
+static int default_underline_color = 3; // cyan (ASCII)
+module_param_named(italic, default_italic_color, int, S_IRUGO | S_IWUSR);
+module_param_named(underline, default_underline_color, int, S_IRUGO | S_IWUSR);
+
static void vc_init(struct vc_data *vc, int do_clear)
{
set_origin(vc);
vc->vc_pos = vc->vc_origin;
reset_vc(vc);
- vc->vc_def_color = 0x07; /* white */
- vc->vc_ulcolor = 0x0f; /* bold white */
- vc->vc_halfcolor = 0x08; /* grey */
+ vc->vc_def_color = 0x07; /* white */
+ vc->vc_ulcolor = default_underline_color;
+ vc->vc_itcolor = default_italic_color;
+ vc->vc_halfcolor = 0x08; /* grey */
init_waitqueue_head(&vc->paste_wait);
vte_ris(vc, do_clear);
}
@@ -1258,10 +1277,12 @@
}
#endif
unsigned long draw_from = 0, draw_to = 0;
- struct vc_data *vc = tty->driver_data;
const unsigned char *orig_buf = NULL;
int c, tc, ok, n = 0, draw_x = -1;
+ uint8_t rescan, inverse, width;
+ unsigned char vc_attr;
u16 himask, charmask;
+ struct vc_data *vc;
int orig_count;
if (in_interrupt())
@@ -1271,6 +1292,7 @@
acquire_console_sem();
+ vc = tty->driver_data;
if (!vc) {
printk("vt_write: tty %d not allocated\n", tty->index);
release_console_sem();
@@ -1304,26 +1326,51 @@
buf++;
n++;
count--;
+ rescan = 0;
+ inverse = 0;
+ width = 1;
/* Do no translation at all in control states */
if (!vc->vc_state) {
tc = c;
} else if (vc->vc_utf && !vc->vc_disp_ctrl) {
- /* Combine UTF-8 into Unicode */
- /* Malformed sequences as sequences of replacement glyphs */
+ /* Combine UTF-8 into Unicode in vc_utf_char.
+ * vc_utf_count is the number of continuation bytes still
+ * expected to arrive.
+ * vc_npar is the number of continuation bytes arrived so
+ * far
+ */
rescan_last_byte:
- if(c > 0x7f) {
- if (vc->vc_utf_count > 0) {
- if ((c & 0xc0) == 0x80) {
- vc->vc_utf_char = (vc->vc_utf_char << 6) | (c & 0x3f);
- if (--vc->vc_utf_count) {
- vc->vc_npar++;
- continue;
- }
- tc = c = vc->vc_utf_char;
- } else
- goto replacement_glyph;
- } else {
+ if ((c & 0xc0) == 0x80) {
+ /* Continuation byte received */
+ static const uint32_t utf8_length_changes[] = { 0x0000007f, 0x000007ff, 0x0000ffff, 0x001fffff, 0x03ffffff, 0x7fffffff };
+ if (vc->vc_utf_count) {
+ vc->vc_utf_char = (vc->vc_utf_char << 6) | (c & 0x3f);
+ vc->vc_npar++;
+ if (--vc->vc_utf_count) {
+ /* Still need some bytes */
+ continue;
+ }
+ /* Got a whole character */
+ c = vc->vc_utf_char;
+ /* Reject overlong sequences */
+ if (c <= utf8_length_changes[vc->vc_npar - 1] ||
+ c > utf8_length_changes[vc->vc_npar])
+ c = 0xfffd;
+ } else
+ /* Unexpected continuation byte */
+ vc->vc_utf_count = 0;
+ c = 0xfffd;
+ }
+ } else {
+ /* Single ASCII byte or first byte of a sequence received */
+ if (vc->vc_utf_count) {
+ /* Continuation byte expected */
+ rescan = 1;
+ vc->vc_utf_count = 0;
+ c = 0xfffd;
+ } else if (c > 0x7f) {
+ /* First byte of a multibyte sequence received */
vc->vc_npar = 0;
if ((c & 0xe0) == 0xc0) {
vc->vc_utf_count = 1;
@@ -1340,17 +1387,25 @@
} else if ((c & 0xfe) == 0xfc) {
vc->vc_utf_count = 5;
vc->vc_utf_char = (c & 0x01);
- } else
- goto replacement_glyph;
- continue;
- }
- } else {
- if (vc->vc_utf_count)
- goto replacement_glyph;
- tc = c;
+ } else {
+ /* 254 and 255 are invalid */
+ c = 0xfffd;
+ }
+ if (vc->vc_utf_count) {
+ /* Still need some bytes */
+ continue;
+ }
+ }
+ /* Nothing to do if an ASCII byte was received */
}
+ /* End of UTF-8 decoding. */
+ /* c is the received character, or U+FFFD for invalid sequences. */
+ /* Replace invalid Unicode code points with U+FFFD too */
+ if ((c >= 0xd800 && c <= 0xdfff) || c == 0xfffe || c == 0xffff)
+ c = 0xfffd;
+ tc = c;
} else { /* no utf or alternate charset mode */
- tc = vc->vc_translate[vc->vc_toggle_meta ? (c | 0x80) : c];
+ tc = vc->vc_translate[vc->vc_toggle_meta ? (c | 0x80) : c];
}
/* If the original code was a control character we
@@ -1370,54 +1425,87 @@
&& (c != 128+27);
if (!vc->vc_state && ok) {
+ if (vc->vc_utf && !vc->vc_disp_ctrl) {
+ if (is_double_width(c))
+ width = 2;
+ }
/* Now try to find out how to display it */
tc = conv_uni_to_pc(vc, tc);
if (tc & ~charmask) {
- if ( tc == -4 ) {
- /* If we got -4 (not found) then see if we have
- defined a replacement character (U+FFFD) */
-replacement_glyph:
- tc = conv_uni_to_pc(vc, 0xfffd);
- if (!(tc & ~charmask))
- goto display_glyph;
- } else if ( tc != -3 )
+ if (tc == -1 || tc == -2) {
continue; /* nothing to display */
- /* no hash table or no replacement --
- * hope for the best */
- if ( c & ~charmask )
- tc = '?';
- else
+ }
+ /* Glyph not found */
+ if ((!(vc->vc_utf && !vc->vc_disp_ctrl) || c < 128) && !(c & ~charmask)) {
+ /* In legacy mode use the glyph we get by a 1:1 mapping.
+ This would make absolutely no sense with Unicode in mind,
+ but do this for ASCII characters since a font may lack
+ Unicode mapping info and we don't want to end up with
+ having question marks only. */
tc = c;
+ } else {
+ /* Display U+FFFD. If it's not found, display an inverse question mark. */
+ tc = conv_uni_to_pc(vc, 0xfffd);
+ if (tc < 0) {
+ inverse = 1;
+ tc = conv_uni_to_pc(vc, '?');
+ if (tc < 0) tc = '?';
+ }
+ }
}
-display_glyph:
- if (vc->vc_need_wrap || vc->vc_irm)
+ if (!inverse) {
+ vc_attr = vc->vc_attr;
+ } else {
+ /* invert vc_attr */
+ if (!vc->vc_can_do_color) {
+ vc_attr = (vc->vc_attr) ^ 0x08;
+ } else if (vc->vc_hi_font_mask == 0x100) {
+ vc_attr = ((vc->vc_attr) & 0x11) | (((vc->vc_attr) & 0xe0) >> 4) | (((vc->vc_attr) & 0x0e) << 4);
+ } else {
+ vc_attr = ((vc->vc_attr) & 0x88) | (((vc->vc_attr) & 0x70) >> 4) | (((vc->vc_attr) & 0x07) << 4);
+ }
FLUSH
- if (vc->vc_need_wrap) {
- vte_cr(vc);
- vte_lf(vc);
}
- if (vc->vc_irm)
- insert_char(vc, 1);
- scr_writew(himask ?
- ((vc->vc_attr << 8) & ~himask) + ((tc & 0x100) ? himask : 0) + (tc & 0xff) : (vc->vc_attr << 8) + tc, (u16 *) vc->vc_pos);
- if (DO_UPDATE && draw_x < 0) {
- draw_x = vc->vc_x;
- draw_from = vc->vc_pos;
+
+ while (1) {
+ if (vc->vc_need_wrap || vc->vc_irm)
+ FLUSH
+ if (vc->vc_need_wrap) {
+ vte_cr(vc);
+ vte_lf(vc);
+ }
+ if (vc->vc_irm)
+ insert_char(vc, 1);
+ scr_writew(himask ?
+ ((vc_attr << 8) & ~himask) + ((tc & 0x100) ? himask : 0) + (tc & 0xff) :
+ (vc->vc_attr << 8) + tc, (u16 *) vc->vc_pos);
+ if (DO_UPDATE && draw_x < 0) {
+ draw_x = vc->vc_x;
+ draw_from = vc->vc_pos;
+ }
+ if (vc->vc_x == vc->vc_cols - 1) {
+ vc->vc_need_wrap = vc->vc_decawm;
+ draw_to = vc->vc_pos + 2;
+ } else {
+ vc->vc_x++;
+ draw_to = (vc->vc_pos += 2);
+ }
+
+ if (!--width) break;
+
+ tc = conv_uni_to_pc(vc, ' '); /* A space is printed in the second column */
+ if (tc < 0) tc = ' ';
}
- if (vc->vc_x == vc->vc_cols - 1) {
- vc->vc_need_wrap = vc->vc_decawm;
- draw_to = vc->vc_pos + 2;
- } else {
- vc->vc_x++;
- draw_to = (vc->vc_pos += 2);
+
+ if (inverse) {
+ FLUSH
}
- if (vc->vc_utf_count) {
- if (vc->vc_npar) {
- vc->vc_npar--;
- goto display_glyph;
- }
- vc->vc_utf_count = 0;
+
+ if (rescan) {
+ rescan = 0;
+ inverse = 0;
+ width = 1;
c = orig;
goto rescan_last_byte;
}
@@ -1429,6 +1517,7 @@
FLUSH
console_conditional_schedule();
release_console_sem();
+out:
return n;
#undef FLUSH
}
Modified: branches/ruby-2.6.21/ruby-2.6/drivers/char/vt_ioctl.c
===================================================================
--- branches/ruby-2.6.21/ruby-2.6/drivers/char/vt_ioctl.c 2007-07-16 15:52:23 UTC (rev 2382)
+++ branches/ruby-2.6.21/ruby-2.6/drivers/char/vt_ioctl.c 2007-07-16 18:14:58 UTC (rev 2383)
@@ -103,7 +103,7 @@
schedule();
}
remove_wait_queue(&vt_activate_queue, &wait);
- set_current_state(TASK_RUNNING);
+ __set_current_state(TASK_RUNNING);
return retval;
}
Modified: branches/ruby-2.6.21/ruby-2.6/drivers/video/console/vgacon.c
===================================================================
--- branches/ruby-2.6.21/ruby-2.6/drivers/video/console/vgacon.c 2007-07-16 15:52:23 UTC (rev 2382)
+++ branches/ruby-2.6.21/ruby-2.6/drivers/video/console/vgacon.c 2007-07-16 18:14:58 UTC (rev 2383)
@@ -88,8 +88,6 @@
static void vgacon_save_screen(struct vc_data *c);
static int vgacon_scroll_region(struct vc_data *c, int t, int b, int dir,
int lines);
-static u8 vgacon_build_attr(struct vc_data *c, u8 color, u8 intensity,
- u8 blink, u8 underline, u8 reverse);
static void vgacon_invert_region(struct vc_data *c, u16 * p, int count);
static unsigned long vgacon_uni_pagedir[2];
@@ -368,6 +366,12 @@
return NULL;
}
+ /* SCREEN_INFO initialized? */
+ if ((ORIG_VIDEO_MODE == 0) &&
+ (ORIG_VIDEO_LINES == 0) &&
+ (ORIG_VIDEO_COLS == 0))
+ goto no_vga;
+
/* VGA16 modes are not handled by VGACON */
if ((ORIG_VIDEO_MODE == 0x0D) || /* 320x200/4 */
(ORIG_VIDEO_MODE == 0x0E) || /* 640x200/4 */
@@ -577,12 +581,14 @@
}
static u8 vgacon_build_attr(struct vc_data *c, u8 color, u8 intensity,
- u8 blink, u8 underline, u8 reverse)
+ u8 blink, u8 underline, u8 reverse, u8 italic)
{
u8 attr = color;
if (vga_can_do_color) {
- if (underline)
+ if (italic)
+ attr = (attr & 0xF0) | c->vc_itcolor;
+ else if (underline)
attr = (attr & 0xf0) | c->vc_ulcolor;
else if (intensity == 0)
attr = (attr & 0xf0) | c->vc_halfcolor;
@@ -596,7 +602,9 @@
if (intensity == 2)
attr ^= 0x08;
if (!vga_can_do_color) {
- if (underline)
+ if (italic)
+ sttr = (attr & 0xF8) | 0x02;
+ else if (underline)
attr = (attr & 0xf8) | 0x01;
else if (intensity == 0)
attr = (attr & 0xf0) | 0x08;
@@ -657,6 +665,9 @@
static void vgacon_cursor(struct vc_data *c, int mode)
{
+ if (c->vc_mode != KD_TEXT)
+ return;
+
vgacon_restore_screen(c);
switch (mode) {
@@ -1315,7 +1326,7 @@
unsigned long oldo;
unsigned int delta;
- if (t || b != c->vc_rows || vga_is_gfx)
+ if (t || b != c->vc_rows || vga_is_gfx || c->vc_mode != KD_TEXT)
return 0;
if (!vga_hardscroll_enabled || lines >= c->vc_rows / 2)
Modified: branches/ruby-2.6.21/ruby-2.6/fs/compat_ioctl.c
===================================================================
--- branches/ruby-2.6.21/ruby-2.6/fs/compat_ioctl.c 2007-07-16 15:52:23 UTC (rev 2382)
+++ branches/ruby-2.6.21/ruby-2.6/fs/compat_ioctl.c 2007-07-16 18:14:58 UTC (rev 2383)
@@ -17,7 +17,6 @@
#include <linux/compiler.h>
#include <linux/sched.h>
#include <linux/smp.h>
-#include <linux/smp_lock.h>
#include <linux/ioctl.h>
#include <linux/if.h>
#include <linux/if_bridge.h>
@@ -58,7 +57,6 @@
#include <linux/serial.h>
#include <linux/if_tun.h>
#include <linux/ctype.h>
-#include <linux/ioctl32.h>
#include <linux/syscalls.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
@@ -66,7 +64,6 @@
#include <linux/atalk.h>
#include <linux/blktrace_api.h>
-#include <net/sock.h> /* siocdevprivate_ioctl */
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci.h>
#include <net/bluetooth/rfcomm.h>
@@ -266,6 +263,23 @@
return err;
}
+static int do_siocgstampns(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+ struct compat_timespec __user *up = compat_ptr(arg);
+ struct timespec kts;
+ mm_segment_t old_fs = get_fs();
+ int err;
+
+ set_fs(KERNEL_DS);
+ err = sys_ioctl(fd, cmd, (unsigned long)&kts);
+ set_fs(old_fs);
+ if (!err) {
+ err = put_user(kts.tv_sec, &up->tv_sec);
+ err |= __put_user(kts.tv_nsec, &up->tv_nsec);
+ }
+ return err;
+}
+
struct ifmap32 {
compat_ulong_t mem_start;
compat_ulong_t mem_end;
@@ -458,7 +472,7 @@
};
}
-int siocdevprivate_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
+static int siocdevprivate_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
{
struct ifreq __user *u_ifreq64;
struct ifreq32 __user *u_ifreq32 = compat_ptr(arg);
@@ -670,8 +684,10 @@
if (!err) {
err = copy_to_user (ugeo, &geo, 4);
err |= __put_user (geo.start, &ugeo->start);
+ if (err)
+ err = -EFAULT;
}
- return err ? -EFAULT : 0;
+ return err;
}
static int hdio_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
@@ -1178,6 +1194,7 @@
{
struct tty_struct *tty;
struct inode *inode = file->f_path.dentry->d_inode;
+ struct vc_data *vc;
if (file->f_op->ioctl != tty_ioctl)
return -EINVAL;
@@ -1188,12 +1205,16 @@
if (tty->driver->ioctl != vt_ioctl)
return -EINVAL;
-
+
+ vc = (struct vc_data *)tty->driver_data;
+ if (!vc) /* impossible? */
+ return -ENOIOCTLCMD;
+
/*
* To have permissions to do most of the vt ioctls, we either have
- * to be the owner of the tty, or super-user.
+ * to be the owner of the tty, or have CAP_SYS_TTY_CONFIG.
*/
- if (current->signal->tty == tty || capable(CAP_SYS_ADMIN))
+ if (current->signal->tty == tty || capable(CAP_SYS_TTY_CONFIG))
return 1;
return 0;
}
@@ -1206,7 +1227,7 @@
static int do_fontx_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file)
{
- struct tty_struct *tty = (struct tty_struct *) file->private_data;
+ struct tty_struct *tty = (struct tty_struct *) file->private_data;
struct consolefontdesc32 __user *user_cfd = compat_ptr(arg);
struct vc_data *vc = (struct vc_data *) tty->driver_data;
struct console_font_op op;
@@ -1215,7 +1236,10 @@
perm = vt_check(file);
if (perm < 0) return perm;
-
+
+ if (!IS_VISIBLE)
+ return -EPERM;
+
switch (cmd) {
case PIO_FONTX:
if (!perm)
@@ -1293,21 +1317,31 @@
static int do_unimap_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file)
{
- struct tty_struct *tty = (struct tty_struct *) file->private_data;
- struct vc_data *vc = (struct vc_data *) tty->driver_data;
+ struct unimapdesc32 tmp;
struct unimapdesc32 __user *user_ud = compat_ptr(arg);
int perm = vt_check(file);
- struct unimapdesc32 tmp;
+ struct vc_data *vc;
- if (perm < 0) return perm;
+ if (perm < 0)
+ return perm;
if (copy_from_user(&tmp, user_ud, sizeof tmp))
return -EFAULT;
+ if (tmp.entries)
+ if (!access_ok(VERIFY_WRITE, compat_ptr(tmp.entries),
+ tmp.entry_ct*sizeof(struct unipair)))
+ return -EFAULT;
+ vc = ((struct tty_struct *)file->private_data)->driver_data;
switch (cmd) {
case PIO_UNIMAP:
- if (!perm) return -EPERM;
- return con_set_unimap(vc, tmp.entry_ct, compat_ptr(tmp.entries));
+ if (!perm)
+ return -EPERM;
+ return con_set_unimap(vc, tmp.entry_ct,
+ compat_ptr(tmp.entries));
case GIO_UNIMAP:
- return con_get_unimap(vc, tmp.entry_ct, &(user_ud->entry_ct), compat_ptr(tmp.entries));
+ if (!perm && IS_VISIBLE)
+ return -EPERM;
+ return con_get_unimap(vc, tmp.entry_ct, &(user_ud->entry_ct),
+ compat_ptr(tmp.entries));
}
return 0;
}
@@ -2372,6 +2406,16 @@
return sys_ioctl(fd, cmd, (unsigned long)tn);
}
+
+typedef int (*ioctl_trans_handler_t)(unsigned int, unsigned int,
+ unsigned long, struct file *);
+
+struct ioctl_trans {
+ unsigned long cmd;
+ ioctl_trans_handler_t handler;
+ struct ioctl_trans *next;
+};
+
#define HANDLE_IOCTL(cmd,handler) \
{ (cmd), (ioctl_trans_handler_t)(handler) },
@@ -2383,9 +2427,844 @@
#define ULONG_IOCTL(cmd) \
{ (cmd), (ioctl_trans_handler_t)sys_ioctl },
+/* ioctl should not be warned about even if it's not implemented.
+ Valid reasons to use this:
+ - It is implemented with ->compat_ioctl on some device, but programs
+ call it on others too.
+ - The ioctl is not implemented in the native kernel, but programs
+ call it commonly anyways.
+ Most other reasons are not valid. */
+#define IGNORE_IOCTL(cmd) COMPATIBLE_IOCTL(cmd)
-struct ioctl_trans ioctl_start[] = {
-#include <linux/compat_ioctl.h>
+static struct ioctl_trans ioctl_start[] = {
+/* compatible ioctls first */
+COMPATIBLE_IOCTL(0x4B50) /* KDGHWCLK - not in the kernel, but don't complain */
+COMPATIBLE_IOCTL(0x4B51) /* KDSHWCLK - not in the kernel, but don't complain */
+
+/* Big T */
+COMPATIBLE_IOCTL(TCGETA)
+COMPATIBLE_IOCTL(TCSETA)
+COMPATIBLE_IOCTL(TCSETAW)
+COMPATIBLE_IOCTL(TCSETAF)
+COMPATIBLE_IOCTL(TCSBRK)
+ULONG_IOCTL(TCSBRKP)
+COMPATIBLE_IOCTL(TCXONC)
+COMPATIBLE_IOCTL(TCFLSH)
+COMPATIBLE_IOCTL(TCGETS)
+COMPATIBLE_IOCTL(TCSETS)
+COMPATIBLE_IOCTL(TCSETSW)
+COMPATIBLE_IOCTL(TCSETSF)
+COMPATIBLE_IOCTL(TIOCLINUX)
+COMPATIBLE_IOCTL(TIOCSBRK)
+COMPATIBLE_IOCTL(TIOCCBRK)
+ULONG_IOCTL(TIOCMIWAIT)
+COMPATIBLE_IOCTL(TIOCGICOUNT)
+/* Little t */
+COMPATIBLE_IOCTL(TIOCGETD)
+COMPATIBLE_IOCTL(TIOCSETD)
+COMPATIBLE_IOCTL(TIOCEXCL)
+COMPATIBLE_IOCTL(TIOCNXCL)
+COMPATIBLE_IOCTL(TIOCCONS)
+COMPATIBLE_IOCTL(TIOCGSOFTCAR)
+COMPATIBLE_IOCTL(TIOCSSOFTCAR)
+COMPATIBLE_IOCTL(TIOCSWINSZ)
+COMPATIBLE_IOCTL(TIOCGWINSZ)
+COMPATIBLE_IOCTL(TIOCMGET)
+COMPATIBLE_IOCTL(TIOCMBIC)
+COMPATIBLE_IOCTL(TIOCMBIS)
+COMPATIBLE_IOCTL(TIOCMSET)
+COMPATIBLE_IOCTL(TIOCPKT)
+COMPATIBLE_IOCTL(TIOCNOTTY)
+COMPATIBLE_IOCTL(TIOCSTI)
+COMPATIBLE_IOCTL(TIOCOUTQ)
+COMPATIBLE_IOCTL(TIOCSPGRP)
+COMPATIBLE_IOCTL(TIOCGPGRP)
+ULONG_IOCTL(TIOCSCTTY)
+COMPATIBLE_IOCTL(TIOCGPTN)
+COMPATIBLE_IOCTL(TIOCSPTLCK)
+COMPATIBLE_IOCTL(TIOCSERGETLSR)
+/* Little f */
+COMPATIBLE_IOCTL(FIOCLEX)
+COMPATIBLE_IOCTL(FIONCLEX)
+COMPATIBLE_IOCTL(FIOASYNC)
+COMPATIBLE_IOCTL(FIONBIO)
+COMPATIBLE_IOCTL(FIONREAD) /* This is also TIOCINQ */
+/* 0x00 */
+COMPATIBLE_IOCTL(FIBMAP)
+COMPATIBLE_IOCTL(FIGETBSZ)
+/* 0x03 -- HD/IDE ioctl's used by hdparm and friends.
+ * Some need translations, these do not.
+ */
+COMPATIBLE_IOCTL(HDIO_GET_IDENTITY)
+COMPATIBLE_IOCTL(HDIO_DRIVE_TASK)
+COMPATIBLE_IOCTL(HDIO_DRIVE_CMD)
+ULONG_IOCTL(HDIO_SET_MULTCOUNT)
+ULONG_IOCTL(HDIO_SET_UNMASKINTR)
+ULONG_IOCTL(HDIO_SET_KEEPSETTINGS)
+ULONG_IOCTL(HDIO_SET_32BIT)
+ULONG_IOCTL(HDIO_SET_NOWERR)
+ULONG_IOCTL(HDIO_SET_DMA)
+ULONG_IOCTL(HDIO_SET_PIO_MODE)
+ULONG_IOCTL(HDIO_SET_NICE)
+ULONG_IOCTL(HDIO_SET_WCACHE)
+ULONG_IOCTL(HDIO_SET_ACOUSTIC)
+ULONG_IOCTL(HDIO_SET_BUSSTATE)
+ULONG_IOCTL(HDIO_SET_ADDRESS)
+COMPATIBLE_IOCTL(HDIO_SCAN_HWIF)
+/* 0x330 is reserved -- it used to be HDIO_GETGEO_BIG */
+COMPATIBLE_IOCTL(0x330)
+/* 0x02 -- Floppy ioctls */
+COMPATIBLE_IOCTL(FDMSGON)
+COMPATIBLE_IOCTL(FDMSGOFF)
+COMPATIBLE_IOCTL(FDSETEMSGTRESH)
+COMPATIBLE_IOCTL(FDFLUSH)
+COMPATIBLE_IOCTL(FDWERRORCLR)
+COMPATIBLE_IOCTL(FDSETMAXERRS)
+COMPATIBLE_IOCTL(FDGETMAXERRS)
+COMPATIBLE_IOCTL(FDGETDRVTYP)
+COMPATIBLE_IOCTL(FDEJECT)
+COMPATIBLE_IOCTL(FDCLRPRM)
+COMPATIBLE_IOCTL(FDFMTBEG)
+COMPATIBLE_IOCTL(FDFMTEND)
+COMPATIBLE_IOCTL(FDRESET)
+COMPATIBLE_IOCTL(FDTWADDLE)
+COMPATIBLE_IOCTL(FDFMTTRK)
+COMPATIBLE_IOCTL(FDRAWCMD)
+/* 0x12 */
+#ifdef CONFIG_BLOCK
+COMPATIBLE_IOCTL(BLKRASET)
+COMPATIBLE_IOCTL(BLKROSET)
+COMPATIBLE_IOCTL(BLKROGET)
+COMPATIBLE_IOCTL(BLKRRPART)
+COMPATIBLE_IOCTL(BLKFLSBUF)
+COMPATIBLE_IOCTL(BLKSECTSET)
+COMPATIBLE_IOCTL(BLKSSZGET)
+COMPATIBLE_IOCTL(BLKTRACESTART)
+COMPATIBLE_IOCTL(BLKTRACESTOP)
+COMPATIBLE_IOCTL(BLKTRACESETUP)
+COMPATIBLE_IOCTL(BLKTRACETEARDOWN)
+ULONG_IOCTL(BLKRASET)
+ULONG_IOCTL(BLKFRASET)
+#endif
+/* RAID */
+COMPATIBLE_IOCTL(RAID_VERSION)
+COMPATIBLE_IOCTL(GET_ARRAY_INFO)
+COMPATIBLE_IOCTL(GET_DISK_INFO)
+COMPATIBLE_IOCTL(PRINT_RAID_DEBUG)
+COMPATIBLE_IOCTL(RAID_AUTORUN)
+COMPATIBLE_IOCTL(CLEAR_ARRAY)
+COMPATIBLE_IOCTL(ADD_NEW_DISK)
+ULONG_IOCTL(HOT_REMOVE_DISK)
+COMPATIBLE_IOCTL(SET_ARRAY_INFO)
+COMPATIBLE_IOCTL(SET_DISK_INFO)
+COMPATIBLE_IOCTL(WRITE_RAID_INFO)
+COMPATIBLE_IOCTL(UNPROTECT_ARRAY)
+COMPATIBLE_IOCTL(PROTECT_ARRAY)
+ULONG_IOCTL(HOT_ADD_DISK)
+ULONG_IOCTL(SET_DISK_FAULTY)
+COMPATIBLE_IOCTL(RUN_ARRAY)
+COMPATIBLE_IOCTL(STOP_ARRAY)
+COMPATIBLE_IOCTL(STOP_ARRAY_RO)
+COMPATIBLE_IOCTL(RESTART_ARRAY_RW)
+COMPATIBLE_IOCTL(GET_BITMAP_FILE)
+ULONG_IOCTL(SET_BITMAP_FILE)
+/* DM */
+COMPATIBLE_IOCTL(DM_VERSION_32)
+COMPATIBLE_IOCTL(DM_REMOVE_ALL_32)
+COMPATIBLE_IOCTL(DM_LIST_DEVICES_32)
+COMPATIBLE_IOCTL(DM_DEV_CREATE_32)
+COMPATIBLE_IOCTL(DM_DEV_REMOVE_32)
+COMPATIBLE_IOCTL(DM_DEV_RENAME_32)
+COMPATIBLE_IOCTL(DM_DEV_SUSPEND_32)
+COMPATIBLE_IOCTL(DM_DEV_STATUS_32)
+COMPATIBLE_IOCTL(DM_DEV_WAIT_32)
+COMPATIBLE_IOCTL(DM_TABLE_LOAD_32)
+COMPATIBLE_IOCTL(DM_TABLE_CLEAR_32)
+COMPATIBLE_IOCTL(DM_TABLE_DEPS_32)
+COMPATIBLE_IOCTL(DM_TABLE_STATUS_32)
+COMPATIBLE_IOCTL(DM_LIST_VERSIONS_32)
+COMPATIBLE_IOCTL(DM_TARGET_MSG_32)
+COMPATIBLE_IOCTL(DM_DEV_SET_GEOMETRY_32)
+COMPATIBLE_IOCTL(DM_VERSION)
+COMPATIBLE_IOCTL(DM_REMOVE_ALL)
+COMPATIBLE_IOCTL(DM_LIST_DEVICES)
+COMPATIBLE_IOCTL(DM_DEV_CREATE)
+COMPATIBLE_IOCTL(DM_DEV_REMOVE)
+COMPATIBLE_IOCTL(DM_DEV_RENAME)
+COMPATIBLE_IOCTL(DM_DEV_SUSPEND)
+COMPATIBLE_IOCTL(DM_DEV_STATUS)
+COMPATIBLE_IOCTL(DM_DEV_WAIT)
+COMPATIBLE_IOCTL(DM_TABLE_LOAD)
+COMPATIBLE_IOCTL(DM_TABLE_CLEAR)
+COMPATIBLE_IOCTL(DM_TABLE_DEPS)
+COMPATIBLE_IOCTL(DM_TABLE_STATUS)
+COMPATIBLE_IOCTL(DM_LIST_VERSIONS)
+COMPATIBLE_IOCTL(DM_TARGET_MSG)
+COMPATIBLE_IOCTL(DM_DEV_SET_GEOMETRY)
+/* Big K */
+COMPATIBLE_IOCTL(PIO_FONT)
+COMPATIBLE_IOCTL(GIO_FONT)
+ULONG_IOCTL(KDSIGACCEPT)
+COMPATIBLE_IOCTL(KDGETKEYCODE)
+COMPATIBLE_IOCTL(KDSETKEYCODE)
+ULONG_IOCTL(KIOCSOUND)
+ULONG_IOCTL(KDMKTONE)
+COMPATIBLE_IOCTL(KDGKBTYPE)
+ULONG_IOCTL(KDSETMODE)
+COMPATIBLE_IOCTL(KDGETMODE)
+ULONG_IOCTL(KDSKBMODE)
+COMPATIBLE_IOCTL(KDGKBMODE)
+ULONG_IOCTL(KDSKBMETA)
+COMPATIBLE_IOCTL(KDGKBMETA)
+COMPATIBLE_IOCTL(KDGKBENT)
+COMPATIBLE_IOCTL(KDSKBENT)
+COMPATIBLE_IOCTL(KDGKBSENT)
+COMPATIBLE_IOCTL(KDSKBSENT)
+COMPATIBLE_IOCTL(KDGKBDIACR)
+COMPATIBLE_IOCTL(KDSKBDIACR)
+COMPATIBLE_IOCTL(KDKBDREP)
+COMPATIBLE_IOCTL(KDGKBLED)
+ULONG_IOCTL(KDSKBLED)
+COMPATIBLE_IOCTL(KDGETLED)
+ULONG_IOCTL(KDSETLED)
+COMPATIBLE_IOCTL(GIO_SCRNMAP)
+COMPATIBLE_IOCTL(PIO_SCRNMAP)
+COMPATIBLE_IOCTL(GIO_UNISCRNMAP)
+COMPATIBLE_IOCTL(PIO_UNISCRNMAP)
+COMPATIBLE_IOCTL(PIO_FONTRESET)
+COMPATIBLE_IOCTL(PIO_UNIMAPCLR)
+/* Big S */
+COMPATIBLE_IOCTL(SCSI_IOCTL_GET_IDLUN)
+COMPATIBLE_IOCTL(SCSI_IOCTL_DOORLOCK)
+COMPATIBLE_IOCTL(SCSI_IOCTL_DOORUNLOCK)
+COMPATIBLE_IOCTL(SCSI_IOCTL_TEST_UNIT_READY)
+COMPATIBLE_IOCTL(SCSI_IOCTL_GET_BUS_NUMBER)
+COMPATIBLE_IOCTL(SCSI_IOCTL_SEND_COMMAND)
+COMPATIBLE_IOCTL(SCSI_IOCTL_PROBE_HOST)
+COMPATIBLE_IOCTL(SCSI_IOCTL_GET_PCI)
+/* Big T */
+COMPATIBLE_IOCTL(TUNSETNOCSUM)
+COMPATIBLE_IOCTL(TUNSETDEBUG)
+COMPATIBLE_IOCTL(TUNSETPERSIST)
+COMPATIBLE_IOCTL(TUNSETOWNER)
+/* Big V */
+COMPATIBLE_IOCTL(VT_SETMODE)
+COMPATIBLE_IOCTL(VT_GETMODE)
+COMPATIBLE_IOCTL(VT_GETSTATE)
+COMPATIBLE_IOCTL(VT_OPENQRY)
+ULONG_IOCTL(VT_ACTIVATE)
+ULONG_IOCTL(VT_WAITACTIVE)
+ULONG_IOCTL(VT_RELDISP)
+ULONG_IOCTL(VT_DISALLOCATE)
+COMPATIBLE_IOCTL(VT_RESIZE)
+COMPATIBLE_IOCTL(VT_RESIZEX)
+COMPATIBLE_IOCTL(VT_LOCKSWITCH)
+COMPATIBLE_IOCTL(VT_UNLOCKSWITCH)
+COMPATIBLE_IOCTL(VT_GETHIFONTMASK)
+/* Little p (/dev/rtc, /dev/envctrl, etc.) */
+COMPATIBLE_IOCTL(RTC_AIE_ON)
+COMPATIBLE_IOCTL(RTC_AIE_OFF)
+COMPATIBLE_IOCTL(RTC_UIE_ON)
+COMPATIBLE_IOCTL(RTC_UIE_OFF)
+COMPATIBLE_IOCTL(RTC_PIE_ON)
+COMPATIBLE_IOCTL(RTC_PIE_OFF)
+COMPATIBLE_IOCTL(RTC_WIE_ON)
+COMPATIBLE_IOCTL(RTC_WIE_OFF)
+COMPATIBLE_IOCTL(RTC_ALM_SET)
+COMPATIBLE_IOCTL(RTC_ALM_READ)
+COMPATIBLE_IOCTL(RTC_RD_TIME)
+COMPATIBLE_IOCTL(RTC_SET_TIME)
+COMPATIBLE_IOCTL(RTC_WKALM_SET)
+COMPATIBLE_IOCTL(RTC_WKALM_RD)
+/*
+ * These two are only for the sbus rtc driver, but
+ * hwclock tries them on every rtc device first when
+ * running on sparc. On other architectures the entries
+ * are useless but harmless.
+ */
+COMPATIBLE_IOCTL(_IOR('p', 20, int[7])) /* RTCGET */
+COMPATIBLE_IOCTL(_IOW('p', 21, int[7])) /* RTCSET */
+/* Little m */
+COMPATIBLE_IOCTL(MTIOCTOP)
+/* Socket level stuff */
+COMPATIBLE_IOCTL(FIOQSIZE)
+COMPATIBLE_IOCTL(FIOSETOWN)
+COMPATIBLE_IOCTL(SIOCSPGRP)
+COMPATIBLE_IOCTL(FIOGETOWN)
+COMPATIBLE_IOCTL(SIOCGPGRP)
+COMPATIBLE_IOCTL(SIOCATMARK)
+COMPATIBLE_IOCTL(SIOCSIFLINK)
+COMPATIBLE_IOCTL(SIOCSIFENCAP)
+COMPATIBLE_IOCTL(SIOCGIFENCAP)
+COMPATIBLE_IOCTL(SIOCSIFNAME)
+COMPATIBLE_IOCTL(SIOCSARP)
+COMPATIBLE_IOCTL(SIOCGARP)
+COMPATIBLE_IOCTL(SIOCDARP)
+COMPATIBLE_IOCTL(SIOCSRARP)
+COMPATIBLE_IOCTL(SIOCGRARP)
+COMPATIBLE_IOCTL(SIOCDRARP)
+COMPATIBLE_IOCTL(SIOCADDDLCI)
+COMPATIBLE_IOCTL(SIOCDELDLCI)
+COMPATIBLE_IOCTL(SIOCGMIIPHY)
+COMPATIBLE_IOCTL(SIOCGMIIREG)
+COMPATIBLE_IOCTL(SIOCSMIIREG)
+COMPATIBLE_IOCTL(SIOCGIFVLAN)
+COMPATIBLE_IOCTL(SIOCSIFVLAN)
+COMPATIBLE_IOCTL(SIOCBRADDBR)
+COMPATIBLE_IOCTL(SIOCBRDELBR)
+/* SG stuff */
+COMPATIBLE_IOCTL(SG_SET_TIMEOUT)
+COMPATIBLE_IOCTL(SG_GET_TIMEOUT)
+COMPATIBLE_IOCTL(SG_EMULATED_HOST)
+ULONG_IOCTL(SG_SET_TRANSFORM)
+COMPATIBLE_IOCTL(SG_GET_TRANSFORM)
+COMPATIBLE_IOCTL(SG_SET_RESERVED_SIZE)
+COMPATIBLE_IOCTL(SG_GET_RESERVED_SIZE)
+COMPATIBLE_IOCTL(SG_GET_SCSI_ID)
+COMPATIBLE_IOCTL(SG_SET_FORCE_LOW_DMA)
+COMPATIBLE_IOCTL(SG_GET_LOW_DMA)
+COMPATIBLE_IOCTL(SG_SET_FORCE_PACK_ID)
+COMPATIBLE_IOCTL(SG_GET_PACK_ID)
+COMPATIBLE_IOCTL(SG_GET_NUM_WAITING)
+COMPATIBLE_IOCTL(SG_SET_DEBUG)
+COMPATIBLE_IOCTL(SG_GET_SG_TABLESIZE)
+COMPATIBLE_IOCTL(SG_GET_COMMAND_Q)
+COMPATIBLE_IOCTL(SG_SET_COMMAND_Q)
+COMPATIBLE_IOCTL(SG_GET_VERSION_NUM)
+COMPATIBLE_IOCTL(SG_NEXT_CMD_LEN)
+COMPATIBLE_IOCTL(SG_SCSI_RESET)
+COMPATIBLE_IOCTL(SG_GET_REQUEST_TABLE)
+COMPATIBLE_IOCTL(SG_SET_KEEP_ORPHAN)
+COMPATIBLE_IOCTL(SG_GET_KEEP_ORPHAN)
+/* PPP stuff */
+COMPATIBLE_IOCTL(PPPIOCGFLAGS)
+COMPATIBLE_IOCTL(PPPIOCSFLAGS)
+COMPATIBLE_IOCTL(PPPIOCGASYNCMAP)
+COMPATIBLE_IOCTL(PPPIOCSASYNCMAP)
+COMPATIBLE_IOCTL(PPPIOCGUNIT)
+COMPATIBLE_IOCTL(PPPIOCGRASYNCMAP)
+COMPATIBLE_IOCTL(PPPIOCSRASYNCMAP)
+COMPATIBLE_IOCTL(PPPIOCGMRU)
+COMPATIBLE_IOCTL(PPPIOCSMRU)
+COMPATIBLE_IOCTL(PPPIOCSMAXCID)
+COMPATIBLE_IOCTL(PPPIOCGXASYNCMAP)
+COMPATIBLE_IOCTL(PPPIOCSXASYNCMAP)
+COMPATIBLE_IOCTL(PPPIOCXFERUNIT)
+/* PPPIOCSCOMPRESS is translated */
+COMPATIBLE_IOCTL(PPPIOCGNPMODE)
+COMPATIBLE_IOCTL(PPPIOCSNPMODE)
+COMPATIBLE_IOCTL(PPPIOCGDEBUG)
+COMPATIBLE_IOCTL(PPPIOCSDEBUG)
+/* PPPIOCSPASS is translated */
+/* PPPIOCSACTIVE is translated */
+/* PPPIOCGIDLE is translated */
+COMPATIBLE_IOCTL(PPPIOCNEWUNIT)
+COMPATIBLE_IOCTL(PPPIOCATTACH)
+COMPATIBLE_IOCTL(PPPIOCDETACH)
+COMPATIBLE_IOCTL(PPPIOCSMRRU)
+COMPATIBLE_IOCTL(PPPIOCCONNECT)
+COMPATIBLE_IOCTL(PPPIOCDISCONN)
+COMPATIBLE_IOCTL(PPPIOCATTCHAN)
+COMPATIBLE_IOCTL(PPPIOCGCHAN)
+/* PPPOX */
+COMPATIBLE_IOCTL(PPPOEIOCSFWD)
+COMPATIBLE_IOCTL(PPPOEIOCDFWD)
+/* LP */
+COMPATIBLE_IOCTL(LPGETSTATUS)
+/* ppdev */
+COMPATIBLE_IOCTL(PPSETMODE)
+COMPATIBLE_IOCTL(PPRSTATUS)
+COMPATIBLE_IOCTL(PPRCONTROL)
+COMPATIBLE_IOCTL(PPWCONTROL)
+COMPATIBLE_IOCTL(PPFCONTROL)
+COMPATIBLE_IOCTL(PPRDATA)
+COMPATIBLE_IOCTL(PPWDATA)
+COMPATIBLE_IOCTL(PPCLAIM)
+COMPATIBLE_IOCTL(PPRELEASE)
+COMPATIBLE_IOCTL(PPYIELD)
+COMPATIBLE_IOCTL(PPEXCL)
+COMPATIBLE_IOCTL(PPDATADIR)
+COMPATIBLE_IOCTL(PPNEGOT)
+COMPATIBLE_IOCTL(PPWCTLONIRQ)
+COMPATIBLE_IOCTL(PPCLRIRQ)
+COMPATIBLE_IOCTL(PPSETPHASE)
+COMPATIBLE_IOCTL(PPGETMODES)
+COMPATIBLE_IOCTL(PPGETMODE)
+COMPATIBLE_IOCTL(PPGETPHASE)
+COMPATIBLE_IOCTL(PPGETFLAGS)
+COMPATIBLE_IOCTL(PPSETFLAGS)
+/* CDROM stuff */
+COMPATIBLE_IOCTL(CDROMPAUSE)
+COMPATIBLE_IOCTL(CDROMRESUME)
+COMPATIBLE_IOCTL(CDROMPLAYMSF)
+COMPATIBLE_IOCTL(CDROMPLAYTRKIND)
+COMPATIBLE_IOCTL(CDROMREADTOCHDR)
+COMPATIBLE_IOCTL(CDROMREADTOCENTRY)
+COMPATIBLE_IOCTL(CDROMSTOP)
+COMPATIBLE_IOCTL(CDROMSTART)
+COMPATIBLE_IOCTL(CDROMEJECT)
+COMPATIBLE_IOCTL(CDROMVOLCTRL)
+COMPATIBLE_IOCTL(CDROMSUBCHNL)
+ULONG_IOCTL(CDROMEJECT_SW)
+COMPATIBLE_IOCTL(CDROMMULTISESSION)
+COMPATIBLE_IOCTL(CDROM_GET_MCN)
+COMPATIBLE_IOCTL(CDROMRESET)
+COMPATIBLE_IOCTL(CDROMVOLREAD)
+COMPATIBLE_IOCTL(CDROMSEEK)
+COMPATIBLE_IOCTL(CDROMPLAYBLK)
+COMPATIBLE_IOCTL(CDROMCLOSETRAY)
+ULONG_IOCTL(CDROM_SET_OPTIONS)
+ULONG_IOCTL(CDROM_CLEAR_OPTIONS)
+ULONG_IOCTL(CDROM_SELECT_SPEED)
+ULONG_IOCTL(CDROM_SELECT_DISC)
+ULONG_IOCTL(CDROM_MEDIA_CHANGED)
+ULONG_IOCTL(CDROM_DRIVE_STATUS)
+COMPATIBLE_IOCTL(CDROM_DISC_STATUS)
+COMPATIBLE_IOCTL(CDROM_CHANGER_NSLOTS)
+ULONG_IOCTL(CDROM_LOCKDOOR)
+ULONG_IOCTL(CDROM_DEBUG)
+COMPATIBLE_IOCTL(CDROM_GET_CAPABILITY)
+/* Ignore cdrom.h about these next 5 ioctls, they absolutely do
+ * not take a struct cdrom_read, instead they take a struct cdrom_msf
+ * which is compatible.
+ */
+COMPATIBLE_IOCTL(CDROMREADMODE2)
+COMPATIBLE_IOCTL(CDROMREADMODE1)
+COMPATIBLE_IOCTL(CDROMREADRAW)
+COMPATIBLE_IOCTL(CDROMREADCOOKED)
+COMPATIBLE_IOCTL(CDROMREADALL)
+/* DVD ioctls */
+COMPATIBLE_IOCTL(DVD_READ_STRUCT)
+COMPATIBLE_IOCTL(DVD_WRITE_STRUCT)
+COMPATIBLE_IOCTL(DVD_AUTH)
+/* pktcdvd */
+COMPATIBLE_IOCTL(PACKET_CTRL_CMD)
+/* Big A */
+/* sparc only */
+/* Big Q for sound/OSS */
+COMPATIBLE_IOCTL(SNDCTL_SEQ_RESET)
+COMPATIBLE_IOCTL(SNDCTL_SEQ_SYNC)
+COMPATIBLE_IOCTL(SNDCTL_SYNTH_INFO)
+COMPATIBLE_IOCTL(SNDCTL_SEQ_CTRLRATE)
+COMPATIBLE_IOCTL(SNDCTL_SEQ_GETOUTCOUNT)
+COMPATIBLE_IOCTL(SNDCTL_SEQ_GETINCOUNT)
+COMPATIBLE_IOCTL(SNDCTL_SEQ_PERCMODE)
+COMPATIBLE_IOCTL(SNDCTL_FM_LOAD_INSTR)
+COMPATIBLE_IOCTL(SNDCTL_SEQ_TESTMIDI)
+COMPATIBLE_IOCTL(SNDCTL_SEQ_RESETSAMPLES)
+COMPATIBLE_IOCTL(SNDCTL_SEQ_NRSYNTHS)
+COMPATIBLE_IOCTL(SNDCTL_SEQ_NRMIDIS)
+COMPATIBLE_IOCTL(SNDCTL_MIDI_INFO)
+COMPATIBLE_IOCTL(SNDCTL_SEQ_THRESHOLD)
+COMPATIBLE_IOCTL(SNDCTL_SYNTH_MEMAVL)
+COMPATIBLE_IOCTL(SNDCTL_FM_4OP_ENABLE)
+COMPATIBLE_IOCTL(SNDCTL_SEQ_PANIC)
+COMPATIBLE_IOCTL(SNDCTL_SEQ_OUTOFBAND)
+COMPATIBLE_IOCTL(SNDCTL_SEQ_GETTIME)
+COMPATIBLE_IOCTL(SNDCTL_SYNTH_ID)
+COMPATIBLE_IOCTL(SNDCTL_SYNTH_CONTROL)
+COMPATIBLE_IOCTL(SNDCTL_SYNTH_REMOVESAMPLE)
+/* Big T for sound/OSS */
+COMPATIBLE_IOCTL(SNDCTL_TMR_TIMEBASE)
+COMPATIBLE_IOCTL(SNDCTL_TMR_START)
+COMPATIBLE_IOCTL(SNDCTL_TMR_STOP)
+COMPATIBLE_IOCTL(SNDCTL_TMR_CONTINUE)
+COMPATIBLE_IOCTL(SNDCTL_TMR_TEMPO)
+COMPATIBLE_IOCTL(SNDCTL_TMR_SOURCE)
+COMPATIBLE_IOCTL(SNDCTL_TMR_METRONOME)
+COMPATIBLE_IOCTL(SNDCTL_TMR_SELECT)
+/* Little m for sound/OSS */
+COMPATIBLE_IOCTL(SNDCTL_MIDI_PRETIME)
+COMPATIBLE_IOCTL(SNDCTL_MIDI_MPUMODE)
+COMPATIBLE_IOCTL(SNDCTL_MIDI_MPUCMD)
+/* Big P for sound/OSS */
+COMPATIBLE_IOCTL(SNDCTL_DSP_RESET)
+COMPATIBLE_IOCTL(SNDCTL_DSP_SYNC)
+COMPATIBLE_IOCTL(SNDCTL_DSP_SPEED)
+COMPATIBLE_IOCTL(SNDCTL_DSP_STEREO)
+COMPATIBLE_IOCTL(SNDCTL_DSP_GETBLKSIZE)
+COMPATIBLE_IOCTL(SNDCTL_DSP_CHANNELS)
+COMPATIBLE_IOCTL(SOUND_PCM_WRITE_FILTER)
+COMPATIBLE_IOCTL(SNDCTL_DSP_POST)
+COMPATIBLE_IOCTL(SNDCTL_DSP_SUBDIVIDE)
+COMPATIBLE_IOCTL(SNDCTL_DSP_SETFRAGMENT)
+COMPATIBLE_IOCTL(SNDCTL_DSP_GETFMTS)
+COMPATIBLE_IOCTL(SNDCTL_DSP_SETFMT)
+COMPATIBLE_IOCTL(SNDCTL_DSP_GETOSPACE)
+COMPATIBLE_IOCTL(SNDCTL_DSP_GETISPACE)
+COMPATIBLE_IOCTL(SNDCTL_DSP_NONBLOCK)
+COMPATIBLE_IOCTL(SNDCTL_DSP_GETCAPS)
+COMPATIBLE_IOCTL(SNDCTL_DSP_GETTRIGGER)
+COMPATIBLE_IOCTL(SNDCTL_DSP_SETTRIGGER)
+COMPATIBLE_IOCTL(SNDCTL_DSP_GETIPTR)
+COMPATIBLE_IOCTL(SNDCTL_DSP_GETOPTR)
+/* SNDCTL_DSP_MAPINBUF, XXX needs translation */
+/* SNDCTL_DSP_MAPOUTBUF, XXX needs translation */
+COMPATIBLE_IOCTL(SNDCTL_DSP_SETSYNCRO)
+COMPATIBLE_IOCTL(SNDCTL_DSP_SETDUPLEX)
+COMPATIBLE_IOCTL(SNDCTL_DSP_GETODELAY)
+COMPATIBLE_IOCTL(SNDCTL_DSP_PROFILE)
+COMPATIBLE_IOCTL(SOUND_PCM_READ_RATE)
+COMPATIBLE_IOCTL(SOUND_PCM_READ_CHANNELS)
+COMPATIBLE_IOCTL(SOUND_PCM_READ_BITS)
+COMPATIBLE_IOCTL(SOUND_PCM_READ_FILTER)
+/* Big C for sound/OSS */
+COMPATIBLE_IOCTL(SNDCTL_COPR_RESET)
+COMPATIBLE_IOCTL(SNDCTL_COPR_LOAD)
+COMPATIBLE_IOCTL(SNDCTL_COPR_RDATA)
+COMPATIBLE_IOCTL(SNDCTL_COPR_RCODE)
+COMPATIBLE_IOCTL(SNDCTL_COPR_WDATA)
+COMPATIBLE_IOCTL(SNDCTL_COPR_WCODE)
+COMPATIBLE_IOCTL(SNDCTL_COPR_RUN)
+COMPATIBLE_IOCTL(SNDCTL_COPR_HALT)
+COMPATIBLE_IOCTL(SNDCTL_COPR_SENDMSG)
+COMPATIBLE_IOCTL(SNDCTL_COPR_RCVMSG)
+/* Big M for sound/OSS */
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_VOLUME)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_BASS)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_TREBLE)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_SYNTH)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_PCM)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_SPEAKER)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_LINE)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_MIC)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_CD)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_IMIX)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_ALTPCM)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_RECLEV)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_IGAIN)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_OGAIN)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_LINE1)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_LINE2)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_LINE3)
+COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_DIGITAL1))
+COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_DIGITAL2))
+COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_DIGITAL3))
+COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_PHONEIN))
+COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_PHONEOUT))
+COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_VIDEO))
+COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_RADIO))
+COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_MONITOR))
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_MUTE)
+/* SOUND_MIXER_READ_ENHANCE, same value as READ_MUTE */
+/* SOUND_MIXER_READ_LOUD, same value as READ_MUTE */
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_RECSRC)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_DEVMASK)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_RECMASK)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_STEREODEVS)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_CAPS)
+COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_VOLUME)
+COMPATIBLE_IOCT...
[truncated message content] |
|
From: <jsi...@us...> - 2007-07-16 15:52:27
|
Revision: 2382
http://linuxconsole.svn.sourceforge.net/linuxconsole/?rev=2382&view=rev
Author: jsimmons
Date: 2007-07-16 08:52:23 -0700 (Mon, 16 Jul 2007)
Log Message:
-----------
Some changes to vga con causes a lock up. Will find later
Modified Paths:
--------------
branches/ruby-2.6.21/ruby-2.6/drivers/video/console/vgacon.c
Modified: branches/ruby-2.6.21/ruby-2.6/drivers/video/console/vgacon.c
===================================================================
--- branches/ruby-2.6.21/ruby-2.6/drivers/video/console/vgacon.c 2007-07-16 15:51:42 UTC (rev 2381)
+++ branches/ruby-2.6.21/ruby-2.6/drivers/video/console/vgacon.c 2007-07-16 15:52:23 UTC (rev 2382)
@@ -47,10 +47,6 @@
#include <linux/init.h>
#include <linux/screen_info.h>
#include <linux/smp_lock.h>
-#ifdef CONFIG_IA64
-#include <linux/efi.h>
-#endif
-
#include <video/vga.h>
#include <asm/io.h>
@@ -60,6 +56,8 @@
static int cursor_size_lastfrom;
static int cursor_size_lastto;
+static u32 vgacon_xres;
+static u32 vgacon_yres;
static struct vgastate state;
#define BLANK 0x0020
@@ -73,7 +71,7 @@
* appear.
*/
#undef TRIDENT_GLITCH
-
+#define VGA_FONTWIDTH 8 /* VGA does not support fontwidths != 8 */
/*
* Interface used by the world
*/
@@ -89,7 +87,7 @@
static int vgacon_set_origin(struct vc_data *c);
static void vgacon_save_screen(struct vc_data *c);
static int vgacon_scroll_region(struct vc_data *c, int t, int b, int dir,
- int lines);
+ int lines);
static u8 vgacon_build_attr(struct vc_data *c, u8 color, u8 intensity,
u8 blink, u8 underline, u8 reverse);
static void vgacon_invert_region(struct vc_data *c, u16 * p, int count);
@@ -102,6 +100,10 @@
static unsigned int vga_vram_size __read_mostly; /* Size of video memory */
static u16 vga_video_port_reg __read_mostly; /* Video register select port */
static u16 vga_video_port_val __read_mostly; /* Video register value port */
+static unsigned int vga_video_num_columns; /* Number of text columns */
+static unsigned int vga_video_num_lines; /* Number of text lines */
+static int vga_can_do_color __read_mostly; /* Do we support colors? */
+static unsigned int vga_default_font_height __read_mostly; /* Height of default screen font */
static unsigned char vga_video_type __read_mostly; /* Card type */
static unsigned char vga_hardscroll_enabled __read_mostly;
static unsigned char vga_hardscroll_user_enable __read_mostly = 1;
@@ -110,6 +112,8 @@
static int vga_palette_blanked;
static int vga_is_gfx;
static int vga_512_chars;
+static int vga_video_font_height;
+static int vga_scan_lines __read_mostly;
static unsigned int vga_rolled_over;
static int __init no_scroll(char *str)
@@ -354,21 +358,15 @@
static const char *vgacon_startup(struct vt_struct *vt, int init)
{
- struct vc_data *vc = &vga_default;
+ struct vc_data *vc = vt->default_mode = &vga_default;
const char *display_desc = NULL;
u16 saved1, saved2;
volatile u16 *p;
-#ifdef CONFIG_IA64
- if (efi_mem_type(0xA0000) == EFI_CONVENTIONAL_MEMORY)
- goto no_vga:
-#endif
-
if (ORIG_VIDEO_ISVGA == VIDEO_TYPE_VLFB) {
no_vga:
return NULL;
}
- vt->default_mode = vc;
/* VGA16 modes are not handled by VGACON */
if ((ORIG_VIDEO_MODE == 0x0D) || /* 320x200/4 */
@@ -378,8 +376,8 @@
(ORIG_VIDEO_MODE == 0x6A)) /* 800x600/4, 0x6A is very common */
goto no_vga;
- vc->vc_rows = ORIG_VIDEO_LINES;
- vc->vc_cols = ORIG_VIDEO_COLS;
+ vc->vc_rows = vga_video_num_lines = ORIG_VIDEO_LINES;
+ vc->vc_cols = vga_video_num_columns = ORIG_VIDEO_COLS;
state.vgabase = NULL;
if (ORIG_VIDEO_MODE == 7) { /* Is this a monochrome display? */
@@ -406,11 +404,11 @@
&mda1_console_resource);
request_resource(&ioport_resource,
&mda2_console_resource);
- vc->vc_font.height = 14;
+ vc->vc_font.height = vga_video_font_height = 14;
}
} else {
/* If not, it is color. */
- vc->vc_can_do_color = 1;
+ vc->vc_can_do_color = vga_can_do_color = 1;
vga_vram_base = 0xb8000;
vga_video_port_reg = VGA_CRT_IC;
vga_video_port_val = VGA_CRT_DC;
@@ -478,7 +476,7 @@
display_desc = "*CGA";
request_resource(&ioport_resource,
&cga_console_resource);
- vc->vc_font.height = 8;
+ vc->vc_font.height = vga_video_font_height = 8;
}
}
@@ -513,11 +511,18 @@
|| vga_video_type == VIDEO_TYPE_VGAC
|| vga_video_type == VIDEO_TYPE_EGAM) {
vga_hardscroll_enabled = vga_hardscroll_user_enable;
- vc->vc_font.height = ORIG_VIDEO_POINTS;
+ vga_default_font_height = ORIG_VIDEO_POINTS;
+ vga_video_font_height = ORIG_VIDEO_POINTS;
/* This may be suboptimal but is a safe bet - go with it */
- vc->vc_scan_lines = vc->vc_font.height * vc->vc_rows;
+ vga_scan_lines =
+ vga_video_font_height * vga_video_num_lines;
+ vc->vc_font.height = vga_default_font_height;
+ vc->vc_scan_lines = vga_scan_lines;
}
+ vgacon_xres = ORIG_VIDEO_COLS * VGA_FONTWIDTH;
+ vgacon_yres = vga_scan_lines;
+
if (!vga_init_done) {
vgacon_scrollback_startup();
vga_init_done = 1;
@@ -528,7 +533,6 @@
static void vgacon_init(struct vc_data *c, int init)
{
- struct vc_data *default_mode = c->display_fg->default_mode;
unsigned long p;
/*
@@ -536,14 +540,17 @@
* but vgacon_init can be called more than once, and init will
* not be 1.
*/
- c->vc_can_do_color = default_mode->vc_can_do_color;
-
+ c->vc_can_do_color = vga_can_do_color;
+
/* set dimensions manually if init != 0 since vc_resize() will fail */
- c->vc_cols = default_mode->vc_cols;
- c->vc_rows = default_mode->vc_rows;
+ if (init) {
+ c->vc_cols = vga_video_num_columns;
+ c->vc_rows = vga_video_num_lines;
+ } else
+ vc_resize(c, vga_video_num_columns, vga_video_num_lines);
- c->vc_scan_lines = default_mode->vc_scan_lines;
- c->vc_font.height = default_mode->vc_font.height;
+ c->vc_scan_lines = vga_scan_lines;
+ c->vc_font.height = vga_video_font_height;
c->vc_complement_mask = 0x7700;
if (vga_512_chars)
c->vc_hi_font_mask = 0x0800;
@@ -574,7 +581,7 @@
{
u8 attr = color;
- if (c->vc_can_do_color) {
+ if (vga_can_do_color) {
if (underline)
attr = (attr & 0xf0) | c->vc_ulcolor;
else if (intensity == 0)
@@ -588,7 +595,7 @@
attr ^= 0x80;
if (intensity == 2)
attr ^= 0x08;
- if (!c->vc_can_do_color) {
+ if (!vga_can_do_color) {
if (underline)
attr = (attr & 0xf8) | 0x01;
else if (intensity == 0)
@@ -599,7 +606,7 @@
static void vgacon_invert_region(struct vc_data *c, u16 * p, int count)
{
- int col = c->vc_can_do_color;
+ int col = vga_can_do_color;
while (count--) {
u16 a = scr_readw(p);
@@ -655,7 +662,7 @@
switch (mode) {
case CM_ERASE:
write_vga(14, (c->vc_pos - vga_vram_base) / 2);
- if (vga_video_type >= VIDEO_TYPE_VGAC)
+ if (vga_video_type >= VIDEO_TYPE_VGAC)
vgacon_set_cursor_size(c->vc_x, 31, 30);
else
vgacon_set_cursor_size(c->vc_x, 31, 31);
@@ -719,6 +726,8 @@
spin_lock_irqsave(&vga_lock, flags);
+ vgacon_xres = width * VGA_FONTWIDTH;
+ vgacon_yres = height * c->vc_font.height;
if (vga_video_type >= VIDEO_TYPE_VGAC) {
outb_p(VGA_CRTC_MAX_SCAN, vga_video_port_reg);
max_scan = inb_p(vga_video_port_val);
@@ -772,23 +781,30 @@
static int vgacon_switch(struct vc_data *c)
{
+ int x = c->vc_cols * VGA_FONTWIDTH;
int y = c->vc_rows * c->vc_font.height;
- int x = c->vc_cols = 8;
+ int rows = ORIG_VIDEO_LINES * vga_default_font_height/
+ c->vc_font.height;
+ /*
+ * We need to save screen size here as it's the only way
+ * we can spot the screen has been resized and we need to
+ * set size of freshly allocated screens ourselves.
+ */
+ vga_video_num_columns = c->vc_cols;
+ vga_video_num_lines = c->vc_rows;
/* We can only copy out the size of the video buffer here,
- * otherwise we get into VGA BIOS. We can only copy out
- * the size of the video buffer here, otherwise we get
- * into VGA BIOS */
+ * otherwise we get into VGA BIOS */
if (!vga_is_gfx) {
- struct winsize *ws = &c->vc_tty->winsize;
-
scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf,
c->vc_screenbuf_size > vga_vram_size ?
vga_vram_size : c->vc_screenbuf_size);
- if ((ws->ws_xpixel != x || ws->ws_ypixel != y) &&
- (!(c->vc_cols % 2) && c->vc_cols <= ORIG_VIDEO_COLS))
+ if ((vgacon_xres != x || vgacon_yres != y) &&
+ (!(vga_video_num_columns % 2) &&
+ vga_video_num_columns <= ORIG_VIDEO_COLS &&
+ vga_video_num_lines <= rows))
vgacon_doresize(c, c->vc_cols, c->vc_rows);
}
@@ -812,7 +828,8 @@
static int vgacon_set_palette(struct vc_data *vc, unsigned char *table)
{
#ifdef CAN_LOAD_PALETTE
- if (vga_video_type != VIDEO_TYPE_VGAC || vga_palette_blanked)
+ if (vga_video_type != VIDEO_TYPE_VGAC || vga_palette_blanked
+ || !IS_VISIBLE)
return -EINVAL;
vga_set_palette(vc, table);
return 0;
@@ -1125,7 +1142,6 @@
/* attribute controller */
for (i = 0; i < vga_vt.vc_count; i++) {
struct vc_data *vc = vga_vt.vc_cons[i];
-
if (vc)
vc->vc_hi_font_mask = ch512 ? 0x0800 : 0;
}
@@ -1151,13 +1167,8 @@
static int vgacon_adjust_height(struct vc_data *vc, unsigned fontheight)
{
unsigned char ovr, vde, fsr;
- int rows, maxscan;
+ int rows, maxscan, i;
- if (fontheight == vc->vc_font.height)
- return 0;
-
- vc->vc_font.height = fontheight;
-
rows = vc->vc_scan_lines / fontheight; /* Number of video rows we end up with */
maxscan = rows * fontheight - 1; /* Scan lines to actually display-1 */
@@ -1191,14 +1202,21 @@
outb_p(0x12, vga_video_port_reg); /* Vertical display limit */
outb_p(vde, vga_video_port_val);
spin_unlock_irq(&vga_lock);
+ vga_video_font_height = fontheight;
- if (IS_VISIBLE) {
- /* void size to cause regs to be rewritten */
- cursor_size_lastfrom = 0;
- cursor_size_lastto = 0;
- vgacon_cursor(vc, CM_DRAW);
- vc->vc_font.height = fontheight;
- vc_resize(vc, 0, rows); /* Adjust console size */
+ for (i = 0; i < vga_vt.vc_count; i++) {
+ struct vc_data *vc = vga_vt.vc_cons[i];
+
+ if (vc) {
+ if (IS_VISIBLE) {
+ /* void size to cause regs to be rewritten */
+ cursor_size_lastfrom = 0;
+ cursor_size_lastto = 0;
+ vc->display_fg->vt_sw->con_cursor(vc, CM_DRAW);
+ }
+ vc->vc_font.height = fontheight;
+ vc_resize(vc, 0, rows); /* Adjust console size */
+ }
}
return 0;
}
@@ -1211,7 +1229,8 @@
if (vga_video_type < VIDEO_TYPE_EGAM)
return -EINVAL;
- if (font->width != 8 || (charcount != 256 && charcount != 512))
+ if (font->width != VGA_FONTWIDTH ||
+ (charcount != 256 && charcount != 512))
return -EINVAL;
rc = vgacon_do_font_op(&state, font->data, 1, charcount == 512);
@@ -1228,7 +1247,7 @@
if (vga_video_type < VIDEO_TYPE_EGAM)
return -EINVAL;
- font->width = 8;
+ font->width = VGA_FONTWIDTH;
font->height = c->vc_font.height;
font->charcount = vga_512_chars ? 512 : 256;
if (!font->data)
@@ -1247,7 +1266,7 @@
unsigned int height)
{
if (width % 2 || width > ORIG_VIDEO_COLS ||
- height > (ORIG_VIDEO_LINES * vc->vc_font.height)/
+ height > (ORIG_VIDEO_LINES * vga_default_font_height)/
vc->vc_font.height)
/* let svgatextmode tinker with video timings */
return 0;
@@ -1260,7 +1279,7 @@
static int vgacon_set_origin(struct vc_data *c)
{
if (vga_is_gfx || /* We don't play origin tricks in graphic modes */
- (c->display_fg->vt_blanked && !vga_palette_blanked)) /* Nor we write to blanked screens */
+ (c->display_fg->vt_blanked && !vga_palette_blanked))/* Nor we write to blanked screens */
return 0;
c->vc_origin = c->vc_visible_origin = vga_vram_base;
vga_set_mem_top(c);
@@ -1270,6 +1289,18 @@
static void vgacon_save_screen(struct vc_data *c)
{
+ static int vga_bootup_console = 0;
+
+ if (!vga_bootup_console) {
+ /* This is a gross hack, but here is the only place we can
+ * set bootup console parameters without messing up generic
+ * console initialization routines.
+ */
+ vga_bootup_console = 1;
+ c->vc_x = ORIG_X;
+ c->vc_y = ORIG_Y;
+ }
+
/* We can't copy in more then the size of the video buffer,
* or we'll be copying in VGA BIOS */
@@ -1279,7 +1310,7 @@
}
static int vgacon_scroll_region(struct vc_data *c, int t, int b, int dir,
- int lines)
+ int lines)
{
unsigned long oldo;
unsigned int delta;
@@ -1370,7 +1401,7 @@
memset(&vga_vt, 0, sizeof(struct vt_struct));
vga_vt.kmalloced = 0;
vga_vt.vt_sw = &vga_con;
- display_desc = vt_map_display(&vga_vt, 1, MAX_NR_USER_CONSOLES);
+ display_desc = vt_map_display(&vga_vt, 1, 16);
if (!display_desc) return -ENODEV;
printk("Console: %s %s %dx%d vc:%d-%d\n",
vga_vt.default_mode->vc_can_do_color ? "Colour" : "Mono",
@@ -1378,6 +1409,6 @@
vga_vt.default_mode->vc_rows,
vga_vt.first_vc + 1, vga_vt.first_vc + vga_vt.vc_count);
return 0;
-}
+}
MODULE_LICENSE("GPL");
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <jsi...@us...> - 2007-07-16 15:51:44
|
Revision: 2381
http://linuxconsole.svn.sourceforge.net/linuxconsole/?rev=2381&view=rev
Author: jsimmons
Date: 2007-07-16 08:51:42 -0700 (Mon, 16 Jul 2007)
Log Message:
-----------
match closer to mainline
Modified Paths:
--------------
branches/ruby-2.6.21/ruby-2.6/include/linux/kbd_kern.h
Modified: branches/ruby-2.6.21/ruby-2.6/include/linux/kbd_kern.h
===================================================================
--- branches/ruby-2.6.21/ruby-2.6/include/linux/kbd_kern.h 2007-07-16 15:51:16 UTC (rev 2380)
+++ branches/ruby-2.6.21/ruby-2.6/include/linux/kbd_kern.h 2007-07-16 15:51:42 UTC (rev 2381)
@@ -7,27 +7,6 @@
#include <linux/keyboard.h>
#include <linux/input.h>
-/*
- * Exported functions/variables
- */
-
-#define KBD_DEFMODE ((1 << VC_REPEAT) | (1 << VC_META))
-
-/*
- * Some laptops take the 789uiojklm,. keys as number pad when NumLock is on.
- * This seems a good reason to start with NumLock off. On HIL keyboards
- * of PARISC machines however there is no NumLock key and everyone expects the keypad
- * to be used for numbers.
- */
-
-#if defined(CONFIG_PARISC) && (defined(CONFIG_KEYBOARD_HIL) || defined(CONFIG_KEYBOARD_HIL_OLD))
-#define KBD_DEFLEDS (1 << VC_NUMLOCK)
-#else
-#define KBD_DEFLEDS 0
-#endif
-
-#define KBD_DEFLOCK 0
-
extern struct tasklet_struct keyboard_tasklet;
extern int shift_state;
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <jsi...@us...> - 2007-07-16 15:51:18
|
Revision: 2380
http://linuxconsole.svn.sourceforge.net/linuxconsole/?rev=2380&view=rev
Author: jsimmons
Date: 2007-07-16 08:51:16 -0700 (Mon, 16 Jul 2007)
Log Message:
-----------
newer kernel
Added Paths:
-----------
branches/ruby-2.6.21/AGAINST-2.6.21
Copied: branches/ruby-2.6.21/AGAINST-2.6.21 (from rev 2379, branches/ruby-2.6.21/AGAINST-2.6.12)
===================================================================
--- branches/ruby-2.6.21/AGAINST-2.6.21 (rev 0)
+++ branches/ruby-2.6.21/AGAINST-2.6.21 2007-07-16 15:51:16 UTC (rev 2380)
@@ -0,0 +1 @@
+
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <jsi...@us...> - 2007-05-11 13:14:42
|
Revision: 2379
http://linuxconsole.svn.sourceforge.net/linuxconsole/?rev=2379&view=rev
Author: jsimmons
Date: 2007-05-11 06:14:40 -0700 (Fri, 11 May 2007)
Log Message:
-----------
Move from proc to sysfs only
Modified Paths:
--------------
branches/ruby-2.6.21/ruby-2.6/drivers/char/Makefile
branches/ruby-2.6.21/ruby-2.6/drivers/char/vt.c
Modified: branches/ruby-2.6.21/ruby-2.6/drivers/char/Makefile
===================================================================
--- branches/ruby-2.6.21/ruby-2.6/drivers/char/Makefile 2007-05-11 13:14:20 UTC (rev 2378)
+++ branches/ruby-2.6.21/ruby-2.6/drivers/char/Makefile 2007-05-11 13:14:40 UTC (rev 2379)
@@ -13,7 +13,7 @@
obj-$(CONFIG_UNIX98_PTYS) += pty.o
obj-y += misc.o
obj-$(CONFIG_VT) += vt_ioctl.o decvte.o vc_screen.o consolemap.o \
- consolemap_deftbl.o selection.o keyboard.o vt_proc.o vt_sysfs.o
+ consolemap_deftbl.o selection.o keyboard.o vt_sysfs.o
obj-$(CONFIG_HW_CONSOLE) += vt.o defkeymap.o
obj-$(CONFIG_MAGIC_SYSRQ) += sysrq.o
obj-$(CONFIG_ESPSERIAL) += esp.o
Modified: branches/ruby-2.6.21/ruby-2.6/drivers/char/vt.c
===================================================================
--- branches/ruby-2.6.21/ruby-2.6/drivers/char/vt.c 2007-05-11 13:14:20 UTC (rev 2378)
+++ branches/ruby-2.6.21/ruby-2.6/drivers/char/vt.c 2007-05-11 13:14:40 UTC (rev 2379)
@@ -129,9 +129,6 @@
#if defined (CONFIG_PROM_CONSOLE)
extern void prom_con_init(void);
#endif
-#ifdef CONFIG_PROC_FS
-extern int vt_proc_init(void);
-#endif
struct tty_driver *console_driver; /* TTY driver for all VT consoles */
static unsigned int current_vc; /* Which /dev/vc/X to allocate next */
@@ -1851,9 +1848,6 @@
current_vt += 1;
if (vt->kmalloced) {
vt_init_device(vt);
-#ifdef CONFIG_PROC_FS
- vt_proc_attach(vt);
-#endif
}
return display_desc;
}
@@ -1924,9 +1918,6 @@
panic("Couldn't register console driver\n");
vt_sysfs_init();
-#ifdef CONFIG_PROC_FS
- vt_proc_init();
-#endif
#if defined (CONFIG_PROM_CONSOLE)
prom_con_init();
#endif
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <jsi...@us...> - 2007-05-11 13:14:21
|
Revision: 2378
http://linuxconsole.svn.sourceforge.net/linuxconsole/?rev=2378&view=rev
Author: jsimmons
Date: 2007-05-11 06:14:20 -0700 (Fri, 11 May 2007)
Log Message:
-----------
update to git tree.
Modified Paths:
--------------
branches/ruby-2.6.21/ruby-2.6/drivers/char/keyboard.c
Modified: branches/ruby-2.6.21/ruby-2.6/drivers/char/keyboard.c
===================================================================
--- branches/ruby-2.6.21/ruby-2.6/drivers/char/keyboard.c 2007-04-21 16:45:57 UTC (rev 2377)
+++ branches/ruby-2.6.21/ruby-2.6/drivers/char/keyboard.c 2007-05-11 13:14:20 UTC (rev 2378)
@@ -41,7 +41,6 @@
#include <linux/input.h>
#include <linux/reboot.h>
-static void kbd_disconnect(struct input_handle *handle);
extern void ctrl_alt_del(void);
void compute_shiftstate(void);
@@ -131,45 +130,33 @@
static int sysrq_alt;
/*
- * Translation of scancodes to keycodes. We set them on only the first attached
- * keyboard - for per-keyboard setting, /dev/input/event is more useful.
+ * Translation of scancodes to keycodes. We set them on only the first
+ * keyboard in the list that accepts the scancode and keycode.
+ * Explanation for not choosing the first attached keyboard anymore:
+ * USB keyboards for example have two event devices: one for all "normal"
+ * keys and one for extra function keys (like "volume up", "make coffee",
+ * etc.). So this means that scancodes for the extra function keys won't
+ * be valid for the first event device, but will be for the second.
*/
int getkeycode(struct input_handle *handle, unsigned int scancode)
{
- struct input_dev *dev = handle->dev;
+ int error = -ENODEV, keycode;
- if (!dev)
- return -ENODEV;
-
- if (!dev->keycodesize || scancode >= dev->keycodemax)
- return -EINVAL;
-
- return INPUT_KEYCODE(dev, scancode);
+ if (handle) {
+ error = handle->dev->getkeycode(handle->dev, scancode, &keycode);
+ if (!error)
+ error = keycode;
+ }
+ return error;
}
int setkeycode(struct input_handle *handle, unsigned int scancode, unsigned int keycode)
{
- struct input_dev *dev = handle->dev;
- int i, oldkey;
+ int error = -ENODEV;
- if (!dev)
- return -ENODEV;
-
- if (scancode >= dev->keycodemax || keycode > KEY_MAX)
- return -EINVAL;
- if (dev->keycodesize < sizeof(keycode) && (keycode >> (dev->keycodesize * 8)))
- return -EINVAL;
-
- oldkey = SET_INPUT_KEYCODE(dev, scancode, keycode);
-
- clear_bit(oldkey, dev->keybit);
- set_bit(keycode, dev->keybit);
-
- for (i = 0; i < dev->keycodemax; i++)
- if (INPUT_KEYCODE(dev,i) == oldkey)
- set_bit(oldkey, dev->keybit);
-
- return 0;
+ if (handle)
+ error = handle->dev->setkeycode(handle->dev, scancode, keycode);
+ return error;
}
/*
@@ -1120,7 +1107,7 @@
if ((raw_mode = (vc->kbd_table.kbdmode == VC_RAW)) && !hw_raw)
if (emulate_raw(vc, keycode, !down << 7))
- if (keycode < BTN_MISC)
+ if (keycode < BTN_MISC && printk_ratelimit())
printk(KERN_WARNING "keyboard.c: can't emulate rawmode for keycode %d\n", keycode);
#ifdef CONFIG_MAGIC_SYSRQ /* Handle the SysRq Hack */
@@ -1245,12 +1232,11 @@
* likes it, it can open it and get events from it. In this (kbd_connect)
* function, we should decide which VT to bind that keyboard to initially.
*/
-static struct input_handle *kbd_connect(struct input_handler *handler,
- struct input_dev *dev,
- const struct input_device_id *id)
+static int kbd_connect(struct input_handler *handler, struct input_dev *dev,
+ const struct input_device_id *id)
{
- struct vt_struct *vt = NULL;
struct input_handle *handle;
+ struct vt_struct *vt = NULL;
int i;
for (i = KEY_RESERVED; i < BTN_MISC; i++)
@@ -1258,17 +1244,24 @@
break;
if (i == BTN_MISC && !test_bit(EV_SND, dev->evbit))
- return NULL;
+ return -ENODEV;
handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL);
if (!handle)
- return NULL;
+ return -ENOMEM;
handle->dev = dev;
handle->handler = handler;
handle->name = "kbd";
- input_open_device(handle);
+ error = input_register_handle(handle);
+ if (error)
+ goto err_free_handle;
+
+ error = input_open_device(handle);
+ if (error)
+ goto err_unregister_handle;
+
/*
* If we have more keyboards than VTs we still register the handler.
* It is possible someone might add a graphics card thus needing the
@@ -1299,7 +1292,12 @@
handle->private = admin_vt;
vt_map_input(admin_vt);
}
- return handle;
+
+err_unregister_handle:
+ input_unregister_handle(handle);
+err_free_handle:
+ kfree(handle);
+ return error;
}
static void kbd_disconnect(struct input_handle *handle)
@@ -1310,7 +1308,7 @@
vt->keyboard = NULL;
handle->private = NULL;
}
- input_close_device(handle);
+ input_unregister_handle(handle);
kfree(handle);
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <jsi...@us...> - 2007-04-21 16:46:02
|
Revision: 2377
http://linuxconsole.svn.sourceforge.net/linuxconsole/?rev=2377&view=rev
Author: jsimmons
Date: 2007-04-21 09:45:57 -0700 (Sat, 21 Apr 2007)
Log Message:
-----------
wrong spelling
Modified Paths:
--------------
branches/ruby-2.6.21/ruby-2.6/drivers/char/keyboard.c
Modified: branches/ruby-2.6.21/ruby-2.6/drivers/char/keyboard.c
===================================================================
--- branches/ruby-2.6.21/ruby-2.6/drivers/char/keyboard.c 2007-04-15 14:13:12 UTC (rev 2376)
+++ branches/ruby-2.6.21/ruby-2.6/drivers/char/keyboard.c 2007-04-21 16:45:57 UTC (rev 2377)
@@ -1022,7 +1022,7 @@
put_queue(vc, 0x45 | up_flag);
break;
- case KEY_HANGUEL:
+ case KEY_HANGEUL:
if (!up_flag)
put_queue(vc, 0xf2);
break;
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <jsi...@us...> - 2007-04-15 14:13:14
|
Revision: 2376
http://linuxconsole.svn.sourceforge.net/linuxconsole/?rev=2376&view=rev
Author: jsimmons
Date: 2007-04-15 07:13:12 -0700 (Sun, 15 Apr 2007)
Log Message:
-----------
Lots of fixes to makeit compile
Modified Paths:
--------------
branches/ruby-2.6.21/ruby-2.6/drivers/char/consolemap.c
branches/ruby-2.6.21/ruby-2.6/drivers/char/decvte.c
branches/ruby-2.6.21/ruby-2.6/drivers/char/keyboard.c
branches/ruby-2.6.21/ruby-2.6/drivers/char/sysrq.c
branches/ruby-2.6.21/ruby-2.6/drivers/char/vt.c
branches/ruby-2.6.21/ruby-2.6/drivers/char/vt_proc.c
branches/ruby-2.6.21/ruby-2.6/drivers/char/vt_sysfs.c
branches/ruby-2.6.21/ruby-2.6/drivers/video/console/dummycon.c
branches/ruby-2.6.21/ruby-2.6/drivers/video/console/vgacon.c
branches/ruby-2.6.21/ruby-2.6/include/linux/kbd_kern.h
branches/ruby-2.6.21/ruby-2.6/include/linux/vt_kern.h
Added Paths:
-----------
branches/ruby-2.6.21/ruby-2.6/kernel/power/
branches/ruby-2.6.21/ruby-2.6/kernel/power/Makefile
branches/ruby-2.6.21/ruby-2.6/kernel/power/disk.c
branches/ruby-2.6.21/ruby-2.6/kernel/power/main.c
Modified: branches/ruby-2.6.21/ruby-2.6/drivers/char/consolemap.c
===================================================================
--- branches/ruby-2.6.21/ruby-2.6/drivers/char/consolemap.c 2007-04-15 01:06:27 UTC (rev 2375)
+++ branches/ruby-2.6.21/ruby-2.6/drivers/char/consolemap.c 2007-04-15 14:13:12 UTC (rev 2376)
@@ -412,8 +412,8 @@
static int
con_insert_unipair(struct uni_pagedir *p, u_short unicode, u_short fontpos)
{
- int i, n;
u16 **p1, *p2;
+ int n;
if (!(p1 = p->uni_pgdir[n = unicode >> 11])) {
p1 = p->uni_pgdir[n] = kzalloc(32*sizeof(u16 *), GFP_KERNEL);
Modified: branches/ruby-2.6.21/ruby-2.6/drivers/char/decvte.c
===================================================================
--- branches/ruby-2.6.21/ruby-2.6/drivers/char/decvte.c 2007-04-15 01:06:27 UTC (rev 2375)
+++ branches/ruby-2.6.21/ruby-2.6/drivers/char/decvte.c 2007-04-15 14:13:12 UTC (rev 2376)
@@ -34,12 +34,10 @@
#include <linux/major.h>
#include <linux/mm.h>
#include <linux/init.h>
-#include <linux/devfs_fs_kernel.h>
#include <linux/vt_kern.h>
#include <linux/vt_buffer.h>
#include <linux/selection.h>
#include <linux/consolemap.h>
-#include <linux/config.h>
#include <linux/version.h>
#include <asm/io.h>
@@ -123,7 +121,7 @@
/*
* CARRIAGE RETURN (CR)
*/
-inline void vte_cr(struct vc_data *vc)
+void vte_cr(struct vc_data *vc)
{
vc->vc_pos -= vc->vc_x << 1;
vc->vc_need_wrap = vc->vc_x = 0;
@@ -132,7 +130,7 @@
/*
* BACK SPACE (BS)
*/
-inline void vte_bs(struct vc_data *vc)
+void vte_bs(struct vc_data *vc)
{
if (vc->vc_x) {
vc->vc_pos -= 2;
Modified: branches/ruby-2.6.21/ruby-2.6/drivers/char/keyboard.c
===================================================================
--- branches/ruby-2.6.21/ruby-2.6/drivers/char/keyboard.c 2007-04-15 01:06:27 UTC (rev 2375)
+++ branches/ruby-2.6.21/ruby-2.6/drivers/char/keyboard.c 2007-04-15 14:13:12 UTC (rev 2376)
@@ -43,28 +43,6 @@
static void kbd_disconnect(struct input_handle *handle);
extern void ctrl_alt_del(void);
-
-/*
- * Exported functions/variables
- */
-
-#define KBD_DEFMODE ((1 << VC_REPEAT) | (1 << VC_META))
-
-/*
- * Some laptops take the 789uiojklm,. keys as number pad when NumLock is on.
- * This seems a good reason to start with NumLock off. On HIL keyboards
- * of PARISC machines however there is no NumLock key and everyone expects the keypad
- * to be used for numbers.
- */
-
-#if defined(CONFIG_PARISC) && (defined(CONFIG_KEYBOARD_HIL) || defined(CONFIG_KEYBOARD_HIL_OLD))
-#define KBD_DEFLEDS (1 << VC_NUMLOCK)
-#else
-#define KBD_DEFLEDS 0
-#endif
-
-#define KBD_DEFLOCK 0
-
void compute_shiftstate(void);
/*
@@ -197,7 +175,7 @@
/*
* Making beeps and bells.
*/
-static void kd_nosound(unsigned long private)
+void kd_nosound(unsigned long private)
{
struct input_handle *handle = (struct input_handle *) private;
@@ -209,7 +187,7 @@
}
}
-static void kd_mksound(struct input_handle *handle, unsigned int hz, unsigned int ticks)
+void kd_mksound(struct input_handle *handle, unsigned int hz, unsigned int ticks)
{
struct vt_struct *vt;
@@ -245,9 +223,9 @@
if (test_bit(EV_REP, dev->evbit)) {
if (rep->delay > 0)
- input_inject_event(dev, EV_REP, REP_DELAY, rep->delay);
+ input_inject_event(handle, EV_REP, REP_DELAY, rep->delay);
if (rep->period > 0)
- input_inject_event(dev, EV_REP, REP_PERIOD, rep->period);
+ input_inject_event(handle, EV_REP, REP_PERIOD, rep->period);
d = dev->rep[REP_DELAY];
p = dev->rep[REP_PERIOD];
}
@@ -265,11 +243,11 @@
if (tty) {
tty_insert_flip_char(tty, ch, 0);
- schedule_work(&tty->flip.work);
+ tty_schedule_flip(tty);
}
}
-static void puts_queue(struct vc_data *vc, char *cp)
+void puts_queue(struct vc_data *vc, char *cp)
{
struct tty_struct *tty = vc->vc_tty;
@@ -280,7 +258,7 @@
tty_insert_flip_char(tty, *cp, 0);
cp++;
}
- schedule_work(&tty->flip.work);
+ tty_schedule_flip(tty);
}
static void applkey(struct vc_data *vc, int key, char mode)
@@ -393,7 +371,7 @@
static void fn_enter(struct vc_data *vc)
{
if (diacr) {
- if (kbd->kbdmode == VC_UNICODE)
+ if (vc->kbd_table.kbdmode == VC_UNICODE)
to_utf8(vc, diacr);
else if (diacr < 0x100)
put_queue(vc, diacr);
@@ -508,7 +486,7 @@
if (!tty)
return;
tty_insert_flip_char(tty, 0, TTY_BREAK);
- schedule_work(&tty->flip.work);
+ tty_schedule_flip(tty);
}
static void fn_scroll_forw(struct vc_data *vc)
@@ -608,7 +586,7 @@
diacr = value;
return;
}
- if (kbd->kbdmode == VC_UNICODE)
+ if (vc->kbd_table.kbdmode == VC_UNICODE)
to_utf8(vc, value);
else if (value < 0x100)
put_queue(vc, value);
@@ -1316,7 +1294,6 @@
break;
}
}
- kbd_start(handle);
} else if (test_bit(EV_SND, dev->evbit) && admin_vt && !admin_vt->beeper) {
admin_vt->beeper = handle;
handle->private = admin_vt;
Modified: branches/ruby-2.6.21/ruby-2.6/drivers/char/sysrq.c
===================================================================
--- branches/ruby-2.6.21/ruby-2.6/drivers/char/sysrq.c 2007-04-15 01:06:27 UTC (rev 2375)
+++ branches/ruby-2.6.21/ruby-2.6/drivers/char/sysrq.c 2007-04-15 14:13:12 UTC (rev 2376)
@@ -90,9 +90,8 @@
{
if (tty->driver->type == TTY_DRIVER_TYPE_CONSOLE) {
struct vc_data *vc = (struct vc_data *) tty->driver_data;
- struct work_struct *SAK_work = vc->SAK_work; // Should this be fg_console
-
- schedule_work(SAK_work);
+ // Should this be fg_console
+ schedule_work(&vc->SAK_work);
}
}
static struct sysrq_key_op sysrq_SAK_op = {
Modified: branches/ruby-2.6.21/ruby-2.6/drivers/char/vt.c
===================================================================
--- branches/ruby-2.6.21/ruby-2.6/drivers/char/vt.c 2007-04-15 01:06:27 UTC (rev 2375)
+++ branches/ruby-2.6.21/ruby-2.6/drivers/char/vt.c 2007-04-15 14:13:12 UTC (rev 2376)
@@ -714,28 +714,6 @@
* Screen blanking
*/
-static void powerdown_screen(unsigned long private)
-{
- /*
- * Power down if currently suspended (1 or 2),
- * suspend if currently blanked (0),
- * else do nothing (i.e. already powered down (3)).
- * Called only if powerdown features are allowed.
- */
- struct vt_struct *vt = (struct vt_struct *) private;
- struct vc_data *vc = vt->fg_console;
-
- switch (vc->display_fg->blank_mode) {
- case VESA_NO_BLANKING:
- sw->con_blank(vc, VESA_VSYNC_SUSPEND+1, 0);
- break;
- case VESA_VSYNC_SUSPEND:
- case VESA_HSYNC_SUSPEND:
- sw->con_blank(vc, VESA_POWERDOWN+1, 0);
- break;
- }
-}
-
void do_blank_screen(struct vt_struct *vt, int entering_gfx)
{
struct vc_data *vc = vt->fg_console;
@@ -746,7 +724,7 @@
if (vt->vt_blanked) {
if (vt->blank_state == blank_vesa_wait) {
vt->blank_state = blank_off;
- vc->vc_sw->con_blank(vc, vesa_blank_mode + 1, 0);
+ vt->vt_sw->con_blank(vc, vt->blank_mode + 1, 0);
}
return;
}
@@ -776,7 +754,7 @@
save_screen(vc);
/* In case we need to reset origin, blanking hook returns 1 */
- i = sw->con_blank(vc, vesa_off_interval ? 1 : (vesa_blank_mode + 1), 0);
+ i = sw->con_blank(vc, vt->off_interval ? 1 : (vt->blank_mode + 1), 0);
vt->vt_blanked = 1;
if (i)
set_origin(vc);
@@ -884,7 +862,7 @@
*/
static void vt_callback(struct work_struct *work)
{
- struct vt_struct *vt = container_of(work, struct vt_struct, SAK_work);
+ struct vt_struct *vt = container_of(work, struct vt_struct, vt_work);
if (!vt || !vt->want_vc || !vt->want_vc->vc_tty)
return;
@@ -916,6 +894,26 @@
release_console_sem();
}
+void vc_SAK(struct work_struct *work)
+{
+ struct vc_data *vc =
+ container_of(work, struct vc_data, SAK_work);
+ struct tty_struct *tty;
+
+ acquire_console_sem();
+ if (vc) {
+ tty = vc->vc_tty;
+ /*
+ * SAK should also work in all raw modes and reset
+ * them properly.
+ */
+ if (tty)
+ __do_SAK(tty);
+ reset_vc(vc);
+ }
+ release_console_sem();
+}
+
int set_console(struct vc_data *vc)
{
if (!vc || vc->display_fg->vt_dont_switch ||
@@ -1074,7 +1072,7 @@
module_put(sw->owner);
vt->vc_cons[vc->vc_num - vt->first_vc] = NULL;
if (vt->kmalloced)
- kfree(screenbuf);
+ kfree(vc->vc_screenbuf);
kfree(vc);
}
return 0;
@@ -1223,38 +1221,6 @@
return 0;
}
-int vc_lock_resize(struct vc_data *vc, unsigned int cols, unsigned int lines)
-{
- int rc;
-
- acquire_console_sem();
- rc = vc_resize(vc, cols, lines);
- release_console_sem();
- return rc;
-}
-
-void vc_SAK(struct work_struct *work)
-{
- struct vc *vc_con =
- container_of(work, struct vc, SAK_work);
- struct tty_struct *tty;
- struct vc_data *vc;
-
- acquire_console_sem();
- vc = vc_con->d;
- if (vc) {
- tty = vc->vc_tty;
- /*
- * SAK should also work in all raw modes and reset
- * them properly.
- */
- if (tty)
- __do_SAK(tty);
- reset_vc(vc);
- }
- release_console_sem();
-}
-
/*
* Selection stuff for GPM.
*/
@@ -1311,7 +1277,7 @@
if (!vc) {
printk("vt_write: tty %d not allocated\n", tty->index);
release_console_sem();
- return 0;
+ return n;
}
release_console_sem();
@@ -1335,7 +1301,9 @@
hide_cursor(vc);
while (!tty->stopped && count) {
- c = *buf;
+ int orig = *buf;
+
+ c = orig;
buf++;
n++;
count--;
@@ -1348,7 +1316,7 @@
/* Malformed sequences as sequences of replacement glyphs */
rescan_last_byte:
if(c > 0x7f) {
- if (vc->vc_utf_count > 0)
+ if (vc->vc_utf_count > 0) {
if ((c & 0xc0) == 0x80) {
vc->vc_utf_char = (vc->vc_utf_char << 6) | (c & 0x3f);
if (--vc->vc_utf_count) {
@@ -1356,8 +1324,8 @@
continue;
}
tc = c = vc->vc_utf_char;
- else
- goto replacement;
+ } else
+ goto replacement_glyph;
} else {
vc->vc_npar = 0;
if ((c & 0xe0) == 0xc0) {
@@ -1464,8 +1432,6 @@
FLUSH
console_conditional_schedule();
release_console_sem();
-
-out:
return n;
#undef FLUSH
}
@@ -1854,7 +1820,7 @@
list_add_tail(&vt->node, &vt_list);
init_MUTEX(&vt->lock);
vt->vt_num = current_vt;
- vt->display_desc = (char *)display_desc;
+ vt->desc = (char *)display_desc;
vt->vt_dont_switch = 0;
vt->scrollback_delta = 0;
vt->vt_blanked = 0;
@@ -1866,7 +1832,7 @@
vt->timer.function = blank_screen_t;
mod_timer(&vt->timer, jiffies + vt->blank_interval);
vt->keyboard = NULL;
- INIT_WORK(&vt->vt_work, vt_callback, vt);
+ INIT_WORK(&vt->vt_work, vt_callback);
if (!admin_vt) {
admin_vt = vt;
@@ -1884,7 +1850,7 @@
current_vc += vc_count;
current_vt += 1;
if (vt->kmalloced) {
- vt_create_sysfs_dev_files(vt);
+ vt_init_device(vt);
#ifdef CONFIG_PROC_FS
vt_proc_attach(vt);
#endif
@@ -2011,7 +1977,7 @@
module_put(owner);
return -ENODEV;
}
- vt->display_desc = (char *)desc;
+ vt->desc = (char *)desc;
vt->vt_sw = csw;
/* Set the VC states to the new default mode */
@@ -2025,7 +1991,7 @@
vc->vc_origin = (unsigned long) vc->vc_screenbuf;
vc->vc_visible_origin = vc->vc_origin;
vc->vc_scr_end = vc->vc_origin + vc->vc_screenbuf_size;
- vc->vc_pos = vc->vc_origin + vc->vc_size_rows * vc->vc_y + 2 * vc->vc_x;
+ vc->vc_pos = vc->vc_origin + vc->vc_size_row * vc->vc_y + 2 * vc->vc_x;
INIT_WORK(&vc->SAK_work, vc_SAK);
visual_init(vc, 0);
set_origin(vc);
@@ -2063,7 +2029,7 @@
EXPORT_SYMBOL(vc_lock_resize);
EXPORT_SYMBOL(console_blank_hook);
EXPORT_SYMBOL(vt_list);
-EXPORT_SYMBOL(take_over_console);
+EXPORT_SYMBOL(bind_vt_driver);
EXPORT_SYMBOL(update_region);
EXPORT_SYMBOL(update_screen);
EXPORT_SYMBOL(vt_map_display);
Modified: branches/ruby-2.6.21/ruby-2.6/drivers/char/vt_proc.c
===================================================================
--- branches/ruby-2.6.21/ruby-2.6/drivers/char/vt_proc.c 2007-04-15 01:06:27 UTC (rev 2375)
+++ branches/ruby-2.6.21/ruby-2.6/drivers/char/vt_proc.c 2007-04-15 14:13:12 UTC (rev 2376)
@@ -6,8 +6,6 @@
* Aivils Stoss <>
*/
-#include <linux/config.h>
-
#ifdef CONFIG_PROC_FS
#include <linux/types.h>
#include <linux/kernel.h>
@@ -53,7 +51,7 @@
if(!vt) return 0;
- len = sprintf(page, "%s\n", vt->display_desc ? vt->display_desc : "");
+ len = sprintf(page, "%s\n", vt->desc ? vt->desc : "");
return generic_read(page, start, off, count, eof, len);
}
@@ -103,7 +101,7 @@
}
handle->private = vt;
printk("keyboard: [%s] bound to [%s] vc:%d-%d\n",
- handle->dev->name, vt->display_desc, vt->first_vc + 1,
+ handle->dev->name, vt->desc, vt->first_vc + 1,
vt->first_vc + vt->vc_count);
}
return count;
Modified: branches/ruby-2.6.21/ruby-2.6/drivers/char/vt_sysfs.c
===================================================================
--- branches/ruby-2.6.21/ruby-2.6/drivers/char/vt_sysfs.c 2007-04-15 01:06:27 UTC (rev 2375)
+++ branches/ruby-2.6.21/ruby-2.6/drivers/char/vt_sysfs.c 2007-04-15 14:13:12 UTC (rev 2376)
@@ -26,7 +26,7 @@
}
static ssize_t show_keyboard(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
+ char *buf)
{
struct vt_struct *vt = dev_get_drvdata(dev);
struct input_handle *handle = vt->keyboard;
@@ -45,7 +45,7 @@
if (bind)
vt_bind(vt);
else
- vt_unbind(con);
+ vt_unbind(vt);
return count;
}
@@ -74,41 +74,42 @@
__ATTR(name, S_IRUGO, show_name, NULL),
};
-static int vt_init_device(struct vt_struct *vt)
+int vt_init_device(struct vt_struct *vt)
{
int err = 0;
- vt->dev = device_create(vt_class, NULL, MKDEV(0, vt->count),
- "vtcon%i", vt->count);
+ vt->dev = device_create(vt_class, NULL, MKDEV(0, vt->vc_count),
+ "vtcon%i", vt->vc_count);
if (IS_ERR(vt->dev)) {
vt->flag &= ~CON_DRIVER_FLAG_ATTR;
vt->dev = NULL;
- error = -EINVAL;
+ err = -EINVAL;
} else {
dev_set_drvdata(vt->dev, vt);
- fb_info->flag |= CON_DRIVER_FLAG_ATTR;
+ vt->flag |= CON_DRIVER_FLAG_ATTR;
}
return err;
}
-static void vt_deinit_device(struct vt_struct *vt)
+void vt_deinit_device(struct vt_struct *vt)
{
vt->flag &= ~CON_DRIVER_FLAG_ATTR;
dev_set_drvdata(vt->dev, NULL);
- device_destroy(vt_class, MKDEV(0, vt->count));
+ device_destroy(vt_class, MKDEV(0, vt->vc_count));
}
-void __init vt_sysfs_init(void)
+int __init vt_sysfs_init(void)
{
/* we have only one boot time console - admin_vt*/
vt_class = class_create(THIS_MODULE, "vt");
if (IS_ERR(vt_class)) {
printk(KERN_WARNING "Unable to create vt console class; "
- "errno = %ld\n", PTR_ERR(vtconsole_class));
+ "errno = %ld\n", PTR_ERR(vt_class));
vt_class = NULL;
} else {
- vt_class->dev_attrs = vt_device_attrs
+ vt_class->dev_attrs = vt_device_attrs;
}
+ return 0;
}
-postcore_initcall(vtconsole_class_init);
+postcore_initcall(vt_sysfs_init);
Modified: branches/ruby-2.6.21/ruby-2.6/drivers/video/console/dummycon.c
===================================================================
--- branches/ruby-2.6.21/ruby-2.6/drivers/video/console/dummycon.c 2007-04-15 01:06:27 UTC (rev 2375)
+++ branches/ruby-2.6.21/ruby-2.6/drivers/video/console/dummycon.c 2007-04-15 14:13:12 UTC (rev 2376)
@@ -32,10 +32,9 @@
#define MAX_DUMB_CONSOLES 16
-static const char *dummycon_startup(void)
-static unsigned long dumb_num = 0;
-static struct vt_struct dummy_vt;
static struct vc_data default_mode;
+static struct vt_struct dummy_vt;
+static unsigned long dumb_num;
static const char *dummycon_startup(struct vt_struct *vt, int init)
{
@@ -45,11 +44,6 @@
return "dummy device";
}
-static const char *dummycon_startup(void)
-{
- return "dummy device";
-}
-
static void dummycon_init(struct vc_data *vc, int init)
{
vc->vc_can_do_color = 1;
@@ -82,7 +76,7 @@
.con_putc = DUMMY,
.con_putcs = DUMMY,
.con_cursor = DUMMY,
- .con_scroll = DUMMY,
+ .con_scroll_region =DUMMY,
.con_bmove = DUMMY,
.con_switch = DUMMY,
.con_blank = DUMMY,
@@ -91,7 +85,7 @@
.con_font_default = DUMMY,
.con_font_copy = DUMMY,
.con_set_palette = DUMMY,
- .con_scrolldelta = DUMMY,
+ .con_scroll = DUMMY,
};
int __init dumbcon_init(void)
@@ -99,7 +93,7 @@
const char *display_desc = NULL;
memset(&dummy_vt, 0, sizeof(struct vt_struct));
- dummy_vt.vt_kmalloced = 0;
+ dummy_vt.kmalloced = 0;
dummy_vt.vt_sw = &dummy_con;
display_desc = vt_map_display(&dummy_vt, 1, MAX_NR_USER_CONSOLES);
if (!display_desc) return -ENODEV;
@@ -120,7 +114,7 @@
if (!vt) return -ENOMEM;
memset(vt, 0, sizeof(struct vt_struct));
- vt->vt_kmalloced = 1;
+ vt->kmalloced = 1;
vt->vt_sw = &dummy_con;
display_desc = vt_map_display(vt, 1, MIN_NR_CONSOLES);
if (!display_desc) {
Modified: branches/ruby-2.6.21/ruby-2.6/drivers/video/console/vgacon.c
===================================================================
--- branches/ruby-2.6.21/ruby-2.6/drivers/video/console/vgacon.c 2007-04-15 01:06:27 UTC (rev 2375)
+++ branches/ruby-2.6.21/ruby-2.6/drivers/video/console/vgacon.c 2007-04-15 14:13:12 UTC (rev 2376)
@@ -719,8 +719,6 @@
spin_lock_irqsave(&vga_lock, flags);
- vgacon_xres = width * VGA_FONTWIDTH;
- vgacon_yres = height * c->vc_font.height;
if (vga_video_type >= VIDEO_TYPE_VGAC) {
outb_p(VGA_CRTC_MAX_SCAN, vga_video_port_reg);
max_scan = inb_p(vga_video_port_val);
@@ -774,20 +772,23 @@
static int vgacon_switch(struct vc_data *c)
{
+ int y = c->vc_rows * c->vc_font.height;
+ int x = c->vc_cols = 8;
+
/* We can only copy out the size of the video buffer here,
* otherwise we get into VGA BIOS. We can only copy out
* the size of the video buffer here, otherwise we get
* into VGA BIOS */
if (!vga_is_gfx) {
+ struct winsize *ws = &c->vc_tty->winsize;
+
scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf,
c->vc_screenbuf_size > vga_vram_size ?
vga_vram_size : c->vc_screenbuf_size);
- if ((vgacon_xres != x || vgacon_yres != y) &&
- (!(vga_video_num_columns % 2) &&
- vga_video_num_columns <= ORIG_VIDEO_COLS &&
- vga_video_num_lines <= rows))
+ if ((ws->ws_xpixel != x || ws->ws_ypixel != y) &&
+ (!(c->vc_cols % 2) && c->vc_cols <= ORIG_VIDEO_COLS))
vgacon_doresize(c, c->vc_cols, c->vc_rows);
}
@@ -1242,17 +1243,17 @@
#endif
-static int vgacon_resize(struct vc_data *c, unsigned int width,
+static int vgacon_resize(struct vc_data *vc, unsigned int width,
unsigned int height)
{
if (width % 2 || width > ORIG_VIDEO_COLS ||
- height > (ORIG_VIDEO_LINES * vga_default_font_height)/
- c->vc_font.height)
+ height > (ORIG_VIDEO_LINES * vc->vc_font.height)/
+ vc->vc_font.height)
/* let svgatextmode tinker with video timings */
return 0;
if (IS_VISIBLE && !vga_is_gfx) /* who knows */
- vgacon_doresize(c, width, height);
+ vgacon_doresize(vc, width, height);
return 0;
}
@@ -1367,7 +1368,7 @@
const char *display_desc = NULL;
memset(&vga_vt, 0, sizeof(struct vt_struct));
- vga_vt.vt_kmalloced = 0;
+ vga_vt.kmalloced = 0;
vga_vt.vt_sw = &vga_con;
display_desc = vt_map_display(&vga_vt, 1, MAX_NR_USER_CONSOLES);
if (!display_desc) return -ENODEV;
Modified: branches/ruby-2.6.21/ruby-2.6/include/linux/kbd_kern.h
===================================================================
--- branches/ruby-2.6.21/ruby-2.6/include/linux/kbd_kern.h 2007-04-15 01:06:27 UTC (rev 2375)
+++ branches/ruby-2.6.21/ruby-2.6/include/linux/kbd_kern.h 2007-04-15 14:13:12 UTC (rev 2376)
@@ -7,6 +7,27 @@
#include <linux/keyboard.h>
#include <linux/input.h>
+/*
+ * Exported functions/variables
+ */
+
+#define KBD_DEFMODE ((1 << VC_REPEAT) | (1 << VC_META))
+
+/*
+ * Some laptops take the 789uiojklm,. keys as number pad when NumLock is on.
+ * This seems a good reason to start with NumLock off. On HIL keyboards
+ * of PARISC machines however there is no NumLock key and everyone expects the keypad
+ * to be used for numbers.
+ */
+
+#if defined(CONFIG_PARISC) && (defined(CONFIG_KEYBOARD_HIL) || defined(CONFIG_KEYBOARD_HIL_OLD))
+#define KBD_DEFLEDS (1 << VC_NUMLOCK)
+#else
+#define KBD_DEFLEDS 0
+#endif
+
+#define KBD_DEFLOCK 0
+
extern struct tasklet_struct keyboard_tasklet;
extern int shift_state;
Modified: branches/ruby-2.6.21/ruby-2.6/include/linux/vt_kern.h
===================================================================
--- branches/ruby-2.6.21/ruby-2.6/include/linux/vt_kern.h 2007-04-15 01:06:27 UTC (rev 2375)
+++ branches/ruby-2.6.21/ruby-2.6/include/linux/vt_kern.h 2007-04-15 14:13:12 UTC (rev 2376)
@@ -11,9 +11,10 @@
#include <linux/kbd_kern.h>
#include <linux/device.h>
-#define MIN_NR_CONSOLES 1 /* must be at least 1 */
-#define MAX_NR_CONSOLES 63 /* serial lines start at 64 */
-#define MAX_NR_USER_CONSOLES 16 /* number of VCs per VT */
+/* VT driver state */
+#define CON_DRIVER_FLAG_MODULE 1
+#define CON_DRIVER_FLAG_INIT 2
+#define CON_DRIVER_FLAG_ATTR 4
/* scroll */
#define SM_UP (1)
@@ -117,7 +118,7 @@
struct tty_struct *vc_tty; /* TTY we are attached to */
/* data for manual vt switching */
struct vt_mode vt_mode;
- int vt_pid;
+ struct pid *vt_pid;
int vt_newvt;
/* mode flags */
unsigned int vc_charset:1; /* Character set G0 / G1 */
@@ -192,6 +193,8 @@
unsigned char vc_saved_G2;
unsigned char vc_saved_G3;
unsigned char vc_saved_GS;
+
+ struct work_struct SAK_work; // Does it really belong here ?
};
struct consw {
@@ -229,6 +232,7 @@
struct vc_data *want_vc; /* VC we want to switch to */
int scrollback_delta;
int cursor_original;
+ int flag;
char kmalloced; /* Did we use kmalloced ? */
char vt_dont_switch; /* VC switching flag */
char vt_blanked; /* Is this display blanked */
@@ -261,8 +265,8 @@
struct proc_dir_entry *procdir;
unsigned char vt_ledstate;
unsigned char vt_ledioctl;
- char *display_desc;
- struct class_device dev; /* Generic device interface */
+ char *desc;
+ struct device *dev; /* Generic device interface */
};
extern struct list_head vt_list;
@@ -272,9 +276,9 @@
/* universal VT emulation functions */
void vte_ris(struct vc_data *vc, int do_clear);
-inline void vte_cr(struct vc_data *vc);
+void vte_cr(struct vc_data *vc);
void vte_lf(struct vc_data *vc);
-inline void vte_bs(struct vc_data *vc);
+void vte_bs(struct vc_data *vc);
void vte_ed(struct vc_data *vc, int vpar);
void vte_decsc(struct vc_data *vc);
void terminal_emulation(struct tty_struct *tty, int c);
@@ -296,16 +300,16 @@
void vt_map_input(struct vt_struct *vt);
struct vc_data *find_vc(int currcons);
struct vc_data *vc_allocate(unsigned int console);
-inline int set_console(struct vc_data *vc);
+int set_console(struct vc_data *vc);
int vc_resize(struct vc_data *vc, unsigned int lines, unsigned int cols);
int vc_lock_resize(struct vc_data *vc, unsigned int cols, unsigned int lines);
-int vc_disallocate(struct vc_data *vc);
+int vc_deallocate(struct vc_data *vc);
void reset_vc(struct vc_data *vc);
void add_softcursor(struct vc_data *vc);
void set_cursor(struct vc_data *vc);
void hide_cursor(struct vc_data *vc);
void gotoxy(struct vc_data *vc, int new_x, int new_y);
-inline void gotoxay(struct vc_data *vc, int new_x, int new_y);
+void gotoxay(struct vc_data *vc, int new_x, int new_y);
void reset_palette(struct vc_data *vc);
void set_palette(struct vc_data *vc);
void scroll_up(struct vc_data *vc, int);
@@ -319,7 +323,7 @@
void insert_line(struct vc_data *vc, unsigned int nr);
void delete_line(struct vc_data *vc, unsigned int nr);
void set_origin(struct vc_data *vc);
-inline void clear_region(struct vc_data *vc, int x, int y, int width, int height);
+void clear_region(struct vc_data *vc, int x, int y, int width, int height);
void do_update_region(struct vc_data *vc, unsigned long start, int count);
void update_region(struct vc_data *vc, unsigned long start, int count);
void update_screen(struct vc_data *vc);
@@ -357,13 +361,16 @@
void con_protect_unimap(struct vc_data *vc, int rdonly);
int con_copy_unimap(struct vc_data *dst, struct vc_data *src);
+/* keyboard.c */
+void puts_queue(struct vc_data *vc, char *cp);
+
/* vt_ioctl.c */
void complete_change_console(struct vc_data *new_vc, struct vc_data *old_vc);
void change_console(struct vc_data *new_vc, struct vc_data *old_vc);
/* vt_sysfs.c*/
-int __init vt_create_sysfs_dev_files (struct vt_struct *vt);
-void __init vt_sysfs_init(void);
+int __init vt_init_device(struct vt_struct *vt);
+int __init vt_sysfs_init(void);
/* vt_proc.c */
#ifdef CONFIG_PROC_FS
extern int vt_proc_attach(struct vt_struct *vt);
Added: branches/ruby-2.6.21/ruby-2.6/kernel/power/Makefile
===================================================================
--- branches/ruby-2.6.21/ruby-2.6/kernel/power/Makefile (rev 0)
+++ branches/ruby-2.6.21/ruby-2.6/kernel/power/Makefile 2007-04-15 14:13:12 UTC (rev 2376)
@@ -0,0 +1,10 @@
+
+ifeq ($(CONFIG_PM_DEBUG),y)
+EXTRA_CFLAGS += -DDEBUG
+endif
+
+obj-y := main.o process.o
+obj-$(CONFIG_PM_LEGACY) += pm.o
+obj-$(CONFIG_SOFTWARE_SUSPEND) += swsusp.o disk.o snapshot.o swap.o user.o
+
+obj-$(CONFIG_MAGIC_SYSRQ) += poweroff.o
Added: branches/ruby-2.6.21/ruby-2.6/kernel/power/disk.c
===================================================================
--- branches/ruby-2.6.21/ruby-2.6/kernel/power/disk.c (rev 0)
+++ branches/ruby-2.6.21/ruby-2.6/kernel/power/disk.c 2007-04-15 14:13:12 UTC (rev 2376)
@@ -0,0 +1,461 @@
+/*
+ * kernel/power/disk.c - Suspend-to-disk support.
+ *
+ * Copyright (c) 2003 Patrick Mochel
+ * Copyright (c) 2003 Open Source Development Lab
+ * Copyright (c) 2004 Pavel Machek <pa...@su...>
+ *
+ * This file is released under the GPLv2.
+ *
+ */
+
+#include <linux/suspend.h>
+#include <linux/syscalls.h>
+#include <linux/reboot.h>
+#include <linux/string.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/fs.h>
+#include <linux/mount.h>
+#include <linux/pm.h>
+#include <linux/console.h>
+#include <linux/cpu.h>
+#include <linux/freezer.h>
+
+#include "power.h"
+
+
+static int noresume = 0;
+char resume_file[256] = CONFIG_PM_STD_PARTITION;
+dev_t swsusp_resume_device;
+sector_t swsusp_resume_block;
+
+/**
+ * platform_prepare - prepare the machine for hibernation using the
+ * platform driver if so configured and return an error code if it fails
+ */
+
+static inline int platform_prepare(void)
+{
+ int error = 0;
+
+ if (pm_disk_mode == PM_DISK_PLATFORM) {
+ if (pm_ops && pm_ops->prepare)
+ error = pm_ops->prepare(PM_SUSPEND_DISK);
+ }
+ return error;
+}
+
+/**
+ * power_down - Shut machine down for hibernate.
+ * @mode: Suspend-to-disk mode
+ *
+ * Use the platform driver, if configured so, and return gracefully if it
+ * fails.
+ * Otherwise, try to power off and reboot. If they fail, halt the machine,
+ * there ain't no turning back.
+ */
+
+static void power_down(suspend_disk_method_t mode)
+{
+ switch(mode) {
+ case PM_DISK_PLATFORM:
+ if (pm_ops && pm_ops->enter) {
+ kernel_shutdown_prepare(SYSTEM_SUSPEND_DISK);
+ pm_ops->enter(PM_SUSPEND_DISK);
+ break;
+ }
+ case PM_DISK_SHUTDOWN:
+ kernel_power_off();
+ break;
+ case PM_DISK_REBOOT:
+ kernel_restart(NULL);
+ break;
+ }
+ kernel_halt();
+ /* Valid image is on the disk, if we continue we risk serious data corruption
+ after resume. */
+ printk(KERN_CRIT "Please power me down manually\n");
+ while(1);
+}
+
+static inline void platform_finish(void)
+{
+ if (pm_disk_mode == PM_DISK_PLATFORM) {
+ if (pm_ops && pm_ops->finish)
+ pm_ops->finish(PM_SUSPEND_DISK);
+ }
+}
+
+static void unprepare_processes(void)
+{
+ thaw_processes();
+}
+
+static int prepare_processes(void)
+{
+ int error = 0;
+
+ if (freeze_processes()) {
+ error = -EBUSY;
+ unprepare_processes();
+ }
+ return error;
+}
+
+/**
+ * pm_suspend_disk - The granpappy of hibernation power management.
+ *
+ * If we're going through the firmware, then get it over with quickly.
+ *
+ * If not, then call swsusp to do its thing, then figure out how
+ * to power down the system.
+ */
+
+int pm_suspend_disk(void)
+{
+ int error;
+
+ error = prepare_processes();
+ if (error)
+ return error;
+
+ if (pm_disk_mode == PM_DISK_TESTPROC) {
+ printk("swsusp debug: Waiting for 5 seconds.\n");
+ mdelay(5000);
+ goto Thaw;
+ }
+ /* Free memory before shutting down devices. */
+ error = swsusp_shrink_memory();
+ if (error)
+ goto Thaw;
+
+ error = platform_prepare();
+ if (error)
+ goto Thaw;
+
+ error = device_suspend(PMSG_FREEZE);
+ if (error) {
+ printk(KERN_ERR "PM: Some devices failed to suspend\n");
+ goto Resume_devices;
+ }
+ error = disable_nonboot_cpus();
+ if (error)
+ goto Enable_cpus;
+
+ if (pm_disk_mode == PM_DISK_TEST) {
+ printk("swsusp debug: Waiting for 5 seconds.\n");
+ mdelay(5000);
+ goto Enable_cpus;
+ }
+
+ pr_debug("PM: snapshotting memory.\n");
+ in_suspend = 1;
+ error = swsusp_suspend();
+ if (error)
+ goto Enable_cpus;
+
+ if (in_suspend) {
+ enable_nonboot_cpus();
+ platform_finish();
+ device_resume();
+ resume_console();
+ pr_debug("PM: writing image.\n");
+ error = swsusp_write();
+ if (!error)
+ power_down(pm_disk_mode);
+ else {
+ swsusp_free();
+ goto Thaw;
+ }
+ } else {
+ pr_debug("PM: Image restored successfully.\n");
+ }
+
+ swsusp_free();
+ Enable_cpus:
+ enable_nonboot_cpus();
+ Resume_devices:
+ platform_finish();
+ device_resume();
+ resume_console();
+ Thaw:
+ unprepare_processes();
+ return error;
+}
+
+
+/**
+ * software_resume - Resume from a saved image.
+ *
+ * Called as a late_initcall (so all devices are discovered and
+ * initialized), we call swsusp to see if we have a saved image or not.
+ * If so, we quiesce devices, the restore the saved image. We will
+ * return above (in pm_suspend_disk() ) if everything goes well.
+ * Otherwise, we fail gracefully and return to the normally
+ * scheduled program.
+ *
+ */
+
+static int software_resume(void)
+{
+ int error;
+
+ mutex_lock(&pm_mutex);
+ if (!swsusp_resume_device) {
+ if (!strlen(resume_file)) {
+ mutex_unlock(&pm_mutex);
+ return -ENOENT;
+ }
+ swsusp_resume_device = name_to_dev_t(resume_file);
+ pr_debug("swsusp: Resume From Partition %s\n", resume_file);
+ } else {
+ pr_debug("swsusp: Resume From Partition %d:%d\n",
+ MAJOR(swsusp_resume_device), MINOR(swsusp_resume_device));
+ }
+
+ if (noresume) {
+ /**
+ * FIXME: If noresume is specified, we need to find the partition
+ * and reset it back to normal swap space.
+ */
+ mutex_unlock(&pm_mutex);
+ return 0;
+ }
+
+ pr_debug("PM: Checking swsusp image.\n");
+
+ error = swsusp_check();
+ if (error)
+ goto Done;
+
+ pr_debug("PM: Preparing processes for restore.\n");
+
+ error = prepare_processes();
+ if (error) {
+ swsusp_close();
+ goto Done;
+ }
+
+ pr_debug("PM: Reading swsusp image.\n");
+
+ error = swsusp_read();
+ if (error) {
+ swsusp_free();
+ goto Thaw;
+ }
+
+ pr_debug("PM: Preparing devices for restore.\n");
+
+ error = device_suspend(PMSG_PRETHAW);
+ if (error)
+ goto Free;
+
+ error = disable_nonboot_cpus();
+ if (!error)
+ swsusp_resume();
+
+ enable_nonboot_cpus();
+ Free:
+ swsusp_free();
+ device_resume();
+ resume_console();
+ Thaw:
+ printk(KERN_ERR "PM: Restore failed, recovering.\n");
+ unprepare_processes();
+ Done:
+ /* For success case, the suspend path will release the lock */
+ mutex_unlock(&pm_mutex);
+ pr_debug("PM: Resume from disk failed.\n");
+ return 0;
+}
+
+late_initcall(software_resume);
+
+
+static const char * const pm_disk_modes[] = {
+ [PM_DISK_FIRMWARE] = "firmware",
+ [PM_DISK_PLATFORM] = "platform",
+ [PM_DISK_SHUTDOWN] = "shutdown",
+ [PM_DISK_REBOOT] = "reboot",
+ [PM_DISK_TEST] = "test",
+ [PM_DISK_TESTPROC] = "testproc",
+};
+
+/**
+ * disk - Control suspend-to-disk mode
+ *
+ * Suspend-to-disk can be handled in several ways. The greatest
+ * distinction is who writes memory to disk - the firmware or the OS.
+ * If the firmware does it, we assume that it also handles suspending
+ * the system.
+ * If the OS does it, then we have three options for putting the system
+ * to sleep - using the platform driver (e.g. ACPI or other PM registers),
+ * powering off the system or rebooting the system (for testing).
+ *
+ * The system will support either 'firmware' or 'platform', and that is
+ * known a priori (and encoded in pm_ops). But, the user may choose
+ * 'shutdown' or 'reboot' as alternatives.
+ *
+ * show() will display what the mode is currently set to.
+ * store() will accept one of
+ *
+ * 'firmware'
+ * 'platform'
+ * 'shutdown'
+ * 'reboot'
+ *
+ * It will only change to 'firmware' or 'platform' if the system
+ * supports it (as determined from pm_ops->pm_disk_mode).
+ */
+
+static ssize_t disk_show(struct subsystem * subsys, char * buf)
+{
+ return sprintf(buf, "%s\n", pm_disk_modes[pm_disk_mode]);
+}
+
+
+static ssize_t disk_store(struct subsystem * s, const char * buf, size_t n)
+{
+ int error = 0;
+ int i;
+ int len;
+ char *p;
+ suspend_disk_method_t mode = 0;
+
+ p = memchr(buf, '\n', n);
+ len = p ? p - buf : n;
+
+ mutex_lock(&pm_mutex);
+ for (i = PM_DISK_FIRMWARE; i < PM_DISK_MAX; i++) {
+ if (!strncmp(buf, pm_disk_modes[i], len)) {
+ mode = i;
+ break;
+ }
+ }
+ if (mode) {
+ if (mode == PM_DISK_SHUTDOWN || mode == PM_DISK_REBOOT ||
+ mode == PM_DISK_TEST || mode == PM_DISK_TESTPROC) {
+ pm_disk_mode = mode;
+ } else {
+ if (pm_ops && pm_ops->enter &&
+ (mode == pm_ops->pm_disk_mode))
+ pm_disk_mode = mode;
+ else
+ error = -EINVAL;
+ }
+ } else {
+ error = -EINVAL;
+ }
+
+ pr_debug("PM: suspend-to-disk mode set to '%s'\n",
+ pm_disk_modes[mode]);
+ mutex_unlock(&pm_mutex);
+ return error ? error : n;
+}
+
+power_attr(disk);
+
+static ssize_t resume_show(struct subsystem * subsys, char *buf)
+{
+ return sprintf(buf,"%d:%d\n", MAJOR(swsusp_resume_device),
+ MINOR(swsusp_resume_device));
+}
+
+static ssize_t resume_store(struct subsystem *subsys, const char *buf, size_t n)
+{
+ unsigned int maj, min;
+ dev_t res;
+ int ret = -EINVAL;
+
+ if (sscanf(buf, "%u:%u", &maj, &min) != 2)
+ goto out;
+
+ res = MKDEV(maj,min);
+ if (maj != MAJOR(res) || min != MINOR(res))
+ goto out;
+
+ mutex_lock(&pm_mutex);
+ swsusp_resume_device = res;
+ mutex_unlock(&pm_mutex);
+ printk("Attempting manual resume\n");
+ noresume = 0;
+ software_resume();
+ ret = n;
+ out:
+ return ret;
+}
+
+power_attr(resume);
+
+static ssize_t image_size_show(struct subsystem * subsys, char *buf)
+{
+ return sprintf(buf, "%lu\n", image_size);
+}
+
+static ssize_t image_size_store(struct subsystem * subsys, const char * buf, size_t n)
+{
+ unsigned long size;
+
+ if (sscanf(buf, "%lu", &size) == 1) {
+ image_size = size;
+ return n;
+ }
+
+ return -EINVAL;
+}
+
+power_attr(image_size);
+
+static struct attribute * g[] = {
+ &disk_attr.attr,
+ &resume_attr.attr,
+ &image_size_attr.attr,
+ NULL,
+};
+
+
+static struct attribute_group attr_group = {
+ .attrs = g,
+};
+
+
+static int __init pm_disk_init(void)
+{
+ return sysfs_create_group(&power_subsys.kset.kobj,&attr_group);
+}
+
+core_initcall(pm_disk_init);
+
+
+static int __init resume_setup(char *str)
+{
+ if (noresume)
+ return 1;
+
+ strncpy( resume_file, str, 255 );
+ return 1;
+}
+
+static int __init resume_offset_setup(char *str)
+{
+ unsigned long long offset;
+
+ if (noresume)
+ return 1;
+
+ if (sscanf(str, "%llu", &offset) == 1)
+ swsusp_resume_block = offset;
+
+ return 1;
+}
+
+static int __init noresume_setup(char *str)
+{
+ noresume = 1;
+ return 1;
+}
+
+__setup("noresume", noresume_setup);
+__setup("resume_offset=", resume_offset_setup);
+__setup("resume=", resume_setup);
Added: branches/ruby-2.6.21/ruby-2.6/kernel/power/main.c
===================================================================
--- branches/ruby-2.6.21/ruby-2.6/kernel/power/main.c (rev 0)
+++ branches/ruby-2.6.21/ruby-2.6/kernel/power/main.c 2007-04-15 14:13:12 UTC (rev 2376)
@@ -0,0 +1,338 @@
+/*
+ * kernel/power/main.c - PM subsystem core functionality.
+ *
+ * Copyright (c) 2003 Patrick Mochel
+ * Copyright (c) 2003 Open Source Development Lab
+ *
+ * This file is released under the GPLv2
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/suspend.h>
+#include <linux/kobject.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/pm.h>
+#include <linux/console.h>
+#include <linux/cpu.h>
+#include <linux/resume-trace.h>
+#include <linux/freezer.h>
+#include <linux/vmstat.h>
+
+#include "power.h"
+
+/*This is just an arbitrary number */
+#define FREE_PAGE_NUMBER (100)
+
+DEFINE_MUTEX(pm_mutex);
+
+struct pm_ops *pm_ops;
+suspend_disk_method_t pm_disk_mode = PM_DISK_PLATFORM;
+
+/**
+ * pm_set_ops - Set the global power method table.
+ * @ops: Pointer to ops structure.
+ */
+
+void pm_set_ops(struct pm_ops * ops)
+{
+ mutex_lock(&pm_mutex);
+ pm_ops = ops;
+ mutex_unlock(&pm_mutex);
+}
+
+static inline void pm_finish(suspend_state_t state)
+{
+ if (pm_ops->finish)
+ pm_ops->finish(state);
+}
+
+/**
+ * suspend_prepare - Do prep work before entering low-power state.
+ * @state: State we're entering.
+ *
+ * This is common code that is called for each state that we're
+ * entering. Allocate a console, stop all processes, then make sure
+ * the platform can enter the requested state.
+ */
+
+static int suspend_prepare(suspend_state_t state)
+{
+ int error;
+ unsigned int free_pages;
+
+ if (!pm_ops || !pm_ops->enter)
+ return -EPERM;
+
+ if (freeze_processes()) {
+ error = -EAGAIN;
+ goto Thaw;
+ }
+
+ if ((free_pages = global_page_state(NR_FREE_PAGES))
+ < FREE_PAGE_NUMBER) {
+ pr_debug("PM: free some memory\n");
+ shrink_all_memory(FREE_PAGE_NUMBER - free_pages);
+ if (nr_free_pages() < FREE_PAGE_NUMBER) {
+ error = -ENOMEM;
+ printk(KERN_ERR "PM: No enough memory\n");
+ goto Thaw;
+ }
+ }
+
+ if (pm_ops->prepare) {
+ if ((error = pm_ops->prepare(state)))
+ goto Thaw;
+ }
+
+ error = device_suspend(PMSG_SUSPEND);
+ if (error) {
+ printk(KERN_ERR "Some devices failed to suspend\n");
+ goto Resume_devices;
+ }
+ error = disable_nonboot_cpus();
+ if (!error)
+ return 0;
+
+ enable_nonboot_cpus();
+ Resume_devices:
+ pm_finish(state);
+ device_resume();
+ resume_console();
+ Thaw:
+ thaw_processes();
+ return error;
+}
+
+
+int suspend_enter(suspend_state_t state)
+{
+ int error = 0;
+ unsigned long flags;
+
+ local_irq_save(flags);
+
+ if ((error = device_power_down(PMSG_SUSPEND))) {
+ printk(KERN_ERR "Some devices failed to power down\n");
+ goto Done;
+ }
+ error = pm_ops->enter(state);
+ device_power_up();
+ Done:
+ local_irq_restore(flags);
+ return error;
+}
+
+
+/**
+ * suspend_finish - Do final work before exiting suspend sequence.
+ * @state: State we're coming out of.
+ *
+ * Call platform code to clean up, restart processes, and free the
+ * console that we've allocated. This is not called for suspend-to-disk.
+ */
+
+static void suspend_finish(suspend_state_t state)
+{
+ enable_nonboot_cpus();
+ pm_finish(state);
+ device_resume();
+ resume_console();
+ thaw_processes();
+}
+
+
+
+
+static const char * const pm_states[PM_SUSPEND_MAX] = {
+ [PM_SUSPEND_STANDBY] = "standby",
+ [PM_SUSPEND_MEM] = "mem",
+#ifdef CONFIG_SOFTWARE_SUSPEND
+ [PM_SUSPEND_DISK] = "disk",
+#endif
+};
+
+static inline int valid_state(suspend_state_t state)
+{
+ /* Suspend-to-disk does not really need low-level support.
+ * It can work with reboot if needed. */
+ if (state == PM_SUSPEND_DISK)
+ return 1;
+
+ /* all other states need lowlevel support and need to be
+ * valid to the lowlevel implementation, no valid callback
+ * implies that all are valid. */
+ if (!pm_ops || (pm_ops->valid && !pm_ops->valid(state)))
+ return 0;
+ return 1;
+}
+
+
+/**
+ * enter_state - Do common work of entering low-power state.
+ * @state: pm_state structure for state we're entering.
+ *
+ * Make sure we're the only ones trying to enter a sleep state. Fail
+ * if someone has beat us to it, since we don't want anything weird to
+ * happen when we wake up.
+ * Then, do the setup for suspend, enter the state, and cleaup (after
+ * we've woken up).
+ */
+
+static int enter_state(suspend_state_t state)
+{
+ int error;
+
+ if (!valid_state(state))
+ return -ENODEV;
+ if (!mutex_trylock(&pm_mutex))
+ return -EBUSY;
+
+ if (state == PM_SUSPEND_DISK) {
+ error = pm_suspend_disk();
+ goto Unlock;
+ }
+
+ pr_debug("PM: Preparing system for %s sleep\n", pm_states[state]);
+ if ((error = suspend_prepare(state)))
+ goto Unlock;
+
+ pr_debug("PM: Entering %s sleep\n", pm_states[state]);
+ error = suspend_enter(state);
+
+ pr_debug("PM: Finishing wakeup.\n");
+ suspend_finish(state);
+ Unlock:
+ mutex_unlock(&pm_mutex);
+ return error;
+}
+
+/*
+ * This is main interface to the outside world. It needs to be
+ * called from process context.
+ */
+int software_suspend(void)
+{
+ return enter_state(PM_SUSPEND_DISK);
+}
+
+
+/**
+ * pm_suspend - Externally visible function for suspending system.
+ * @state: Enumarted value of state to enter.
+ *
+ * Determine whether or not value is within range, get state
+ * structure, and enter (above).
+ */
+
+int pm_suspend(suspend_state_t state)
+{
+ if (state > PM_SUSPEND_ON && state <= PM_SUSPEND_MAX)
+ return enter_state(state);
+ return -EINVAL;
+}
+
+EXPORT_SYMBOL(pm_suspend);
+
+decl_subsys(power,NULL,NULL);
+
+
+/**
+ * state - control system power state.
+ *
+ * show() returns what states are supported, which is hard-coded to
+ * 'standby' (Power-On Suspend), 'mem' (Suspend-to-RAM), and
+ * 'disk' (Suspend-to-Disk).
+ *
+ * store() accepts one of those strings, translates it into the
+ * proper enumerated value, and initiates a suspend transition.
+ */
+
+static ssize_t state_show(struct subsystem * subsys, char * buf)
+{
+ int i;
+ char * s = buf;
+
+ for (i = 0; i < PM_SUSPEND_MAX; i++) {
+ if (pm_states[i] && valid_state(i))
+ s += sprintf(s,"%s ", pm_states[i]);
+ }
+ s += sprintf(s,"\n");
+ return (s - buf);
+}
+
+static ssize_t state_store(struct subsystem * subsys, const char * buf, size_t n)
+{
+ suspend_state_t state = PM_SUSPEND_STANDBY;
+ const char * const *s;
+ char *p;
+ int error;
+ int len;
+
+ p = memchr(buf, '\n', n);
+ len = p ? p - buf : n;
+
+ for (s = &pm_states[state]; state < PM_SUSPEND_MAX; s++, state++) {
+ if (*s && !strncmp(buf, *s, len))
+ break;
+ }
+ if (state < PM_SUSPEND_MAX && *s)
+ error = enter_state(state);
+ else
+ error = -EINVAL;
+ return error ? error : n;
+}
+
+power_attr(state);
+
+#ifdef CONFIG_PM_TRACE
+int pm_trace_enabled;
+
+static ssize_t pm_trace_show(struct subsystem * subsys, char * buf)
+{
+ return sprintf(buf, "%d\n", pm_trace_enabled);
+}
+
+static ssize_t
+pm_trace_store(struct subsystem * subsys, const char * buf, size_t n)
+{
+ int val;
+
+ if (sscanf(buf, "%d", &val) == 1) {
+ pm_trace_enabled = !!val;
+ return n;
+ }
+ return -EINVAL;
+}
+
+power_attr(pm_trace);
+
+static struct attribute * g[] = {
+ &state_attr.attr,
+ &pm_trace_attr.attr,
+ NULL,
+};
+#else
+static struct attribute * g[] = {
+ &state_attr.attr,
+ NULL,
+};
+#endif /* CONFIG_PM_TRACE */
+
+static struct attribute_group attr_group = {
+ .attrs = g,
+};
+
+
+static int __init pm_init(void)
+{
+ int error = subsystem_register(&power_subsys);
+ if (!error)
+ error = sysfs_create_group(&power_subsys.kset.kobj,&attr_group);
+ return error;
+}
+
+core_initcall(pm_init);
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <jsi...@us...> - 2007-04-15 01:06:31
|
Revision: 2375
http://linuxconsole.svn.sourceforge.net/linuxconsole/?rev=2375&view=rev
Author: jsimmons
Date: 2007-04-14 18:06:27 -0700 (Sat, 14 Apr 2007)
Log Message:
-----------
update to 2.6.21
Modified Paths:
--------------
branches/ruby-2.6.21/ruby-2.6/drivers/char/Kconfig
Modified: branches/ruby-2.6.21/ruby-2.6/drivers/char/Kconfig
===================================================================
--- branches/ruby-2.6.21/ruby-2.6/drivers/char/Kconfig 2007-04-15 00:52:34 UTC (rev 2374)
+++ branches/ruby-2.6.21/ruby-2.6/drivers/char/Kconfig 2007-04-15 01:06:27 UTC (rev 2375)
@@ -69,6 +69,23 @@
depends on VT && !S390 && !UML
default y
+config VT_HW_CONSOLE_BINDING
+ bool "Support for binding and unbinding console drivers"
+ depends on HW_CONSOLE
+ default n
+ ---help---
+ The virtual terminal is the device that interacts with the physical
+ terminal through console drivers. On these systems, at least one
+ console driver is loaded. In other configurations, additional console
+ drivers may be enabled, such as the framebuffer console. If more than
+ 1 console driver is enabled, setting this to 'y' will allow you to
+ select the console driver that will serve as the backend for the
+ virtual terminals.
+
+ See <file:Documentation/console/console.txt> for more
+ information. For framebuffer console users, please refer to
+ <file:Documentation/fb/fbcon.txt>.
+
config SERIAL_NONSTANDARD
bool "Non-standard serial port support"
---help---
@@ -87,7 +104,7 @@
config COMPUTONE
tristate "Computone IntelliPort Plus serial support"
- depends on SERIAL_NONSTANDARD && BROKEN_ON_SMP
+ depends on SERIAL_NONSTANDARD && (ISA || EISA || PCI)
---help---
This driver supports the entire family of Intelliport II/Plus
controllers with the exception of the MicroChannel controllers and
@@ -145,7 +162,7 @@
config DIGIEPCA
tristate "Digiboard Intelligent Async Support"
- depends on SERIAL_NONSTANDARD && BROKEN_ON_SMP
+ depends on SERIAL_NONSTANDARD
---help---
This is a driver for Digi International's Xx, Xeve, and Xem series
of cards which provide multiple serial ports. You would need
@@ -160,7 +177,7 @@
config ESPSERIAL
tristate "Hayes ESP serial port support"
- depends on SERIAL_NONSTANDARD && ISA && BROKEN_ON_SMP && ISA_DMA_API
+ depends on SERIAL_NONSTANDARD && ISA && ISA_DMA_API
help
This is a driver which supports Hayes ESP serial ports. Both single
port cards and multiport cards are supported. Make sure to read
@@ -173,7 +190,7 @@
config MOXA_INTELLIO
tristate "Moxa Intellio support"
- depends on SERIAL_NONSTANDARD && BROKEN_ON_SMP
+ depends on SERIAL_NONSTANDARD
help
Say Y here if you have a Moxa Intellio multiport serial card.
@@ -181,7 +198,7 @@
module will be called moxa.
config MOXA_SMARTIO
- tristate "Moxa SmartIO support"
+ tristate "Moxa SmartIO support (OBSOLETE)"
depends on SERIAL_NONSTANDARD
help
Say Y here if you have a Moxa SmartIO multiport serial card.
@@ -191,9 +208,25 @@
The module will be called mxser. If you want to do that, say M
here.
+config MOXA_SMARTIO_NEW
+ tristate "Moxa SmartIO support v. 2.0"
+ depends on SERIAL_NONSTANDARD && (PCI || EISA || ISA)
+ help
+ Say Y here if you have a Moxa SmartIO multiport serial card and/or
+ want to help develop a new version of this driver.
+
+ This is upgraded (1.9.1) driver from original Moxa drivers with
+ changes finally resulting in PCI probing.
+
+ Use at your own risk.
+
+ This driver can also be built as a module. The module will be called
+ mxser_new. If you want to do that, say M here.
+
config ISI
tristate "Multi-Tech multiport card support (EXPERIMENTAL)"
- depends on SERIAL_NONSTANDARD
+ depends on SERIAL_NONSTANDARD && PCI
+ select FW_LOADER
help
This is a driver for the Multi-Tech cards which provide several
serial ports. The driver is experimental and can currently only be
@@ -227,6 +260,14 @@
The module will be called synclinkmp. If you want to do that, say M
here.
+config SYNCLINK_GT
+ tristate "SyncLink GT/AC support"
+ depends on SERIAL_NONSTANDARD && PCI
+ help
+ Support for SyncLink GT and SyncLink AC families of
+ synchronous and asynchronous serial adapters
+ manufactured by Microgate Systems, Ltd. (www.microgate.com)
+
config N_HDLC
tristate "HDLC line discipline support"
depends on SERIAL_NONSTANDARD
@@ -278,7 +319,7 @@
config SX
tristate "Specialix SX (and SI) card support"
- depends on SERIAL_NONSTANDARD
+ depends on SERIAL_NONSTANDARD && (PCI || EISA || ISA)
help
This is a driver for the SX and SI multiport serial cards.
Please read the file <file:Documentation/sx.txt> for details.
@@ -289,7 +330,7 @@
config RIO
tristate "Specialix RIO system support"
- depends on SERIAL_NONSTANDARD && BROKEN_ON_SMP
+ depends on SERIAL_NONSTANDARD
help
This is a driver for the Specialix RIO, a smart serial card which
drives an outboard box that can support up to 128 ports. Product
@@ -352,35 +393,38 @@
If you have an Alchemy AU1000 processor (MIPS based) and you want
to use a console on a serial port, say Y. Otherwise, say N.
-config QTRONIX_KEYBOARD
- bool "Enable Qtronix 990P Keyboard Support"
- depends on IT8712
+config SERIAL_DEC
+ bool "DECstation serial support"
+ depends on MACH_DECSTATION
+ default y
help
- Images of Qtronix keyboards are at
- <http://www.qtronix.com/keyboard.html>.
+ This selects whether you want to be asked about drivers for
+ DECstation serial ports.
-config IT8172_CIR
- bool
- depends on QTRONIX_KEYBOARD
+ Note that the answer to this question won't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about DECstation serial ports.
+
+config SERIAL_DEC_CONSOLE
+ bool "Support for console on a DECstation serial port"
+ depends on SERIAL_DEC
default y
-
-config IT8172_SCR0
- bool "Enable Smart Card Reader 0 Support "
- depends on IT8712
help
- Say Y here to support smart-card reader 0 (SCR0) on the Integrated
- Technology Express, Inc. ITE8172 SBC. Vendor page at
- <http://www.ite.com.tw/ia/brief_it8172bsp.htm>; picture of the
- board at <http://www.mvista.com/partners/semiconductor/ite.html>.
+ If you say Y here, it will be possible to use a serial port as the
+ system console (the system console is the device which receives all
+ kernel messages and warnings and which allows logins in single user
+ mode). Note that the firmware uses ttyS0 as the serial console on
+ the Maxine and ttyS2 on the others.
-config IT8172_SCR1
- bool "Enable Smart Card Reader 1 Support "
- depends on IT8712
+ If unsure, say Y.
+
+config ZS
+ bool "Z85C30 Serial Support"
+ depends on SERIAL_DEC
+ default y
help
- Say Y here to support smart-card reader 1 (SCR1) on the Integrated
- Technology Express, Inc. ITE8172 SBC. Vendor page at
- <http://www.ite.com.tw/ia/brief_it8172bsp.htm>; picture of the
- board at <http://www.mvista.com/partners/semiconductor/ite.html>.
+ Documentation on the Zilog 85C350 serial communications controller
+ is downloadable at <http://www.zilog.com/pdfs/serial/z85c30.pdf>
config A2232
tristate "Commodore A2232 serial support (EXPERIMENTAL)"
@@ -476,6 +520,21 @@
When not in use, each legacy PTY occupies 12 bytes on 32-bit
architectures and 24 bytes on 64-bit architectures.
+config BRIQ_PANEL
+ tristate 'Total Impact briQ front panel driver'
+ depends on PPC_CHRP
+ ---help---
+ The briQ is a small footprint CHRP computer with a frontpanel VFD, a
+ tristate led and two switches. It is the size of a CDROM drive.
+
+ If you have such one and want anything showing on the VFD then you
+ must answer Y here.
+
+ To compile this driver as a module, choose M here: the
+ module will be called briq_panel.
+
+ It's safe to say N here.
+
config PRINTER
tristate "Parallel printer support"
depends on PARPORT
@@ -559,14 +618,45 @@
If unsure, say N.
+config HVC_DRIVER
+ bool
+ help
+ Users of pSeries machines that want to utilize the hvc console front-end
+ module for their backend console driver should select this option.
+ It will automatically be selected if one of the back-end console drivers
+ is selected.
+
+
config HVC_CONSOLE
bool "pSeries Hypervisor Virtual Console support"
depends on PPC_PSERIES
+ select HVC_DRIVER
help
pSeries machines when partitioned support a hypervisor virtual
console. This driver allows each pSeries partition to have a console
which is accessed via the HMC.
+config HVC_ISERIES
+ bool "iSeries Hypervisor Virtual Console support"
+ depends on PPC_ISERIES && !VIOCONS
+ select HVC_DRIVER
+ help
+ iSeries machines support a hypervisor virtual console.
+
+config HVC_RTAS
+ bool "IBM RTAS Console support"
+ depends on PPC_RTAS
+ select HVC_DRIVER
+ help
+ IBM Console device driver which makes use of RTAS
+
+config HVC_BEAT
+ bool "Toshiba's Beat Hypervisor Console support"
+ depends on PPC_CELLEB
+ select HVC_DRIVER
+ help
+ Toshiba's Cell Reference Set Beat Console device driver
+
config HVCS
tristate "IBM Hypervisor Virtual Console Server support"
depends on PPC_PSERIES
@@ -651,24 +741,11 @@
If you're not sure, say N.
-config HW_RANDOM
- tristate "Intel/AMD/VIA HW Random Number Generator support"
- depends on (X86 || IA64) && PCI
- ---help---
- This driver provides kernel-side support for the Random Number
- Generator hardware found on Intel i8xx-based motherboards,
- AMD 76x-based motherboards, and Via Nehemiah CPUs.
+source "drivers/char/hw_random/Kconfig"
- Provides a character driver, used to read() entropy data.
-
- To compile this driver as a module, choose M here: the
- module will be called hw_random.
-
- If unsure, say N.
-
config NVRAM
tristate "/dev/nvram support"
- depends on ATARI || X86 || X86_64 || ARM || GENERIC_NVRAM
+ depends on ATARI || X86 || ARM || GENERIC_NVRAM
---help---
If you say Y here and create a character special file /dev/nvram
with major number 10 and minor number 144 using mknod ("man mknod"),
@@ -694,7 +771,7 @@
config RTC
tristate "Enhanced Real Time Clock Support"
- depends on !PPC32 && !PARISC && !IA64 && !M68K
+ depends on !PPC && !PARISC && !IA64 && !M68K && (!SPARC || PCI) && !FRV && !ARM && !SUPERH
---help---
If you say Y here and create a character special file /dev/rtc with
major number 10 and minor number 135 using mknod ("man mknod"), you
@@ -742,7 +819,7 @@
config GEN_RTC
tristate "Generic /dev/rtc emulation"
- depends on RTC!=y && !IA64 && !ARM
+ depends on RTC!=y && !IA64 && !ARM && !M32R && !SPARC && !FRV
---help---
If you say Y here and create a character special file /dev/rtc with
major number 10 and minor number 135 using mknod ("man mknod"), you
@@ -778,18 +855,6 @@
will get access to the real time clock (or hardware clock) built
into your computer.
-config S3C2410_RTC
- bool "S3C2410 RTC Driver"
- depends on ARCH_S3C2410
- help
- RTC (Realtime Clock) driver for the clock inbuilt into the
- Samsung S3C2410. This can provide periodic interrupt rates
- from 1Hz to 64Hz for user programs, and wakeup from Alarm.
-
-config RTC_VR41XX
- tristate "NEC VR4100 series Real Time Clock Support"
- depends on CPU_VR41XX
-
config COBALT_LCD
bool "Support for Cobalt LCD"
depends on MIPS_COBALT
@@ -849,52 +914,9 @@
config TANBAC_TB0219
tristate "TANBAC TB0219 base board support"
- depends TANBAC_TB0229
+ depends on TANBAC_TB022X
+ select GPIO_VR41XX
-
-menu "Ftape, the floppy tape device driver"
-
-config FTAPE
- tristate "Ftape (QIC-80/Travan) support"
- depends on BROKEN_ON_SMP && (ALPHA || X86)
- ---help---
- If you have a tape drive that is connected to your floppy
- controller, say Y here.
-
- Some tape drives (like the Seagate "Tape Store 3200" or the Iomega
- "Ditto 3200" or the Exabyte "Eagle TR-3") come with a "high speed"
- controller of their own. These drives (and their companion
- controllers) are also supported if you say Y here.
-
- If you have a special controller (such as the CMS FC-10, FC-20,
- Mountain Mach-II, or any controller that is based on the Intel 82078
- FDC like the high speed controllers by Seagate and Exabyte and
- Iomega's "Ditto Dash") you must configure it by selecting the
- appropriate entries from the "Floppy tape controllers" sub-menu
- below and possibly modify the default values for the IRQ and DMA
- channel and the IO base in ftape's configuration menu.
-
- If you want to use your floppy tape drive on a PCI-bus based system,
- please read the file <file:drivers/char/ftape/README.PCI>.
-
- The ftape kernel driver is also available as a runtime loadable
- module. To compile this driver as a module, choose M here: the
- module will be called ftape.
-
- Note that the Ftape-HOWTO is out of date (sorry) and documents the
- older version 2.08 of this software but still contains useful
- information. There is a web page with more recent documentation at
- <http://www.instmath.rwth-aachen.de/~heine/ftape/>. This page
- always contains the latest release of the ftape driver and useful
- information (backup software, ftape related patches and
- documentation, FAQ). Note that the file system interface has
- changed quite a bit compared to previous versions of ftape. Please
- read <file:Documentation/ftape.txt>.
-
-source "drivers/char/ftape/Kconfig"
-
-endmenu
-
source "drivers/char/agp/Kconfig"
source "drivers/char/drm/Kconfig"
@@ -930,23 +952,70 @@
config SCx200_GPIO
tristate "NatSemi SCx200 GPIO Support"
depends on SCx200
+ select NSC_GPIO
help
Give userspace access to the GPIO pins on the National
Semiconductor SCx200 processors.
If compiled as a module, it will be called scx200_gpio.
+config PC8736x_GPIO
+ tristate "NatSemi PC8736x GPIO Support"
+ depends on X86
+ default SCx200_GPIO # mostly N
+ select NSC_GPIO # needed for support routines
+ help
+ Give userspace access to the GPIO pins on the National
+ Semiconductor PC-8736x (x=[03456]) SuperIO chip. The chip
+ has multiple functional units, inc several managed by
+ hwmon/pc87360 driver. Tested with PC-87366
+
+ If compiled as a module, it will be called pc8736x_gpio.
+
+config NSC_GPIO
+ tristate "NatSemi Base GPIO Support"
+ depends on X86_32
+ # selected by SCx200_GPIO and PC8736x_GPIO
+ # what about 2 selectors differing: m != y
+ help
+ Common support used (and needed) by scx200_gpio and
+ pc8736x_gpio drivers. If those drivers are built as
+ modules, this one will be too, named nsc_gpio
+
+config CS5535_GPIO
+ tristate "AMD CS5535/CS5536 GPIO (Geode Companion Device)"
+ depends on X86_32
+ help
+ Give userspace access to the GPIO pins on the AMD CS5535 and
+ CS5536 Geode companion devices.
+
+ If compiled as a module, it will be called cs5535_gpio.
+
+config GPIO_VR41XX
+ tristate "NEC VR4100 series General-purpose I/O Unit support"
+ depends on CPU_VR41XX
+
config RAW_DRIVER
tristate "RAW driver (/dev/raw/rawN) (OBSOLETE)"
+ depends on BLOCK
help
The raw driver permits block devices to be bound to /dev/raw/rawN.
Once bound, I/O against /dev/raw/rawN uses efficient zero-copy I/O.
See the raw(8) manpage for more details.
- The raw driver is deprecated and may be removed from 2.7
- kernels. Applications should simply open the device (eg /dev/hda1)
+ The raw driver is deprecated and will be removed soon.
+ Applications should simply open the device (eg /dev/hda1)
with the O_DIRECT flag.
+config MAX_RAW_DEVS
+ int "Maximum number of RAW devices to support (1-8192)"
+ depends on RAW_DRIVER
+ default "256"
+ help
+ The maximum number of RAW devices that are supported.
+ Default is 256. Increase this number in case you need lots of
+ raw devices.
+
config HPET
bool "HPET - High Precision Event Timer" if (X86 || IA64)
default n
@@ -954,7 +1023,7 @@
help
If you say Y here, you will have a miscdevice named "/dev/hpet/". Each
open selects one of the timers supported by the HPET. The timers are
- non-periodioc and/or periodic.
+ non-periodic and/or periodic.
config HPET_RTC_IRQ
bool "HPET Control RTC IRQ" if !HPET_EMULATE_RTC
@@ -978,18 +1047,9 @@
exposed to the user. If this applies to your hardware,
say N here.
-config MAX_RAW_DEVS
- int "Maximum number of RAW devices to support (1-8192)"
- depends on RAW_DRIVER
- default "256"
- help
- The maximum number of RAW devices that are supported.
- Default is 256. Increase this number in case you need lots of
- raw devices.
-
config HANGCHECK_TIMER
tristate "Hangcheck timer"
- depends on X86_64 || X86 || IA64 || PPC64 || ARCH_S390
+ depends on X86 || IA64 || PPC64
help
The hangcheck-timer module detects when the system has gone
out to lunch past a certain margin. It can reboot the system
@@ -1005,5 +1065,18 @@
source "drivers/char/tpm/Kconfig"
+config TELCLOCK
+ tristate "Telecom clock driver for ATCA SBC"
+ depends on EXPERIMENTAL && X86
+ default n
+ help
+ The telecom clock device is specific to the MPCBL0010 and MPCBL0050
+ ATCA computers and allows direct userspace access to the
+ configuration of the telecom clock configuration settings. This
+ device is used for hardware synchronization across the ATCA backplane
+ fabric. Upon loading, the driver exports a sysfs directory,
+ /sys/devices/platform/telco_clock, with a number of files for
+ controlling the behavior of this hardware.
+
endmenu
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <jsi...@us...> - 2007-04-15 00:52:36
|
Revision: 2374
http://linuxconsole.svn.sourceforge.net/linuxconsole/?rev=2374&view=rev
Author: jsimmons
Date: 2007-04-14 17:52:34 -0700 (Sat, 14 Apr 2007)
Log Message:
-----------
Parital merged with VT sysfs code
Modified Paths:
--------------
branches/ruby-2.6.21/ruby-2.6/drivers/char/vt_sysfs.c
Modified: branches/ruby-2.6.21/ruby-2.6/drivers/char/vt_sysfs.c
===================================================================
--- branches/ruby-2.6.21/ruby-2.6/drivers/char/vt_sysfs.c 2007-04-14 23:31:33 UTC (rev 2373)
+++ branches/ruby-2.6.21/ruby-2.6/drivers/char/vt_sysfs.c 2007-04-15 00:52:34 UTC (rev 2374)
@@ -10,61 +10,105 @@
#include <linux/vt_kern.h>
#include <linux/input.h>
-/* show configuration fields */
-#define vt_config_attr(field, format_string) \
-static ssize_t \
-vt_show_##field (struct class_device *dev, char *buf) \
-{ \
- struct vt_struct *vt; \
- \
- vt = to_vt_struct (dev); \
- return sprintf (buf, format_string, vt->field); \
-} \
-static CLASS_DEVICE_ATTR(field, S_IRUGO, vt_show_##field, NULL);
+static struct class *vt_class;
-struct class vt_class = {
- .name = "vt",
-};
+//vt_config_attr(first_vc, "%d\n");
+//vt_config_attr(vc_count, "%d\n");
-vt_config_attr(display_desc, "%s\n");
-vt_config_attr(first_vc, "%d\n");
-vt_config_attr(vc_count, "%d\n");
+static inline int vt_bind(struct vt_struct *vt)
+{
+ return 0;
+}
+static inline int vt_unbind(struct vt_struct *vt)
+{
+ return 0;
+}
-static ssize_t
-vt_show_keyboard (struct class_device *dev, char *buf)
+static ssize_t show_keyboard(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
{
- struct vt_struct *vt;
- struct input_handle *handle;
+ struct vt_struct *vt = dev_get_drvdata(dev);
+ struct input_handle *handle = vt->keyboard;
- vt = to_vt_struct (dev);
- handle = vt->keyboard;
if (handle && handle->dev->phys)
return sprintf (buf, "%s\n", handle->dev->phys);
return sprintf (buf, "%s\n", "");
}
-static CLASS_DEVICE_ATTR(keyboard, S_IRUGO, vt_show_keyboard, NULL);
-int __init vt_create_sysfs_dev_files (struct vt_struct *vt)
+static ssize_t store_bind(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
{
- struct class_device *dev = &vt->dev;
+ struct vt_struct *vt = dev_get_drvdata(dev);
+ int bind = simple_strtoul(buf, NULL, 0);
- dev->class = &vt_class;
- sprintf (dev->class_id, "%02x", vt->vt_num);
- class_device_register(dev);
+ if (bind)
+ vt_bind(vt);
+ else
+ vt_unbind(con);
+ return count;
+}
- /* current configuration's attributes */
- class_device_create_file (dev, &class_device_attr_display_desc);
- class_device_create_file (dev, &class_device_attr_first_vc);
- class_device_create_file (dev, &class_device_attr_vc_count);
- class_device_create_file (dev, &class_device_attr_keyboard);
+static ssize_t show_bind(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct vt_struct *vt = dev_get_drvdata(dev);
+ int bind = (vt->vt_sw != NULL) ? 1 : 0;
- return 0;
+ return snprintf(buf, PAGE_SIZE, "%i\n", bind);
}
+static ssize_t show_name(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct vt_struct *vt = dev_get_drvdata(dev);
+
+ return snprintf(buf, PAGE_SIZE, "%s %s\n",
+ (vt->flag & CON_DRIVER_FLAG_MODULE) ? "(M)" : "(S)",
+ vt->desc);
+}
+
+static struct device_attribute vt_device_attrs[] = {
+ __ATTR(bind, S_IRUGO|S_IWUSR, show_bind, store_bind),
+ __ATTR(keyboard, S_IRUGO, show_keyboard, NULL),
+ __ATTR(name, S_IRUGO, show_name, NULL),
+};
+
+static int vt_init_device(struct vt_struct *vt)
+{
+ int err = 0;
+
+ vt->dev = device_create(vt_class, NULL, MKDEV(0, vt->count),
+ "vtcon%i", vt->count);
+ if (IS_ERR(vt->dev)) {
+ vt->flag &= ~CON_DRIVER_FLAG_ATTR;
+ vt->dev = NULL;
+ error = -EINVAL;
+ } else {
+ dev_set_drvdata(vt->dev, vt);
+ fb_info->flag |= CON_DRIVER_FLAG_ATTR;
+ }
+ return err;
+}
+
+static void vt_deinit_device(struct vt_struct *vt)
+{
+ vt->flag &= ~CON_DRIVER_FLAG_ATTR;
+ dev_set_drvdata(vt->dev, NULL);
+ device_destroy(vt_class, MKDEV(0, vt->count));
+}
+
void __init vt_sysfs_init(void)
{
/* we have only one boot time console - admin_vt*/
- class_register(&vt_class);
- vt_create_sysfs_dev_files(admin_vt);
+ vt_class = class_create(THIS_MODULE, "vt");
+ if (IS_ERR(vt_class)) {
+ printk(KERN_WARNING "Unable to create vt console class; "
+ "errno = %ld\n", PTR_ERR(vtconsole_class));
+ vt_class = NULL;
+ } else {
+ vt_class->dev_attrs = vt_device_attrs
+ }
}
+
+postcore_initcall(vtconsole_class_init);
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <jsi...@us...> - 2007-04-14 23:31:35
|
Revision: 2373
http://linuxconsole.svn.sourceforge.net/linuxconsole/?rev=2373&view=rev
Author: jsimmons
Date: 2007-04-14 16:31:33 -0700 (Sat, 14 Apr 2007)
Log Message:
-----------
merged to 2.6.21. Missing the new sysfs. Need to merge to what we have
Modified Paths:
--------------
branches/ruby-2.6.21/ruby-2.6/drivers/char/vc_screen.c
branches/ruby-2.6.21/ruby-2.6/drivers/char/vt.c
branches/ruby-2.6.21/ruby-2.6/drivers/char/vt_ioctl.c
Modified: branches/ruby-2.6.21/ruby-2.6/drivers/char/vc_screen.c
===================================================================
--- branches/ruby-2.6.21/ruby-2.6/drivers/char/vc_screen.c 2007-04-11 20:19:34 UTC (rev 2372)
+++ branches/ruby-2.6.21/ruby-2.6/drivers/char/vc_screen.c 2007-04-14 23:31:33 UTC (rev 2373)
@@ -52,6 +52,7 @@
void putconsxy(struct vc_data *vc, unsigned char *p)
{
+ hide_cursor(vc);
gotoxy(vc, p[0], p[1]);
set_cursor(vc);
}
Modified: branches/ruby-2.6.21/ruby-2.6/drivers/char/vt.c
===================================================================
--- branches/ruby-2.6.21/ruby-2.6/drivers/char/vt.c 2007-04-11 20:19:34 UTC (rev 2372)
+++ branches/ruby-2.6.21/ruby-2.6/drivers/char/vt.c 2007-04-14 23:31:33 UTC (rev 2373)
@@ -72,6 +72,13 @@
*
* Removed console_lock, enabled interrupts across all console operations
* 13 March 2001, Andrew Morton
+ *
+ * Fixed UTF-8 mode so alternate charset modes always work according
+ * to control sequences interpreted in do_con_trol function
+ * preserving backward VT100 semigraphics compatibility,
+ * malformed UTF sequences represented as sequences of replacement glyphs,
+ * original codes or '?' as a last resort if replacement glyph is undefined
+ * by Adam Tla/lka <at...@pg...>, Aug 2006
*/
#include <linux/module.h>
@@ -87,14 +94,12 @@
#include <linux/mm.h>
#include <linux/console.h>
#include <linux/init.h>
-#include <linux/devfs_fs_kernel.h>
#include <linux/vt_kern.h>
#include <linux/selection.h>
#include <linux/tiocl.h>
#include <linux/consolemap.h>
#include <linux/timer.h>
#include <linux/interrupt.h>
-#include <linux/config.h>
#include <linux/workqueue.h>
#include <linux/bootmem.h>
#include <linux/pm.h>
@@ -113,8 +118,6 @@
#define CTRL_ACTION 0x0d00ff81
#define CTRL_ALWAYS 0x0800f501 /* Cannot be overridden by disp_ctrl */
-extern void vcs_make_devfs(struct tty_struct *tty);
-extern void vcs_remove_devfs(struct tty_struct *tty);
extern void console_map_init(void);
#ifdef CONFIG_VGA_CONSOLE
@@ -677,19 +680,24 @@
void complement_pos(struct vc_data *vc, int offset)
{
static unsigned short oldx, oldy, old;
- static unsigned short *p;
+ static int old_offset = -1;
WARN_CONSOLE_UNLOCKED();
- if (p) {
- scr_writew(old, p);
+ if (old_offset != -1 && old_offset >= 0 &&
+ old_offset < vc->vc_screenbuf_size) {
+ scr_writew(old, screenpos(vc, old_offset, 1));
if (DO_UPDATE)
sw->con_putc(vc, old, oldy, oldx);
}
- if (offset == -1)
- p = NULL;
- else {
+
+ old_offset = offset;
+
+ if (offset != -1 && offset >= 0 &&
+ offset < vc->vc_screenbuf_size) {
unsigned short new;
+ unsigned short *p;
+
p = screenpos(vc, offset, 1);
old = scr_readw(p);
new = old ^ vc->vc_complement_mask;
@@ -738,7 +746,7 @@
if (vt->vt_blanked) {
if (vt->blank_state == blank_vesa_wait) {
vt->blank_state = blank_off;
- powerdown_screen((unsigned long)vt);
+ vc->vc_sw->con_blank(vc, vesa_blank_mode + 1, 0);
}
return;
}
@@ -768,14 +776,14 @@
save_screen(vc);
/* In case we need to reset origin, blanking hook returns 1 */
- i = sw->con_blank(vc, 1, 0);
+ i = sw->con_blank(vc, vesa_off_interval ? 1 : (vesa_blank_mode + 1), 0);
vt->vt_blanked = 1;
if (i)
set_origin(vc);
if (console_blank_hook && console_blank_hook(1))
return;
- if (vt->off_interval) {
+ if (vt->off_interval && vt->blank_mode) {
vt->blank_state = blank_vesa_wait;
mod_timer(&vt->timer, jiffies + vt->off_interval);
}
@@ -785,9 +793,9 @@
EXPORT_SYMBOL(do_blank_screen);
/*
- * We defer the timer blanking to work queue so it can take the console semaphore
+ * We defer the timer blanking to work queue so it can take the console mutex
* (console operations can still happen at irq time, but only from printk which
- * has the console semaphore. Not perfect yet, but better than no locking
+ * has the console mutex. Not perfect yet, but better than no locking
*/
static void blank_screen_t(unsigned long dummy)
{
@@ -874,9 +882,9 @@
* with other console code and prevention of re-entrancy is
* ensured with the console semaphore.
*/
-static void vt_callback(void *private)
+static void vt_callback(struct work_struct *work)
{
- struct vt_struct *vt = (struct vt_struct *) private;
+ struct vt_struct *vt = container_of(work, struct vt_struct, SAK_work);
if (!vt || !vt->want_vc || !vt->want_vc->vc_tty)
return;
@@ -908,10 +916,24 @@
release_console_sem();
}
-inline void set_console(struct vc_data *vc)
+int set_console(struct vc_data *vc)
{
+ if (!vc || vc->display_fg->vt_dont_switch ||
+ (vc->vt_mode.mode == VT_AUTO && vc->vc_mode == KD_GRAPHICS)) {
+
+ /*
+ * Console switch will fail in console_callback() or
+ * change_console() so there is no point scheduling
+ * the callback
+ *
+ * Existing set_console() users don't check the return
+ * value so this shouldn't break anything
+ */
+ return -EINVAL;
+ }
vc->display_fg->want_vc = vc;
schedule_work(&vc->display_fg->vt_work);
+ return 0;
}
/*
@@ -1003,6 +1025,7 @@
vc->vc_num = currcons;
vc->display_fg = vt;
+ INIT_WORK(&vc->SAK_work, vc_SAK);
visual_init(vc, 1);
if (vt->kmalloced || !((vt->first_vc) == currcons)) {
vc->vc_screenbuf = (unsigned short *) kmalloc(vc->vc_screenbuf_size, GFP_KERNEL);
@@ -1029,14 +1052,26 @@
return vc;
}
-int vc_disallocate(struct vc_data *vc)
+int vc_lock_resize(struct vc_data *vc, unsigned int cols, unsigned int lines)
{
+ int rc;
+
+ acquire_console_sem();
+ rc = vc_resize(vc, cols, lines);
+ release_console_sem();
+ return rc;
+}
+
+int vc_deallocate(struct vc_data *vc)
+{
struct vt_struct *vt = vc->display_fg;
WARN_CONSOLE_UNLOCKED();
if (vc && vc->vc_num > MIN_NR_CONSOLES) {
sw->con_deinit(vc);
+ put_pid(vc->vt_pid);
+ module_put(sw->owner);
vt->vc_cons[vc->vc_num - vt->first_vc] = NULL;
if (vt->kmalloced)
kfree(screenbuf);
@@ -1071,15 +1106,16 @@
int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines)
{
- unsigned int old_cols, old_rows, old_screenbuf_size, old_row_size;
- unsigned long ol, nl, nlend, rlth, rrem;
- unsigned int new_cols, new_rows, ss, new_row_size, err = 0;
+ unsigned long old_origin, new_origin, new_scr_end, rlth, rrem, err = 0;
+ unsigned int old_cols, old_rows, old_row_size, old_screen_size;
+ unsigned int new_cols, new_rows, new_row_size, new_screen_size;
+ unsigned int end;
unsigned short *newscreen;
WARN_CONSOLE_UNLOCKED();
if (!vc)
- return 0;
+ return -ENXIO;
if (cols > VC_RESIZE_MAXCOL || lines > VC_RESIZE_MAXROW)
return -EINVAL;
@@ -1087,23 +1123,22 @@
new_cols = (cols ? cols : vc->vc_cols);
new_rows = (lines ? lines : vc->vc_rows);
new_row_size = new_cols << 1;
- ss = new_row_size * new_rows;
+ new_screen_size = new_row_size * new_rows;
if (new_cols == vc->vc_cols && new_rows == vc->vc_rows)
return 0;
- newscreen = (unsigned short *) kmalloc(ss, GFP_USER);
+ newscreen = kmalloc(new_screen_size, GFP_USER);
if (!newscreen)
return -ENOMEM;
old_rows = vc->vc_rows;
old_cols = vc->vc_cols;
old_row_size = vc->vc_size_row;
- old_screenbuf_size = vc->vc_screenbuf_size;
+ old_screen_size = vc->vc_screenbuf_size;
err = resize_screen(vc, new_cols, new_rows);
if (err) {
- resize_screen(vc, old_cols, old_rows);
kfree(newscreen);
return err;
}
@@ -1111,32 +1146,57 @@
vc->vc_rows = new_rows;
vc->vc_cols = new_cols;
vc->vc_size_row = new_row_size;
- vc->vc_screenbuf_size = ss;
+ vc->vc_screenbuf_size = new_screen_size;
rlth = min(old_row_size, new_row_size);
rrem = new_row_size - rlth;
- ol = vc->vc_origin;
- nl = (long) newscreen;
- nlend = nl + ss;
- if (new_rows < old_rows)
- ol += (old_rows - new_rows) * old_row_size;
+ old_origin = vc->vc_origin;
+ new_origin = (long) newscreen;
+ new_scr_end = new_origin + new_screen_size;
+ if (vc->vc_y > new_rows) {
+ if (old_rows - vc->vc_y < new_rows) {
+ /*
+ * Cursor near the bottom, copy contents from the
+ * bottom of buffer
+ */
+ old_origin += (old_rows - new_rows) * old_row_size;
+ end = vc->vc_scr_end;
+ } else {
+ /*
+ * Cursor is in no man's land, copy 1/2 screenful
+ * from the top and bottom of cursor position
+ */
+ old_origin += (vc->vc_y - new_rows/2) * old_row_size;
+ end = old_origin + (old_row_size * new_rows);
+ }
+ } else
+ /*
+ * Cursor near the top, copy contents from the top of buffer
+ */
+ end = (old_rows > new_rows) ? old_origin +
+ (old_row_size * new_rows) :
+ vc->vc_scr_end;
+
update_attr(vc);
- while (ol < vc->vc_scr_end) {
- scr_memcpyw((unsigned short *) nl, (unsigned short *) ol, rlth);
+ while (old_origin < end) {
+ scr_memcpyw((unsigned short *) new_origin,
+ (unsigned short *) old_origin, rlth);
if (rrem)
- scr_memsetw((void *)(nl + rlth), vc->vc_video_erase_char, rrem);
- ol += old_row_size;
- nl += new_row_size;
+ scr_memsetw((void *)(new_origin + rlth),
+ vc->vc_video_erase_char, rrem);
+ old_origin += old_row_size;
+ new_origin += new_row_size;
}
- if (nlend > nl)
- scr_memsetw((void *) nl, vc->vc_video_erase_char, nlend - nl);
+ if (new_scr_end > new_origin)
+ scr_memsetw((void *)new_origin, vc->vc_video_erase_char,
+ new_scr_end - new_origin);
if (vc->display_fg->kmalloced)
kfree(vc->vc_screenbuf);
vc->vc_screenbuf = newscreen;
vc->display_fg->kmalloced = 1;
- vc->vc_screenbuf_size = ss;
+ vc->vc_screenbuf_size = new_screen_size;
set_origin(vc);
/* do part of a reset_terminal() */
@@ -1153,8 +1213,8 @@
ws.ws_col = vc->vc_cols;
ws.ws_ypixel = vc->vc_scan_lines;
if ((ws.ws_row != cws->ws_row || ws.ws_col != cws->ws_col) &&
- vc->vc_tty->pgrp > 0)
- kill_pg(vc->vc_tty->pgrp, SIGWINCH, 1);
+ vc->vc_tty->pgrp)
+ kill_pgrp(vc->vc_tty->pgrp, SIGWINCH, 1);
*cws = ws;
}
@@ -1163,6 +1223,16 @@
return 0;
}
+int vc_lock_resize(struct vc_data *vc, unsigned int cols, unsigned int lines)
+{
+ int rc;
+
+ acquire_console_sem();
+ rc = vc_resize(vc, cols, lines);
+ release_console_sem();
+ return rc;
+}
+
void vc_SAK(struct work_struct *work)
{
struct vc *vc_con =
@@ -1273,17 +1343,23 @@
/* Do no translation at all in control states */
if (!vc->vc_state) {
tc = c;
- } else if (vc->vc_utf) {
+ } else if (vc->vc_utf && !vc->vc_disp_ctrl) {
/* Combine UTF-8 into Unicode */
- /* Incomplete characters silently ignored */
+ /* Malformed sequences as sequences of replacement glyphs */
+rescan_last_byte:
if(c > 0x7f) {
- if (vc->vc_utf_count > 0 && (c & 0xc0) == 0x80) {
- vc->vc_utf_char = (vc->vc_utf_char << 6) | (c & 0x3f);
- vc->vc_utf_count--;
- if (vc->vc_utf_count == 0)
- tc = c = vc->vc_utf_char;
- else continue;
+ if (vc->vc_utf_count > 0)
+ if ((c & 0xc0) == 0x80) {
+ vc->vc_utf_char = (vc->vc_utf_char << 6) | (c & 0x3f);
+ if (--vc->vc_utf_count) {
+ vc->vc_npar++;
+ continue;
+ }
+ tc = c = vc->vc_utf_char;
+ else
+ goto replacement;
} else {
+ vc->vc_npar = 0;
if ((c & 0xe0) == 0xc0) {
vc->vc_utf_count = 1;
vc->vc_utf_char = (c & 0x1f);
@@ -1300,15 +1376,16 @@
vc->vc_utf_count = 5;
vc->vc_utf_char = (c & 0x01);
} else
- vc->vc_utf_count = 0;
+ goto replacement_glyph;
continue;
}
} else {
+ if (vc->vc_utf_count)
+ goto replacement_glyph;
tc = c;
- vc->vc_utf_count = 0;
}
- } else { /* no utf */
- tc = vc->vc_translate[vc->vc_toggle_meta ? (c|0x80) : c];
+ } else { /* no utf or alternate charset mode */
+ tc = vc->vc_translate[vc->vc_toggle_meta ? (c | 0x80) : c];
}
/* If the original code was a control character we
@@ -1322,31 +1399,33 @@
* direct-to-font zone in UTF-8 mode.
*/
ok = tc && (c >= 32 ||
- (!vc->vc_utf && !(((vc->vc_disp_ctrl ? CTRL_ALWAYS
- : CTRL_ACTION) >> c) & 1)))
+ !(vc->vc_disp_ctrl ? (CTRL_ALWAYS >> c) & 1 :
+ vc->vc_utf || ((CTRL_ACTION >> c) & 1)))
&& (c != 127 || vc->vc_disp_ctrl)
&& (c != 128+27);
if (!vc->vc_state && ok) {
/* Now try to find out how to display it */
tc = conv_uni_to_pc(vc, tc);
- if ( tc == -4 ) {
+ if (tc & ~charmask) {
+ if ( tc == -4 ) {
/* If we got -4 (not found) then see if we have
defined a replacement character (U+FFFD) */
- tc = conv_uni_to_pc(vc, 0xfffd);
-
- /* One reason for the -4 can be that we just
- did a clear_unimap();
- try at least to show something. */
- if (tc == -4)
- tc = c;
- } else if ( tc == -3 ) {
- /* Bad hash table -- hope for the best */
- tc = c;
+replacement_glyph:
+ tc = conv_uni_to_pc(vc, 0xfffd);
+ if (!(tc & ~charmask))
+ goto display_glyph;
+ } else if ( tc != -3 )
+ continue; /* nothing to display */
+ /* no hash table or no replacement --
+ * hope for the best */
+ if ( c & ~charmask )
+ tc = '?';
+ else
+ tc = c;
}
- if (tc & ~charmask)
- continue; /* Conversion failed */
+display_glyph:
if (vc->vc_need_wrap || vc->vc_irm)
FLUSH
if (vc->vc_need_wrap) {
@@ -1368,6 +1447,15 @@
vc->vc_x++;
draw_to = (vc->vc_pos += 2);
}
+ if (vc->vc_utf_count) {
+ if (vc->vc_npar) {
+ vc->vc_npar--;
+ goto display_glyph;
+ }
+ vc->vc_utf_count = 0;
+ c = orig;
+ goto rescan_last_byte;
+ }
continue;
}
FLUSH
@@ -1376,6 +1464,8 @@
FLUSH
console_conditional_schedule();
release_console_sem();
+
+out:
return n;
#undef FLUSH
}
@@ -1390,7 +1480,7 @@
struct vc_data *vc = tty->driver_data;
int ret = 0;
- if (tty->count == 1) {
+ if (tty->driver_data == NULL) {
acquire_console_sem();
ret = tty->index;
vc = vc_allocate(ret);
@@ -1402,7 +1492,7 @@
tty->winsize.ws_row = vc->vc_rows;
tty->winsize.ws_col = vc->vc_cols;
}
- vcs_make_devfs(tty);
+ vcs_make_sysfs(tty);
}
release_console_sem();
}
@@ -1410,15 +1500,15 @@
}
/*
- * We take tty_sem in here to prevent another thread from coming in via init_dev
+ * We take tty_mutex in here to prevent another thread from coming in via init_dev
* and taking a ref against the tty while we're in the process of forgetting
* about it and cleaning things up.
*
- * This is because vcs_remove_devfs() can sleep and will drop the BKL.
+ * This is because vcs_remove_sysfs() can sleep and will drop the BKL.
*/
static void vt_close(struct tty_struct *tty, struct file * filp)
{
- down(&tty_sem);
+ mutex_lock(&tty_mutex);
acquire_console_sem();
if (tty && tty->count == 1) {
struct vc_data *vc = tty->driver_data;
@@ -1426,16 +1516,16 @@
vc->vc_tty = NULL;
tty->driver_data = NULL;
release_console_sem();
- vcs_remove_devfs(tty);
- up(&tty_sem);
+ vcs_remove_sysfs(tty);
+ mutex_unlock(&tty_mutex);
/*
- * tty_sem is released, but we still hold BKL, so there is
+ * tty_mutex is released, but we still hold BKL, so there is
* still exclusion against init_dev()
*/
return;
}
release_console_sem();
- up(&tty_sem);
+ mutex_unlock(&tty_mutex);
}
static int vt_write(struct tty_struct * tty, const unsigned char *buf, int count)
@@ -1676,7 +1766,9 @@
ret = paste_selection(tty);
break;
case TIOCL_UNBLANKSCREEN:
+ acquire_console_sem();
unblank_screen();
+ release_console_sem();
break;
case TIOCL_SELLOADLUT:
ret = sel_loadlut(p);
@@ -1701,6 +1793,10 @@
return -EFAULT;
vc->display_fg->blank_mode = (data < 4) ? data : 0;
break;
+ case TIOCL_GETKMSGREDIRECT:
+ data = kmsg_redirect;
+ ret = __put_user(data, p);
+ break;
case TIOCL_SETKMSGREDIRECT:
if (!capable(CAP_SYS_ADMIN)) {
ret = -EPERM;
@@ -1723,8 +1819,10 @@
}
break;
case TIOCL_BLANKSCREEN: /* until explicitly unblanked, not only poked */
+ acquire_console_sem();
ignore_poke = 1;
do_blank_screen(vc->display_fg, 0);
+ release_console_sem();
break;
case TIOCL_BLANKEDSCREEN:
ret = vc->display_fg->vt_blanked;
@@ -1822,7 +1920,7 @@
console_initcall(vt_console_init);
-static struct tty_operations vt_ops = {
+static const struct tty_operations vt_ops = {
.open = vt_open,
.close = vt_close,
.write = vt_write,
@@ -1848,7 +1946,6 @@
if (!console_driver)
panic("Couldn't allocate VT console driver\n");
console_driver->owner = THIS_MODULE;
- console_driver->devfs_name = "vc/";
console_driver->name = "tty";
console_driver->name_base = 1;
console_driver->major = TTY_MAJOR;
@@ -1881,14 +1978,13 @@
* and become default driver for newly opened ones.
*/
-int take_over_console(struct vt_struct *vt, const struct consw *csw)
+static int bind_vt_driver(struct vt_struct *vt, const struct consw *csw)
{
struct vc_data *vc = vt->fg_console;
- struct module *owner;
- const char *desc;
+ struct module *owner = csw->owner;
+ const char *desc = NULL;
int i;
- owner = csw->owner;
if (!try_module_get(owner))
return -ENODEV;
@@ -1930,7 +2026,9 @@
vc->vc_visible_origin = vc->vc_origin;
vc->vc_scr_end = vc->vc_origin + vc->vc_screenbuf_size;
vc->vc_pos = vc->vc_origin + vc->vc_size_rows * vc->vc_y + 2 * vc->vc_x;
+ INIT_WORK(&vc->SAK_work, vc_SAK);
visual_init(vc, 0);
+ set_origin(vc);
update_attr(vc);
/* If the console changed between mono <-> color, then
@@ -1962,6 +2060,7 @@
EXPORT_SYMBOL(default_grn);
EXPORT_SYMBOL(default_blu);
EXPORT_SYMBOL(vc_resize);
+EXPORT_SYMBOL(vc_lock_resize);
EXPORT_SYMBOL(console_blank_hook);
EXPORT_SYMBOL(vt_list);
EXPORT_SYMBOL(take_over_console);
Modified: branches/ruby-2.6.21/ruby-2.6/drivers/char/vt_ioctl.c
===================================================================
--- branches/ruby-2.6.21/ruby-2.6/drivers/char/vt_ioctl.c 2007-04-11 20:19:34 UTC (rev 2372)
+++ branches/ruby-2.6.21/ruby-2.6/drivers/char/vt_ioctl.c 2007-04-14 23:31:33 UTC (rev 2373)
@@ -236,7 +236,7 @@
ret = -ENOMEM;
goto reterr;
}
-
+
/* we mostly copy too much here (512bytes), but who cares ;) */
if (copy_from_user(kbs, user_kdgkb, sizeof(struct kbsentry))) {
ret = -EFAULT;
@@ -254,9 +254,9 @@
if (p)
for ( ; *p && sz; p++, sz--)
if (put_user(*p, up++)) {
- ret = -EFAULT;
+ ret = -EFAULT;
goto reterr;
- }
+ }
if (put_user('\0', up)) {
ret = -EFAULT;
goto reterr;
@@ -271,7 +271,7 @@
q = func_table[i];
first_free = funcbufptr + (funcbufsize - funcbufleft);
for (j = i + 1; j < MAX_NR_FUNC && !func_table[j]; j++);
-
+
if (j < MAX_NR_FUNC)
fj = func_table[j];
else
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <jsi...@us...> - 2007-04-11 20:19:39
|
Revision: 2372
http://linuxconsole.svn.sourceforge.net/linuxconsole/?rev=2372&view=rev
Author: jsimmons
Date: 2007-04-11 13:19:34 -0700 (Wed, 11 Apr 2007)
Log Message:
-----------
more updates
Modified Paths:
--------------
branches/ruby-2.6.21/ruby-2.6/drivers/char/vc_screen.c
branches/ruby-2.6.21/ruby-2.6/drivers/char/vt.c
branches/ruby-2.6.21/ruby-2.6/drivers/char/vt_ioctl.c
Modified: branches/ruby-2.6.21/ruby-2.6/drivers/char/vc_screen.c
===================================================================
--- branches/ruby-2.6.21/ruby-2.6/drivers/char/vc_screen.c 2007-04-11 19:53:20 UTC (rev 2371)
+++ branches/ruby-2.6.21/ruby-2.6/drivers/char/vc_screen.c 2007-04-11 20:19:34 UTC (rev 2372)
@@ -21,13 +21,10 @@
* - making it shorter - scr_readw are macros which expand in PRETTY long code
*/
-#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/errno.h>
#include <linux/tty.h>
-#include <linux/devfs_fs_kernel.h>
-#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/mm.h>
#include <linux/init.h>
@@ -87,7 +84,7 @@
static loff_t vcs_lseek(struct file *file, loff_t offset, int orig)
{
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
struct vc_data *vc = file->private_data;
long attr = iminor(inode) & 128;
int size;
@@ -115,10 +112,11 @@
return file->f_pos;
}
+
static ssize_t
vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
{
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
struct vc_data *vc = file->private_data;
long attr = iminor(inode) & 128;
unsigned short *org = NULL;
@@ -284,7 +282,7 @@
static ssize_t
vcs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
{
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
struct vc_data *vc = file->private_data;
long viewed, size, written, pos;
long attr = iminor(inode) & 128;
@@ -472,43 +470,36 @@
return 0;
}
-static struct file_operations vcs_fops = {
+static const struct file_operations vcs_fops = {
.llseek = vcs_lseek,
.read = vcs_read,
.write = vcs_write,
.open = vcs_open,
};
-static struct class_simple *vc_class;
+static struct class *vc_class;
-void vcs_make_devfs(struct tty_struct *tty)
+void vcs_make_sysfs(struct tty_struct *tty)
{
- devfs_mk_cdev(MKDEV(VCS_MAJOR, tty->index + 1),
- S_IFCHR|S_IRUSR|S_IWUSR,
- "vcc/%u", tty->index + 1);
- devfs_mk_cdev(MKDEV(VCS_MAJOR, tty->index + 129),
- S_IFCHR|S_IRUSR|S_IWUSR,
- "vcc/a%u", tty->index + 1);
- class_simple_device_add(vc_class, MKDEV(VCS_MAJOR, tty->index + 1), NULL, "vcs%u", tty->index + 1);
- class_simple_device_add(vc_class, MKDEV(VCS_MAJOR, tty->index + 129), NULL, "vcsa%u", tty->index + 1);
+ device_create(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 1),
+ "vcs%u", tty->index + 1);
+ device_create(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 129),
+ "vcsa%u", tty->index + 1);
}
-void vcs_remove_devfs(struct tty_struct *tty)
+
+void vcs_remove_sysfs(struct tty_struct *tty)
{
- devfs_remove("vcc/%u", tty->index + 1);
- devfs_remove("vcc/a%u", tty->index + 1);
- class_simple_device_remove(MKDEV(VCS_MAJOR, tty->index + 1));
- class_simple_device_remove(MKDEV(VCS_MAJOR, tty->index + 129));
+ device_destroy(vc_class, MKDEV(VCS_MAJOR, tty->index + 1));
+ device_destroy(vc_class, MKDEV(VCS_MAJOR, tty->index + 129));
}
int __init vcs_init(void)
{
if (register_chrdev(VCS_MAJOR, "vcs", &vcs_fops))
panic("unable to get major %d for vcs device", VCS_MAJOR);
- vc_class = class_simple_create(THIS_MODULE, "vc");
+ vc_class = class_create(THIS_MODULE, "vc");
- devfs_mk_cdev(MKDEV(VCS_MAJOR, 0), S_IFCHR|S_IRUSR|S_IWUSR, "vcc/0");
- devfs_mk_cdev(MKDEV(VCS_MAJOR, 128), S_IFCHR|S_IRUSR|S_IWUSR, "vcc/a0");
- class_simple_device_add(vc_class, MKDEV(VCS_MAJOR, 0), NULL, "vcs");
- class_simple_device_add(vc_class, MKDEV(VCS_MAJOR, 128), NULL, "vcsa");
+ device_create(vc_class, NULL, MKDEV(VCS_MAJOR, 0), "vcs");
+ device_create(vc_class, NULL, MKDEV(VCS_MAJOR, 128), "vcsa");
return 0;
}
Modified: branches/ruby-2.6.21/ruby-2.6/drivers/char/vt.c
===================================================================
--- branches/ruby-2.6.21/ruby-2.6/drivers/char/vt.c 2007-04-11 19:53:20 UTC (rev 2371)
+++ branches/ruby-2.6.21/ruby-2.6/drivers/char/vt.c 2007-04-11 20:19:34 UTC (rev 2372)
@@ -1054,7 +1054,7 @@
vc->vt_mode.relsig = 0;
vc->vt_mode.acqsig = 0;
vc->vt_mode.frsig = 0;
- vc->vt_pid = -1;
+ put_pid(vc->vt_pid);
vc->vt_newvt = -1;
if (!in_interrupt()) /* Via keyboard.c:SAK() - akpm */
reset_palette(vc) ;
@@ -1163,6 +1163,28 @@
return 0;
}
+void vc_SAK(struct work_struct *work)
+{
+ struct vc *vc_con =
+ container_of(work, struct vc, SAK_work);
+ struct tty_struct *tty;
+ struct vc_data *vc;
+
+ acquire_console_sem();
+ vc = vc_con->d;
+ if (vc) {
+ tty = vc->vc_tty;
+ /*
+ * SAK should also work in all raw modes and reset
+ * them properly.
+ */
+ if (tty)
+ __do_SAK(tty);
+ reset_vc(vc);
+ }
+ release_console_sem();
+}
+
/*
* Selection stuff for GPM.
*/
Modified: branches/ruby-2.6.21/ruby-2.6/drivers/char/vt_ioctl.c
===================================================================
--- branches/ruby-2.6.21/ruby-2.6/drivers/char/vt_ioctl.c 2007-04-11 19:53:20 UTC (rev 2371)
+++ branches/ruby-2.6.21/ruby-2.6/drivers/char/vt_ioctl.c 2007-04-11 20:19:34 UTC (rev 2372)
@@ -11,7 +11,6 @@
* Check put/get_user, cleanups - ac...@co... - Jun 2001
*/
-#include <linux/config.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/sched.h>
@@ -82,10 +81,22 @@
add_wait_queue(&vt_activate_queue, &wait);
for (;;) {
+ retval = 0;
+
+ /*
+ * Synchronize with redraw_screen(). By acquiring the console
+ * semaphore we make sure that the console switch is completed
+ * before we return. If we didn't wait for the semaphore, we
+ * could return at a point where fg_console has already been
+ * updated, but the console switch hasn't been completed.
+ */
+ acquire_console_sem();
set_current_state(TASK_INTERRUPTIBLE);
- retval = 0;
- if (IS_VISIBLE)
+ if (IS_VISIBLE) {
+ release_console_sem();
break;
+ }
+ release_console_sem();
retval = -EINTR;
if (signal_pending(current))
break;
@@ -108,6 +119,9 @@
if (copy_from_user(&tmp, user_kbe, sizeof(struct kbentry)))
return -EFAULT;
+ if (!capable(CAP_SYS_TTY_CONFIG))
+ perm = 0;
+
switch (cmd) {
case KDGKBENT:
key_map = key_maps[s];
@@ -122,7 +136,7 @@
if (!perm)
return -EPERM;
if (!i && v == K_NOSUCHMAP) {
- /* disallocate map */
+ /* deallocate map */
key_map = key_maps[s];
if (s && key_map) {
key_maps[s] = NULL;
@@ -154,7 +168,7 @@
!capable(CAP_SYS_RESOURCE))
return -EPERM;
- key_map = (ushort *) kmalloc(sizeof(plain_map), GFP_KERNEL);
+ key_map = kmalloc(sizeof(plain_map), GFP_KERNEL);
if (!key_map)
return -ENOMEM;
key_maps[s] = key_map;
@@ -214,6 +228,9 @@
u_char __user *up;
u_char *q;
+ if (!capable(CAP_SYS_TTY_CONFIG))
+ perm = 0;
+
kbs = kmalloc(sizeof(*kbs), GFP_KERNEL);
if (!kbs) {
ret = -ENOMEM;
@@ -275,7 +292,7 @@
sz = 256;
while (sz < funcbufsize - funcbufleft + delta)
sz <<= 1;
- fnw = (char *) kmalloc(sz, GFP_KERNEL);
+ fnw = kmalloc(sz, GFP_KERNEL);
if (!fnw) {
ret = -ENOMEM;
goto reterr;
@@ -657,11 +674,11 @@
*/
if (old_vc->vt_mode.mode == VT_PROCESS) {
/*
- * Send the signal as privileged - kill_proc() will
+ * Send the signal as privileged - kill_pid() will
* tell us if the process has gone or something else
* is awry
*/
- if (kill_proc(old_vc->vt_pid, old_vc->vt_mode.relsig, 1) == 0) {
+ if (kill_pid(old_vc->vt_pid, old_vc->vt_mode.relsig, 1) == 0) {
/*
* It worked. Mark the vt to switch to and
* return. The process needs to send us a
@@ -714,7 +731,7 @@
switch_screen(new_vc, old_vc);
/*
- * This can't appear below a successful kill_proc(). If it did,
+ * This can't appear below a successful kill_pid(). If it did,
* then the *blank_screen operation could occur while X, having
* received acqsig, is waking up on another processor. This
* condition can lead to overlapping accesses to the VGA range
@@ -739,11 +756,11 @@
*/
if (new_vc->vt_mode.mode == VT_PROCESS) {
/*
- * Send the signal as privileged - kill_proc() will
+ * Send the signal as privileged - kill_pid() will
* tell us if the process has gone or something else
* is awry
*/
- if (kill_proc(new_vc->vt_pid,new_vc->vt_mode.acqsig, 1) != 0) {
+ if (kill_pid(new_vc->vt_pid,new_vc->vt_mode.acqsig, 1) != 0) {
/*
* The controlling process has died, so we revert back
* to normal operation. In this case, we'll also change
@@ -1054,13 +1071,16 @@
*/
case KDSIGACCEPT:
{
- extern int spawnpid, spawnsig;
if (!perm || !capable(CAP_KILL))
return -EPERM;
if (!valid_signal(arg) || arg < 1 || arg == SIGKILL)
return -EINVAL;
- spawnpid = current->pid;
- spawnsig = arg;
+
+ spin_lock_irq(&vt_spawn_con.lock);
+ put_pid(vt_spawn_con.pid);
+ vt_spawn_con.pid = get_pid(task_pid(current));
+ vt_spawn_con.sig = arg;
+ spin_unlock_irq(&vt_spawn_con.lock);
return 0;
}
@@ -1078,7 +1098,8 @@
vc->vt_mode = tmp;
/* the frsig is ignored, so we set it to 0 */
vc->vt_mode.frsig = 0;
- vc->vt_pid = current->pid;
+ put_pid(vc->vt_pid);
+ vc->vt_pid = get_pid(task_pid(current));
/* no switch is required -- sa...@sh... */
vc->vt_newvt = -1;
release_console_sem();
@@ -1248,13 +1269,13 @@
if (arg > MAX_NR_CONSOLES)
return -ENXIO;
if (arg == 0) {
- /* disallocate all unused consoles, but leave visible VC */
+ /* deallocate all unused consoles, but leave visible VC */
acquire_console_sem();
for (i = 1; i < vt->vc_count; i++) {
tmp = find_vc(i + vt->first_vc);
if (tmp && !VT_BUSY(tmp))
- vc_disallocate(tmp);
+ vc_deallocate(tmp);
}
release_console_sem();
} else {
@@ -1263,7 +1284,7 @@
if (!tmp || VT_BUSY(tmp))
return -EBUSY;
acquire_console_sem();
- vc_disallocate(tmp);
+ vc_deallocate(tmp);
release_console_sem();
}
return 0;
@@ -1280,9 +1301,7 @@
for (i = 0; i < vc->display_fg->vc_count; i++) {
struct vc_data *tmp = vc->display_fg->vc_cons[i];
- acquire_console_sem();
- vc_resize(tmp, cc, ll);
- release_console_sem();
+ vc_lock_resize(tmp, cc, ll);
}
return 0;
}
@@ -1441,6 +1460,8 @@
return -EPERM;
vc->display_fg->vt_dont_switch = 0;
return 0;
+ case VT_GETHIFONTMASK:
+ return put_user(vc->vc_hi_font_mask, (unsigned short __user *)arg);
default:
return -ENOIOCTLCMD;
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <jsi...@us...> - 2007-04-11 19:53:45
|
Revision: 2371
http://linuxconsole.svn.sourceforge.net/linuxconsole/?rev=2371&view=rev
Author: jsimmons
Date: 2007-04-11 12:53:20 -0700 (Wed, 11 Apr 2007)
Log Message:
-----------
updated to tty_io
Modified Paths:
--------------
branches/ruby-2.6.21/ruby-2.6/drivers/char/tty_io.c
Modified: branches/ruby-2.6.21/ruby-2.6/drivers/char/tty_io.c
===================================================================
--- branches/ruby-2.6.21/ruby-2.6/drivers/char/tty_io.c 2007-04-11 19:49:18 UTC (rev 2370)
+++ branches/ruby-2.6.21/ruby-2.6/drivers/char/tty_io.c 2007-04-11 19:53:20 UTC (rev 2371)
@@ -65,7 +65,6 @@
* alloc_tty_struct() always uses kmalloc() -- Andrew Morton <an...@uo...> 17Mar01
*/
-#include <linux/config.h>
#include <linux/types.h>
#include <linux/major.h>
#include <linux/errno.h>
@@ -93,12 +92,12 @@
#include <linux/idr.h>
#include <linux/wait.h>
#include <linux/bitops.h>
+#include <linux/delay.h>
#include <asm/uaccess.h>
#include <asm/system.h>
#include <linux/vt_kern.h>
-#include <linux/devfs_fs_kernel.h>
#include <linux/kmod.h>
@@ -107,13 +106,15 @@
#define TTY_PARANOIA_CHECK 1
#define CHECK_TTY_COUNT 1
-struct termios tty_std_termios = { /* for the benefit of tty drivers */
+struct ktermios tty_std_termios = { /* for the benefit of tty drivers */
.c_iflag = ICRNL | IXON,
.c_oflag = OPOST | ONLCR,
.c_cflag = B38400 | CS8 | CREAD | HUPCL,
.c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK |
ECHOCTL | ECHOKE | IEXTEN,
- .c_cc = INIT_C_CC
+ .c_cc = INIT_C_CC,
+ .c_ispeed = 38400,
+ .c_ospeed = 38400
};
EXPORT_SYMBOL(tty_std_termios);
@@ -124,9 +125,10 @@
LIST_HEAD(tty_drivers); /* linked list of tty drivers */
-/* Semaphore to protect creating and releasing a tty. This is shared with
+/* Mutex to protect creating and releasing a tty. This is shared with
vt.c for deeply disgusting hack reasons */
-DECLARE_MUTEX(tty_sem);
+DEFINE_MUTEX(tty_mutex);
+EXPORT_SYMBOL(tty_mutex);
#ifdef CONFIG_UNIX98_PTYS
extern struct tty_driver *ptm_driver; /* Unix98 pty masters; for /dev/ptmx */
@@ -149,28 +151,55 @@
int tty_ioctl(struct inode * inode, struct file * file,
unsigned int cmd, unsigned long arg);
static int tty_fasync(int fd, struct file * filp, int on);
-extern void rs_360_init(void);
-static void release_mem(struct tty_struct *tty, int idx);
+static void release_tty(struct tty_struct *tty, int idx);
+static struct pid *__proc_set_tty(struct task_struct *tsk,
+ struct tty_struct *tty);
+/**
+ * alloc_tty_struct - allocate a tty object
+ *
+ * Return a new empty tty structure. The data fields have not
+ * been initialized in any way but has been zeroed
+ *
+ * Locking: none
+ */
static struct tty_struct *alloc_tty_struct(void)
{
- struct tty_struct *tty;
-
- tty = kmalloc(sizeof(struct tty_struct), GFP_KERNEL);
- if (tty)
- memset(tty, 0, sizeof(struct tty_struct));
- return tty;
+ return kzalloc(sizeof(struct tty_struct), GFP_KERNEL);
}
+static void tty_buffer_free_all(struct tty_struct *);
+
+/**
+ * free_tty_struct - free a disused tty
+ * @tty: tty struct to free
+ *
+ * Free the write buffers, tty queue and tty memory itself.
+ *
+ * Locking: none. Must be called after tty is definitely unused
+ */
+
static inline void free_tty_struct(struct tty_struct *tty)
{
kfree(tty->write_buf);
+ tty_buffer_free_all(tty);
kfree(tty);
}
#define TTY_NUMBER(tty) ((tty)->index + (tty)->driver->name_base)
+/**
+ * tty_name - return tty naming
+ * @tty: tty structure
+ * @buf: buffer for output
+ *
+ * Convert a tty structure into a name. The name reflects the kernel
+ * naming policy and if udev is in use may not reflect user space
+ *
+ * Locking: none
+ */
+
char *tty_name(struct tty_struct *tty, char *buf)
{
if (!tty) /* Hmm. NULL pointer. That's fun. */
@@ -222,22 +251,366 @@
"!= #fd's(%d) in %s\n",
tty->name, tty->count, count, routine);
return count;
- }
+ }
#endif
return 0;
}
/*
+ * Tty buffer allocation management
+ */
+
+/**
+ * tty_buffer_free_all - free buffers used by a tty
+ * @tty: tty to free from
+ *
+ * Remove all the buffers pending on a tty whether queued with data
+ * or in the free ring. Must be called when the tty is no longer in use
+ *
+ * Locking: none
+ */
+
+static void tty_buffer_free_all(struct tty_struct *tty)
+{
+ struct tty_buffer *thead;
+ while((thead = tty->buf.head) != NULL) {
+ tty->buf.head = thead->next;
+ kfree(thead);
+ }
+ while((thead = tty->buf.free) != NULL) {
+ tty->buf.free = thead->next;
+ kfree(thead);
+ }
+ tty->buf.tail = NULL;
+ tty->buf.memory_used = 0;
+}
+
+/**
+ * tty_buffer_init - prepare a tty buffer structure
+ * @tty: tty to initialise
+ *
+ * Set up the initial state of the buffer management for a tty device.
+ * Must be called before the other tty buffer functions are used.
+ *
+ * Locking: none
+ */
+
+static void tty_buffer_init(struct tty_struct *tty)
+{
+ spin_lock_init(&tty->buf.lock);
+ tty->buf.head = NULL;
+ tty->buf.tail = NULL;
+ tty->buf.free = NULL;
+ tty->buf.memory_used = 0;
+}
+
+/**
+ * tty_buffer_alloc - allocate a tty buffer
+ * @tty: tty device
+ * @size: desired size (characters)
+ *
+ * Allocate a new tty buffer to hold the desired number of characters.
+ * Return NULL if out of memory or the allocation would exceed the
+ * per device queue
+ *
+ * Locking: Caller must hold tty->buf.lock
+ */
+
+static struct tty_buffer *tty_buffer_alloc(struct tty_struct *tty, size_t size)
+{
+ struct tty_buffer *p;
+
+ if (tty->buf.memory_used + size > 65536)
+ return NULL;
+ p = kmalloc(sizeof(struct tty_buffer) + 2 * size, GFP_ATOMIC);
+ if(p == NULL)
+ return NULL;
+ p->used = 0;
+ p->size = size;
+ p->next = NULL;
+ p->commit = 0;
+ p->read = 0;
+ p->char_buf_ptr = (char *)(p->data);
+ p->flag_buf_ptr = (unsigned char *)p->char_buf_ptr + size;
+ tty->buf.memory_used += size;
+ return p;
+}
+
+/**
+ * tty_buffer_free - free a tty buffer
+ * @tty: tty owning the buffer
+ * @b: the buffer to free
+ *
+ * Free a tty buffer, or add it to the free list according to our
+ * internal strategy
+ *
+ * Locking: Caller must hold tty->buf.lock
+ */
+
+static void tty_buffer_free(struct tty_struct *tty, struct tty_buffer *b)
+{
+ /* Dumb strategy for now - should keep some stats */
+ tty->buf.memory_used -= b->size;
+ WARN_ON(tty->buf.memory_used < 0);
+
+ if(b->size >= 512)
+ kfree(b);
+ else {
+ b->next = tty->buf.free;
+ tty->buf.free = b;
+ }
+}
+
+/**
+ * tty_buffer_find - find a free tty buffer
+ * @tty: tty owning the buffer
+ * @size: characters wanted
+ *
+ * Locate an existing suitable tty buffer or if we are lacking one then
+ * allocate a new one. We round our buffers off in 256 character chunks
+ * to get better allocation behaviour.
+ *
+ * Locking: Caller must hold tty->buf.lock
+ */
+
+static struct tty_buffer *tty_buffer_find(struct tty_struct *tty, size_t size)
+{
+ struct tty_buffer **tbh = &tty->buf.free;
+ while((*tbh) != NULL) {
+ struct tty_buffer *t = *tbh;
+ if(t->size >= size) {
+ *tbh = t->next;
+ t->next = NULL;
+ t->used = 0;
+ t->commit = 0;
+ t->read = 0;
+ tty->buf.memory_used += t->size;
+ return t;
+ }
+ tbh = &((*tbh)->next);
+ }
+ /* Round the buffer size out */
+ size = (size + 0xFF) & ~ 0xFF;
+ return tty_buffer_alloc(tty, size);
+ /* Should possibly check if this fails for the largest buffer we
+ have queued and recycle that ? */
+}
+
+/**
+ * tty_buffer_request_room - grow tty buffer if needed
+ * @tty: tty structure
+ * @size: size desired
+ *
+ * Make at least size bytes of linear space available for the tty
+ * buffer. If we fail return the size we managed to find.
+ *
+ * Locking: Takes tty->buf.lock
+ */
+int tty_buffer_request_room(struct tty_struct *tty, size_t size)
+{
+ struct tty_buffer *b, *n;
+ int left;
+ unsigned long flags;
+
+ spin_lock_irqsave(&tty->buf.lock, flags);
+
+ /* OPTIMISATION: We could keep a per tty "zero" sized buffer to
+ remove this conditional if its worth it. This would be invisible
+ to the callers */
+ if ((b = tty->buf.tail) != NULL)
+ left = b->size - b->used;
+ else
+ left = 0;
+
+ if (left < size) {
+ /* This is the slow path - looking for new buffers to use */
+ if ((n = tty_buffer_find(tty, size)) != NULL) {
+ if (b != NULL) {
+ b->next = n;
+ b->commit = b->used;
+ } else
+ tty->buf.head = n;
+ tty->buf.tail = n;
+ } else
+ size = left;
+ }
+
+ spin_unlock_irqrestore(&tty->buf.lock, flags);
+ return size;
+}
+EXPORT_SYMBOL_GPL(tty_buffer_request_room);
+
+/**
+ * tty_insert_flip_string - Add characters to the tty buffer
+ * @tty: tty structure
+ * @chars: characters
+ * @size: size
+ *
+ * Queue a series of bytes to the tty buffering. All the characters
+ * passed are marked as without error. Returns the number added.
+ *
+ * Locking: Called functions may take tty->buf.lock
+ */
+
+int tty_insert_flip_string(struct tty_struct *tty, const unsigned char *chars,
+ size_t size)
+{
+ int copied = 0;
+ do {
+ int space = tty_buffer_request_room(tty, size - copied);
+ struct tty_buffer *tb = tty->buf.tail;
+ /* If there is no space then tb may be NULL */
+ if(unlikely(space == 0))
+ break;
+ memcpy(tb->char_buf_ptr + tb->used, chars, space);
+ memset(tb->flag_buf_ptr + tb->used, TTY_NORMAL, space);
+ tb->used += space;
+ copied += space;
+ chars += space;
+ /* There is a small chance that we need to split the data over
+ several buffers. If this is the case we must loop */
+ } while (unlikely(size > copied));
+ return copied;
+}
+EXPORT_SYMBOL(tty_insert_flip_string);
+
+/**
+ * tty_insert_flip_string_flags - Add characters to the tty buffer
+ * @tty: tty structure
+ * @chars: characters
+ * @flags: flag bytes
+ * @size: size
+ *
+ * Queue a series of bytes to the tty buffering. For each character
+ * the flags array indicates the status of the character. Returns the
+ * number added.
+ *
+ * Locking: Called functions may take tty->buf.lock
+ */
+
+int tty_insert_flip_string_flags(struct tty_struct *tty,
+ const unsigned char *chars, const char *flags, size_t size)
+{
+ int copied = 0;
+ do {
+ int space = tty_buffer_request_room(tty, size - copied);
+ struct tty_buffer *tb = tty->buf.tail;
+ /* If there is no space then tb may be NULL */
+ if(unlikely(space == 0))
+ break;
+ memcpy(tb->char_buf_ptr + tb->used, chars, space);
+ memcpy(tb->flag_buf_ptr + tb->used, flags, space);
+ tb->used += space;
+ copied += space;
+ chars += space;
+ flags += space;
+ /* There is a small chance that we need to split the data over
+ several buffers. If this is the case we must loop */
+ } while (unlikely(size > copied));
+ return copied;
+}
+EXPORT_SYMBOL(tty_insert_flip_string_flags);
+
+/**
+ * tty_schedule_flip - push characters to ldisc
+ * @tty: tty to push from
+ *
+ * Takes any pending buffers and transfers their ownership to the
+ * ldisc side of the queue. It then schedules those characters for
+ * processing by the line discipline.
+ *
+ * Locking: Takes tty->buf.lock
+ */
+
+void tty_schedule_flip(struct tty_struct *tty)
+{
+ unsigned long flags;
+ spin_lock_irqsave(&tty->buf.lock, flags);
+ if (tty->buf.tail != NULL)
+ tty->buf.tail->commit = tty->buf.tail->used;
+ spin_unlock_irqrestore(&tty->buf.lock, flags);
+ schedule_delayed_work(&tty->buf.work, 1);
+}
+EXPORT_SYMBOL(tty_schedule_flip);
+
+/**
+ * tty_prepare_flip_string - make room for characters
+ * @tty: tty
+ * @chars: return pointer for character write area
+ * @size: desired size
+ *
+ * Prepare a block of space in the buffer for data. Returns the length
+ * available and buffer pointer to the space which is now allocated and
+ * accounted for as ready for normal characters. This is used for drivers
+ * that need their own block copy routines into the buffer. There is no
+ * guarantee the buffer is a DMA target!
+ *
+ * Locking: May call functions taking tty->buf.lock
+ */
+
+int tty_prepare_flip_string(struct tty_struct *tty, unsigned char **chars, size_t size)
+{
+ int space = tty_buffer_request_room(tty, size);
+ if (likely(space)) {
+ struct tty_buffer *tb = tty->buf.tail;
+ *chars = tb->char_buf_ptr + tb->used;
+ memset(tb->flag_buf_ptr + tb->used, TTY_NORMAL, space);
+ tb->used += space;
+ }
+ return space;
+}
+
+EXPORT_SYMBOL_GPL(tty_prepare_flip_string);
+
+/**
+ * tty_prepare_flip_string_flags - make room for characters
+ * @tty: tty
+ * @chars: return pointer for character write area
+ * @flags: return pointer for status flag write area
+ * @size: desired size
+ *
+ * Prepare a block of space in the buffer for data. Returns the length
+ * available and buffer pointer to the space which is now allocated and
+ * accounted for as ready for characters. This is used for drivers
+ * that need their own block copy routines into the buffer. There is no
+ * guarantee the buffer is a DMA target!
+ *
+ * Locking: May call functions taking tty->buf.lock
+ */
+
+int tty_prepare_flip_string_flags(struct tty_struct *tty, unsigned char **chars, char **flags, size_t size)
+{
+ int space = tty_buffer_request_room(tty, size);
+ if (likely(space)) {
+ struct tty_buffer *tb = tty->buf.tail;
+ *chars = tb->char_buf_ptr + tb->used;
+ *flags = tb->flag_buf_ptr + tb->used;
+ tb->used += space;
+ }
+ return space;
+}
+
+EXPORT_SYMBOL_GPL(tty_prepare_flip_string_flags);
+
+
+
+/**
+ * tty_set_termios_ldisc - set ldisc field
+ * @tty: tty structure
+ * @num: line discipline number
+ *
* This is probably overkill for real world processors but
* they are not on hot paths so a little discipline won't do
* any harm.
+ *
+ * Locking: takes termios_mutex
*/
static void tty_set_termios_ldisc(struct tty_struct *tty, int num)
{
- down(&tty->termios_sem);
+ mutex_lock(&tty->termios_mutex);
tty->termios->c_line = num;
- up(&tty->termios_sem);
+ mutex_unlock(&tty->termios_mutex);
}
/*
@@ -248,8 +621,21 @@
static DEFINE_SPINLOCK(tty_ldisc_lock);
static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_wait);
-static struct tty_ldisc tty_ldiscs[NR_LDISCS]; /* line disc dispatch table */
+static struct tty_ldisc tty_ldiscs[NR_LDISCS]; /* line disc dispatch table */
+/**
+ * tty_register_ldisc - install a line discipline
+ * @disc: ldisc number
+ * @new_ldisc: pointer to the ldisc object
+ *
+ * Installs a new line discipline into the kernel. The discipline
+ * is set up as unreferenced and then made available to the kernel
+ * from this point onwards.
+ *
+ * Locking:
+ * takes tty_ldisc_lock to guard against ldisc races
+ */
+
int tty_register_ldisc(int disc, struct tty_ldisc *new_ldisc)
{
unsigned long flags;
@@ -259,24 +645,60 @@
return -EINVAL;
spin_lock_irqsave(&tty_ldisc_lock, flags);
- if (new_ldisc) {
- tty_ldiscs[disc] = *new_ldisc;
- tty_ldiscs[disc].num = disc;
- tty_ldiscs[disc].flags |= LDISC_FLAG_DEFINED;
- tty_ldiscs[disc].refcount = 0;
- } else {
- if(tty_ldiscs[disc].refcount)
- ret = -EBUSY;
- else
- tty_ldiscs[disc].flags &= ~LDISC_FLAG_DEFINED;
- }
+ tty_ldiscs[disc] = *new_ldisc;
+ tty_ldiscs[disc].num = disc;
+ tty_ldiscs[disc].flags |= LDISC_FLAG_DEFINED;
+ tty_ldiscs[disc].refcount = 0;
spin_unlock_irqrestore(&tty_ldisc_lock, flags);
return ret;
}
-
EXPORT_SYMBOL(tty_register_ldisc);
+/**
+ * tty_unregister_ldisc - unload a line discipline
+ * @disc: ldisc number
+ * @new_ldisc: pointer to the ldisc object
+ *
+ * Remove a line discipline from the kernel providing it is not
+ * currently in use.
+ *
+ * Locking:
+ * takes tty_ldisc_lock to guard against ldisc races
+ */
+
+int tty_unregister_ldisc(int disc)
+{
+ unsigned long flags;
+ int ret = 0;
+
+ if (disc < N_TTY || disc >= NR_LDISCS)
+ return -EINVAL;
+
+ spin_lock_irqsave(&tty_ldisc_lock, flags);
+ if (tty_ldiscs[disc].refcount)
+ ret = -EBUSY;
+ else
+ tty_ldiscs[disc].flags &= ~LDISC_FLAG_DEFINED;
+ spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+
+ return ret;
+}
+EXPORT_SYMBOL(tty_unregister_ldisc);
+
+/**
+ * tty_ldisc_get - take a reference to an ldisc
+ * @disc: ldisc number
+ *
+ * Takes a reference to a line discipline. Deals with refcounts and
+ * module locking counts. Returns NULL if the discipline is not available.
+ * Returns a pointer to the discipline and bumps the ref count if it is
+ * available
+ *
+ * Locking:
+ * takes tty_ldisc_lock to guard against ldisc races
+ */
+
struct tty_ldisc *tty_ldisc_get(int disc)
{
unsigned long flags;
@@ -305,25 +727,47 @@
EXPORT_SYMBOL_GPL(tty_ldisc_get);
+/**
+ * tty_ldisc_put - drop ldisc reference
+ * @disc: ldisc number
+ *
+ * Drop a reference to a line discipline. Manage refcounts and
+ * module usage counts
+ *
+ * Locking:
+ * takes tty_ldisc_lock to guard against ldisc races
+ */
+
void tty_ldisc_put(int disc)
{
struct tty_ldisc *ld;
unsigned long flags;
- if (disc < N_TTY || disc >= NR_LDISCS)
- BUG();
+ BUG_ON(disc < N_TTY || disc >= NR_LDISCS);
spin_lock_irqsave(&tty_ldisc_lock, flags);
ld = &tty_ldiscs[disc];
- if(ld->refcount == 0)
- BUG();
- ld->refcount --;
+ BUG_ON(ld->refcount == 0);
+ ld->refcount--;
module_put(ld->owner);
spin_unlock_irqrestore(&tty_ldisc_lock, flags);
}
EXPORT_SYMBOL_GPL(tty_ldisc_put);
+/**
+ * tty_ldisc_assign - set ldisc on a tty
+ * @tty: tty to assign
+ * @ld: line discipline
+ *
+ * Install an instance of a line discipline into a tty structure. The
+ * ldisc must have a reference count above zero to ensure it remains/
+ * The tty instance refcount starts at zero.
+ *
+ * Locking:
+ * Caller must hold references
+ */
+
static void tty_ldisc_assign(struct tty_struct *tty, struct tty_ldisc *ld)
{
tty->ldisc = *ld;
@@ -338,6 +782,8 @@
* the tty ldisc. Return 0 on failure or 1 on success. This is
* used to implement both the waiting and non waiting versions
* of tty_ldisc_ref
+ *
+ * Locking: takes tty_ldisc_lock
*/
static int tty_ldisc_try(struct tty_struct *tty)
@@ -369,6 +815,8 @@
* must also be careful not to hold other locks that will deadlock
* against a discipline change, such as an existing ldisc reference
* (which we check for)
+ *
+ * Locking: call functions take tty_ldisc_lock
*/
struct tty_ldisc *tty_ldisc_ref_wait(struct tty_struct *tty)
@@ -389,6 +837,8 @@
* Dereference the line discipline for the terminal and take a
* reference to it. If the line discipline is in flux then
* return NULL. Can be called from IRQ and timer functions.
+ *
+ * Locking: called functions take tty_ldisc_lock
*/
struct tty_ldisc *tty_ldisc_ref(struct tty_struct *tty)
@@ -406,14 +856,15 @@
*
* Undoes the effect of tty_ldisc_ref or tty_ldisc_ref_wait. May
* be called in IRQ context.
+ *
+ * Locking: takes tty_ldisc_lock
*/
void tty_ldisc_deref(struct tty_ldisc *ld)
{
unsigned long flags;
- if(ld == NULL)
- BUG();
+ BUG_ON(ld == NULL);
spin_lock_irqsave(&tty_ldisc_lock, flags);
if(ld->refcount == 0)
@@ -451,25 +902,26 @@
*
* Set the discipline of a tty line. Must be called from a process
* context.
+ *
+ * Locking: takes tty_ldisc_lock.
+ * called functions take termios_mutex
*/
static int tty_set_ldisc(struct tty_struct *tty, int ldisc)
{
- int retval = 0;
- struct tty_ldisc o_ldisc;
+ int retval = 0;
+ struct tty_ldisc o_ldisc;
char buf[64];
int work;
unsigned long flags;
struct tty_ldisc *ld;
+ struct tty_struct *o_tty;
if ((ldisc < N_TTY) || (ldisc >= NR_LDISCS))
return -EINVAL;
restart:
- if (tty->ldisc.num == ldisc)
- return 0; /* We are already in the desired discipline */
-
ld = tty_ldisc_get(ldisc);
/* Eduardo Blanco <ej...@cs...> */
/* Cyrus Durgin <ci...@sp...> */
@@ -480,48 +932,85 @@
if (ld == NULL)
return -EINVAL;
- o_ldisc = tty->ldisc;
+ /*
+ * No more input please, we are switching. The new ldisc
+ * will update this value in the ldisc open function
+ */
+ tty->receive_room = 0;
+
+ /*
+ * Problem: What do we do if this blocks ?
+ */
+
tty_wait_until_sent(tty, 0);
+ if (tty->ldisc.num == ldisc) {
+ tty_ldisc_put(ldisc);
+ return 0;
+ }
+
+ o_ldisc = tty->ldisc;
+ o_tty = tty->link;
+
/*
* Make sure we don't change while someone holds a
* reference to the line discipline. The TTY_LDISC bit
* prevents anyone taking a reference once it is clear.
* We need the lock to avoid racing reference takers.
*/
-
+
spin_lock_irqsave(&tty_ldisc_lock, flags);
- if(tty->ldisc.refcount)
- {
- /* Free the new ldisc we grabbed. Must drop the lock
- first. */
+ if (tty->ldisc.refcount || (o_tty && o_tty->ldisc.refcount)) {
+ if(tty->ldisc.refcount) {
+ /* Free the new ldisc we grabbed. Must drop the lock
+ first. */
+ spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+ tty_ldisc_put(ldisc);
+ /*
+ * There are several reasons we may be busy, including
+ * random momentary I/O traffic. We must therefore
+ * retry. We could distinguish between blocking ops
+ * and retries if we made tty_ldisc_wait() smarter. That
+ * is up for discussion.
+ */
+ if (wait_event_interruptible(tty_ldisc_wait, tty->ldisc.refcount == 0) < 0)
+ return -ERESTARTSYS;
+ goto restart;
+ }
+ if(o_tty && o_tty->ldisc.refcount) {
+ spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+ tty_ldisc_put(ldisc);
+ if (wait_event_interruptible(tty_ldisc_wait, o_tty->ldisc.refcount == 0) < 0)
+ return -ERESTARTSYS;
+ goto restart;
+ }
+ }
+
+ /* if the TTY_LDISC bit is set, then we are racing against another ldisc change */
+
+ if (!test_bit(TTY_LDISC, &tty->flags)) {
spin_unlock_irqrestore(&tty_ldisc_lock, flags);
tty_ldisc_put(ldisc);
- /*
- * There are several reasons we may be busy, including
- * random momentary I/O traffic. We must therefore
- * retry. We could distinguish between blocking ops
- * and retries if we made tty_ldisc_wait() smarter. That
- * is up for discussion.
- */
- if(wait_event_interruptible(tty_ldisc_wait, tty->ldisc.refcount == 0) < 0)
- return -ERESTARTSYS;
+ ld = tty_ldisc_ref_wait(tty);
+ tty_ldisc_deref(ld);
goto restart;
}
- clear_bit(TTY_LDISC, &tty->flags);
- clear_bit(TTY_DONT_FLIP, &tty->flags);
+
+ clear_bit(TTY_LDISC, &tty->flags);
+ if (o_tty)
+ clear_bit(TTY_LDISC, &o_tty->flags);
spin_unlock_irqrestore(&tty_ldisc_lock, flags);
-
+
/*
* From this point on we know nobody has an ldisc
* usage reference, nor can they obtain one until
* we say so later on.
*/
-
- work = cancel_delayed_work(&tty->flip.work);
+
+ work = cancel_delayed_work(&tty->buf.work);
/*
- * Wait for ->hangup_work and ->flip.work handlers to terminate
+ * Wait for ->hangup_work and ->buf.work handlers to terminate
*/
flush_scheduled_work();
@@ -569,17 +1058,27 @@
*/
tty_ldisc_enable(tty);
+ if (o_tty)
+ tty_ldisc_enable(o_tty);
/* Restart it in case no characters kick it off. Safe if
already running */
- if(work)
- schedule_delayed_work(&tty->flip.work, 1);
+ if (work)
+ schedule_delayed_work(&tty->buf.work, 1);
return retval;
}
-/*
- * This routine returns a tty driver structure, given a device number
+/**
+ * get_tty_driver - find device of a tty
+ * @dev_t: device identifier
+ * @index: returns the index of the tty
+ *
+ * This routine returns a tty driver structure, given a device number
+ * and also passes back the index number.
+ *
+ * Locking: caller must hold tty_mutex
*/
+
static struct tty_driver *get_tty_driver(dev_t device, int *index)
{
struct tty_driver *p;
@@ -594,26 +1093,32 @@
return NULL;
}
-/*
- * If we try to write to, or set the state of, a terminal and we're
- * not in the foreground, send a SIGTTOU. If the signal is blocked or
- * ignored, go ahead and perform the operation. (POSIX 7.2)
+/**
+ * tty_check_change - check for POSIX terminal changes
+ * @tty: tty to check
+ *
+ * If we try to write to, or set the state of, a terminal and we're
+ * not in the foreground, send a SIGTTOU. If the signal is blocked or
+ * ignored, go ahead and perform the operation. (POSIX 7.2)
+ *
+ * Locking: none
*/
+
int tty_check_change(struct tty_struct * tty)
{
if (current->signal->tty != tty)
return 0;
- if (tty->pgrp <= 0) {
- printk(KERN_WARNING "tty_check_change: tty->pgrp <= 0!\n");
+ if (!tty->pgrp) {
+ printk(KERN_WARNING "tty_check_change: tty->pgrp == NULL!\n");
return 0;
}
- if (process_group(current) == tty->pgrp)
+ if (task_pgrp(current) == tty->pgrp)
return 0;
if (is_ignored(SIGTTOU))
return 0;
- if (is_orphaned_pgrp(process_group(current)))
+ if (is_current_pgrp_orphaned())
return -EIO;
- (void) kill_pg(process_group(current), SIGTTOU, 1);
+ (void) kill_pgrp(task_pgrp(current), SIGTTOU, 1);
return -ERESTARTSYS;
}
@@ -643,7 +1148,7 @@
return cmd == TIOCSPGRP ? -ENOTTY : -EIO;
}
-static struct file_operations tty_fops = {
+static const struct file_operations tty_fops = {
.llseek = no_llseek,
.read = tty_read,
.write = tty_write,
@@ -655,7 +1160,7 @@
};
#ifdef CONFIG_UNIX98_PTYS
-static struct file_operations ptmx_fops = {
+static const struct file_operations ptmx_fops = {
.llseek = no_llseek,
.read = tty_read,
.write = tty_write,
@@ -667,7 +1172,7 @@
};
#endif
-static struct file_operations console_fops = {
+static const struct file_operations console_fops = {
.llseek = no_llseek,
.read = tty_read,
.write = redirected_tty_write,
@@ -678,7 +1183,7 @@
.fasync = tty_fasync,
};
-static struct file_operations hung_up_tty_fops = {
+static const struct file_operations hung_up_tty_fops = {
.llseek = no_llseek,
.read = hung_up_tty_read,
.write = hung_up_tty_write,
@@ -735,15 +1240,49 @@
}
EXPORT_SYMBOL_GPL(tty_ldisc_flush);
+
+/**
+ * tty_reset_termios - reset terminal state
+ * @tty: tty to reset
+ *
+ * Restore a terminal to the driver default state
+ */
+
+static void tty_reset_termios(struct tty_struct *tty)
+{
+ mutex_lock(&tty->termios_mutex);
+ *tty->termios = tty->driver->init_termios;
+ tty->termios->c_ispeed = tty_termios_input_baud_rate(tty->termios);
+ tty->termios->c_ospeed = tty_termios_baud_rate(tty->termios);
+ mutex_unlock(&tty->termios_mutex);
+}
-/*
- * This can be called by the "eventd" kernel thread. That is process synchronous,
- * but doesn't hold any locks, so we need to make sure we have the appropriate
- * locks for what we're doing..
+/**
+ * do_tty_hangup - actual handler for hangup events
+ * @work: tty device
+ *
+ * This can be called by the "eventd" kernel thread. That is process
+ * synchronous but doesn't hold any locks, so we need to make sure we
+ * have the appropriate locks for what we're doing.
+ *
+ * The hangup event clears any pending redirections onto the hung up
+ * device. It ensures future writes will error and it does the needed
+ * line discipline hangup and signal delivery. The tty object itself
+ * remains intact.
+ *
+ * Locking:
+ * BKL
+ * redirect lock for undoing redirection
+ * file list lock for manipulating list of ttys
+ * tty_ldisc_lock from called functions
+ * termios_mutex resetting termios data
+ * tasklist_lock to walk task list for hangup event
+ * ->siglock to protect ->signal/->sighand
*/
-static void do_tty_hangup(void *data)
+static void do_tty_hangup(struct work_struct *work)
{
- struct tty_struct *tty = (struct tty_struct *) data;
+ struct tty_struct *tty =
+ container_of(work, struct tty_struct, hangup_work);
struct file * cons_filp = NULL;
struct file *filp, *f = NULL;
struct task_struct *p;
@@ -766,7 +1305,7 @@
check_tty_count(tty, "do_tty_hangup");
file_list_lock();
/* This breaks for file handles being sent over AF_UNIX sockets ? */
- list_for_each_entry(filp, &tty->tty_files, f_list) {
+ list_for_each_entry(filp, &tty->tty_files, f_u.fu_list) {
if (filp->f_op->write == redirected_tty_write)
cons_filp = filp;
if (filp->f_op->write != tty_write)
@@ -805,11 +1344,7 @@
* N_TTY.
*/
if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS)
- {
- down(&tty->termios_sem);
- *tty->termios = tty->driver->init_termios;
- up(&tty->termios_sem);
- }
+ tty_reset_termios(tty);
/* Defer ldisc switch */
/* tty_deferred_ldisc_switch(N_TTY);
@@ -818,23 +1353,30 @@
tty_release is called */
read_lock(&tasklist_lock);
- if (tty->session > 0) {
- do_each_task_pid(tty->session, PIDTYPE_SID, p) {
+ if (tty->session) {
+ do_each_pid_task(tty->session, PIDTYPE_SID, p) {
+ spin_lock_irq(&p->sighand->siglock);
if (p->signal->tty == tty)
p->signal->tty = NULL;
- if (!p->signal->leader)
+ if (!p->signal->leader) {
+ spin_unlock_irq(&p->sighand->siglock);
continue;
- send_group_sig_info(SIGHUP, SEND_SIG_PRIV, p);
- send_group_sig_info(SIGCONT, SEND_SIG_PRIV, p);
- if (tty->pgrp > 0)
- p->signal->tty_old_pgrp = tty->pgrp;
- } while_each_task_pid(tty->session, PIDTYPE_SID, p);
+ }
+ __group_send_sig_info(SIGHUP, SEND_SIG_PRIV, p);
+ __group_send_sig_info(SIGCONT, SEND_SIG_PRIV, p);
+ put_pid(p->signal->tty_old_pgrp); /* A noop */
+ if (tty->pgrp)
+ p->signal->tty_old_pgrp = get_pid(tty->pgrp);
+ spin_unlock_irq(&p->sighand->siglock);
+ } while_each_pid_task(tty->session, PIDTYPE_SID, p);
}
read_unlock(&tasklist_lock);
tty->flags = 0;
- tty->session = 0;
- tty->pgrp = -1;
+ put_pid(tty->session);
+ put_pid(tty->pgrp);
+ tty->session = NULL;
+ tty->pgrp = NULL;
tty->ctrl_status = 0;
/*
* If one of the devices matches a console pointer, we
@@ -864,6 +1406,14 @@
fput(f);
}
+/**
+ * tty_hangup - trigger a hangup event
+ * @tty: tty to hangup
+ *
+ * A carrier loss (virtual or otherwise) has occurred on this like
+ * schedule a hangup sequence to run after this event.
+ */
+
void tty_hangup(struct tty_struct * tty)
{
#ifdef TTY_DEBUG_HANGUP
@@ -876,6 +1426,15 @@
EXPORT_SYMBOL(tty_hangup);
+/**
+ * tty_vhangup - process vhangup
+ * @tty: tty to hangup
+ *
+ * The user has asked via system call for the terminal to be hung up.
+ * We do this synchronously so that when the syscall returns the process
+ * is complete. That guarantee is neccessary for security reasons.
+ */
+
void tty_vhangup(struct tty_struct * tty)
{
#ifdef TTY_DEBUG_HANGUP
@@ -883,10 +1442,18 @@
printk(KERN_DEBUG "%s vhangup...\n", tty_name(tty, buf));
#endif
- do_tty_hangup((void *) tty);
+ do_tty_hangup(&tty->hangup_work);
}
EXPORT_SYMBOL(tty_vhangup);
+/**
+ * tty_hung_up_p - was tty hung up
+ * @filp: file pointer of tty
+ *
+ * Return true if the tty has been subject to a vhangup or a carrier
+ * loss
+ */
+
int tty_hung_up_p(struct file * filp)
{
return (filp->f_op == &hung_up_tty_fops);
@@ -894,65 +1461,123 @@
EXPORT_SYMBOL(tty_hung_up_p);
-/*
- * This function is typically called only by the session leader, when
- * it wants to disassociate itself from its controlling tty.
+static void session_clear_tty(struct pid *session)
+{
+ struct task_struct *p;
+ do_each_pid_task(session, PIDTYPE_SID, p) {
+ proc_clear_tty(p);
+ } while_each_pid_task(session, PIDTYPE_SID, p);
+}
+
+/**
+ * disassociate_ctty - disconnect controlling tty
+ * @on_exit: true if exiting so need to "hang up" the session
*
- * It performs the following functions:
+ * This function is typically called only by the session leader, when
+ * it wants to disassociate itself from its controlling tty.
+ *
+ * It performs the following functions:
* (1) Sends a SIGHUP and SIGCONT to the foreground process group
* (2) Clears the tty from being controlling the session
* (3) Clears the controlling tty for all processes in the
* session group.
*
- * The argument on_exit is set to 1 if called when a process is
- * exiting; it is 0 if called by the ioctl TIOCNOTTY.
+ * The argument on_exit is set to 1 if called when a process is
+ * exiting; it is 0 if called by the ioctl TIOCNOTTY.
+ *
+ * Locking:
+ * BKL is taken for hysterical raisins
+ * tty_mutex is taken to protect tty
+ * ->siglock is taken to protect ->signal/->sighand
+ * tasklist_lock is taken to walk process list for sessions
+ * ->siglock is taken to protect ->signal/->sighand
*/
+
void disassociate_ctty(int on_exit)
{
struct tty_struct *tty;
- struct task_struct *p;
- int tty_pgrp = -1;
+ struct pid *tty_pgrp = NULL;
lock_kernel();
- down(&tty_sem);
- tty = current->signal->tty;
+ mutex_lock(&tty_mutex);
+ tty = get_current_tty();
if (tty) {
- tty_pgrp = tty->pgrp;
- up(&tty_sem);
+ tty_pgrp = get_pid(tty->pgrp);
+ mutex_unlock(&tty_mutex);
+ /* XXX: here we race, there is nothing protecting tty */
if (on_exit && tty->driver->type != TTY_DRIVER_TYPE_PTY)
tty_vhangup(tty);
- } else {
- if (current->signal->tty_old_pgrp) {
- kill_pg(current->signal->tty_old_pgrp, SIGHUP, on_exit);
- kill_pg(current->signal->tty_old_pgrp, SIGCONT, on_exit);
+ } else if (on_exit) {
+ struct pid *old_pgrp;
+ spin_lock_irq(¤t->sighand->siglock);
+ old_pgrp = current->signal->tty_old_pgrp;
+ current->signal->tty_old_pgrp = NULL;
+ spin_unlock_irq(¤t->sighand->siglock);
+ if (old_pgrp) {
+ kill_pgrp(old_pgrp, SIGHUP, on_exit);
+ kill_pgrp(old_pgrp, SIGCONT, on_exit);
+ put_pid(old_pgrp);
}
- up(&tty_sem);
+ mutex_unlock(&tty_mutex);
unlock_kernel();
return;
}
- if (tty_pgrp > 0) {
- kill_pg(tty_pgrp, SIGHUP, on_exit);
+ if (tty_pgrp) {
+ kill_pgrp(tty_pgrp, SIGHUP, on_exit);
if (!on_exit)
- kill_pg(tty_pgrp, SIGCONT, on_exit);
+ kill_pgrp(tty_pgrp, SIGCONT, on_exit);
+ put_pid(tty_pgrp);
}
- /* Must lock changes to tty_old_pgrp */
- down(&tty_sem);
- current->signal->tty_old_pgrp = 0;
- tty->session = 0;
- tty->pgrp = -1;
+ spin_lock_irq(¤t->sighand->siglock);
+ tty_pgrp = current->signal->tty_old_pgrp;
+ current->signal->tty_old_pgrp = NULL;
+ spin_unlock_irq(¤t->sighand->siglock);
+ put_pid(tty_pgrp);
+ mutex_lock(&tty_mutex);
+ /* It is possible that do_tty_hangup has free'd this tty */
+ tty = get_current_tty();
+ if (tty) {
+ put_pid(tty->session);
+ put_pid(tty->pgrp);
+ tty->session = NULL;
+ tty->pgrp = NULL;
+ } else {
+#ifdef TTY_DEBUG_HANGUP
+ printk(KERN_DEBUG "error attempted to write to tty [0x%p]"
+ " = NULL", tty);
+#endif
+ }
+ mutex_unlock(&tty_mutex);
+
/* Now clear signal->tty under the lock */
read_lock(&tasklist_lock);
- do_each_task_pid(current->signal->session, PIDTYPE_SID, p) {
- p->signal->tty = NULL;
- } while_each_task_pid(current->signal->session, PIDTYPE_SID, p);
+ session_clear_tty(task_session(current));
read_unlock(&tasklist_lock);
- up(&tty_sem);
unlock_kernel();
}
+
+/**
+ * stop_tty - propogate flow control
+ * @tty: tty to stop
+ *
+ * Perform flow control to the driver. For PTY/TTY pairs we
+ * must also propogate the TIOCKPKT status. May be called
+ * on an already stopped device and will not re-call the driver
+ * method.
+ *
+ * This functionality is used by both the line disciplines for
+ * halting incoming flow and by the driver. It may therefore be
+ * called from any context, may be under the tty atomic_write_lock
+ * but not always.
+ *
+ * Locking:
+ * Broken. Relies on BKL which is unsafe here.
+ */
+
void stop_tty(struct tty_struct *tty)
{
if (tty->stopped)
@@ -969,6 +1594,19 @@
EXPORT_SYMBOL(stop_tty);
+/**
+ * start_tty - propogate flow control
+ * @tty: tty to start
+ *
+ * Start a tty that has been stopped if at all possible. Perform
+ * any neccessary wakeups and propogate the TIOCPKT status. If this
+ * is the tty was previous stopped and is being started then the
+ * driver start method is invoked and the line discipline woken.
+ *
+ * Locking:
+ * Broken. Relies on BKL which is unsafe here.
+ */
+
void start_tty(struct tty_struct *tty)
{
if (!tty->stopped || tty->flow_stopped)
@@ -984,11 +1622,27 @@
/* If we have a running line discipline it may need kicking */
tty_wakeup(tty);
- wake_up_interruptible(&tty->write_wait);
}
EXPORT_SYMBOL(start_tty);
+/**
+ * tty_read - read method for tty device files
+ * @file: pointer to tty file
+ * @buf: user buffer
+ * @count: size of user buffer
+ * @ppos: unused
+ *
+ * Perform the read system call function on this terminal device. Checks
+ * for hung up devices before calling the line discipline method.
+ *
+ * Locking:
+ * Locks the line discipline internally while needed
+ * For historical reasons the line discipline read method is
+ * invoked under the BKL. This will go away in time so do not rely on it
+ * in new code. Multiple read calls may be outstanding in parallel.
+ */
+
static ssize_t tty_read(struct file * file, char __user * buf, size_t count,
loff_t *ppos)
{
@@ -998,7 +1652,7 @@
struct tty_ldisc *ld;
tty = (struct tty_struct *)file->private_data;
- inode = file->f_dentry->d_inode;
+ inode = file->f_path.dentry->d_inode;
if (tty_paranoia_check(tty, inode, "tty_read"))
return -EIO;
if (!tty || (test_bit(TTY_IO_ERROR, &tty->flags)))
@@ -1033,7 +1687,8 @@
ssize_t ret = 0, written = 0;
unsigned int chunk;
- if (down_interruptible(&tty->atomic_write)) {
+ /* FIXME: O_NDELAY ... */
+ if (mutex_lock_interruptible(&tty->atomic_write_lock)) {
return -ERESTARTSYS;
}
@@ -1049,6 +1704,9 @@
* layer has problems with bigger chunks. It will
* claim to be able to handle more characters than
* it actually does.
+ *
+ * FIXME: This can probably go away now except that 64K chunks
+ * are too likely to fail unless switched to vmalloc...
*/
chunk = 2048;
if (test_bit(TTY_NO_WRITE_SPLIT, &tty->flags))
@@ -1056,7 +1714,7 @@
if (count < chunk)
chunk = count;
- /* write_buf/write_cnt is protected by the atomic_write semaphore */
+ /* write_buf/write_cnt is protected by the atomic_write_lock mutex */
if (tty->write_cnt < chunk) {
unsigned char *buf;
@@ -1065,7 +1723,7 @@
buf = kmalloc(chunk, GFP_KERNEL);
if (!buf) {
- up(&tty->atomic_write);
+ mutex_unlock(&tty->atomic_write_lock);
return -ENOMEM;
}
kfree(tty->write_buf);
@@ -1097,20 +1755,38 @@
cond_resched();
}
if (written) {
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
inode->i_mtime = current_fs_time(inode->i_sb);
ret = written;
}
- up(&tty->atomic_write);
+ mutex_unlock(&tty->atomic_write_lock);
return ret;
}
+/**
+ * tty_write - write method for tty device file
+ * @file: tty file pointer
+ * @buf: user data to write
+ * @count: bytes to write
+ * @ppos: unused
+ *
+ * Write data to a tty device via the line discipline.
+ *
+ * Locking:
+ * Locks the line discipline as required
+ * Writes to the tty driver are serialized by the atomic_write_lock
+ * and are then processed in chunks to the device. The line discipline
+ * write method will not be involked in parallel for each device
+ * The line discipline write method is called under the big
+ * kernel lock for historical reasons. New code should not rely on this.
+ */
+
static ssize_t tty_write(struct file * file, const char __user * buf, size_t count,
loff_t *ppos)
{
struct tty_struct * tty;
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
ssize_t ret;
struct tty_ldisc *ld;
@@ -1153,7 +1829,18 @@
static char ptychar[] = "pqrstuvwxyzabcde";
-static inline void pty_line_name(struct tty_driver *driver, int index, char *p)
+/**
+ * pty_line_name - generate name for a pty
+ * @driver: the tty driver in use
+ * @index: the minor number
+ * @p: output buffer of at least 6 bytes
+ *
+ * Generate a name from a driver reference and write it to the output
+ * buffer.
+ *
+ * Locking: None
+ */
+static void pty_line_name(struct tty_driver *driver, int index, char *p)
{
int i = index + driver->name_base;
/* ->name is initialized to "ttyp", but "tty" is expected */
@@ -1162,28 +1849,71 @@
ptychar[i >> 4 & 0xf], i & 0xf);
}
-static inline void tty_line_name(struct tty_driver *driver, int index, char *p)
+/**
+ * pty_line_name - generate name for a tty
+ * @driver: the tty driver in use
+ * @index: the minor number
+ * @p: output buffer of at least 7 bytes
+ *
+ * Generate a name from a driver reference and write it to the output
+ * buffer.
+ *
+ * Locking: None
+ */
+static void tty_line_name(struct tty_driver *driver, int index, char *p)
{
sprintf(p, "%s%d", driver->name, index + driver->name_base);
}
-/*
+/**
+ * init_dev - initialise a tty device
+ * @driver: tty driver we are opening a device on
+ * @idx: device index
+ * @tty: returned tty structure
+ *
+ * Prepare a tty device. This may not be a "new" clean device but
+ * could also be an active device. The pty drivers require special
+ * handling because of this.
+ *
+ * Locking:
+ * The function is called under the tty_mutex, which
+ * protects us from the tty struct or driver itself going away.
+ *
+ * On exit the tty device has the line discipline attached and
+ * a reference count of 1. If a pair was created for pty/tty use
+ * and the other was a pty master then it too has a reference count of 1.
+ *
* WSH 06/09/97: Rewritten to remove races and properly clean up after a
- * failed open. The new code protects the open with a semaphore, so it's
- * really quite straightforward. The semaphore locking can probably be
+ * failed open. The new code protects the open with a mutex, so it's
+ * really quite straightforward. The mutex locking can probably be
* relaxed for the (most common) case of reopening a tty.
*/
+
static int init_dev(struct tty_driver *driver, int idx,
struct tty_struct **ret_tty)
{
struct tty_struct *tty, *o_tty;
- struct termios *tp, **tp_loc, *o_tp, **o_tp_loc;
- struct termios *ltp, **ltp_loc, *o_ltp, **o_ltp_loc;
- int retval=0;
+ struct ktermios *tp, **tp_loc, *o_tp, **o_tp_loc;
+ struct ktermios *ltp, **ltp_loc, *o_ltp, **o_ltp_loc;
+ int retval = 0;
/* check whether we're reopening an existing tty */
if (driver->flags & TTY_DRIVER_DEVPTS_MEM) {
tty = devpts_get_tty(idx);
+ /*
+ * If we don't have a tty here on a slave open, it's because
+ * the master already started the close process and there's
+ * no relation between devpts file and tty anymore.
+ */
+ if (!tty && driver->subtype == PTY_TYPE_SLAVE) {
+ retval = -EIO;
+ goto end_init;
+ }
+ /*
+ * It's safe from now on because init_dev() is called with
+ * tty_mutex held and release_dev() won't change tty->count
+ * or tty->flags without having to grab tty_mutex
+ */
if (tty && driver->subtype == PTY_TYPE_MASTER)
tty = tty->link;
} else {
@@ -1225,7 +1955,7 @@
}
if (!*tp_loc) {
- tp = (struct termios *) kmalloc(sizeof(struct termios),
+ tp = (struct ktermios *) kmalloc(sizeof(struct ktermios),
GFP_KERNEL);
if (!tp)
goto free_mem_out;
@@ -1233,11 +1963,11 @@
}
if (!*ltp_loc) {
- ltp = (struct termios *) kmalloc(sizeof(struct termios),
+ ltp = (struct ktermios *) kmalloc(sizeof(struct ktermios),
GFP_KERNEL);
if (!ltp)
goto free_mem_out;
- memset(ltp, 0, sizeof(struct termios));
+ memset(ltp, 0, sizeof(struct ktermios));
}
if (driver->type == TTY_DRIVER_TYPE_PTY) {
@@ -1258,19 +1988,19 @@
}
if (!*o_tp_loc) {
- o_tp = (struct termios *)
- kmalloc(sizeof(struct termios), GFP_KERNEL);
+ o_tp = (struct ktermios *)
+ kmalloc(sizeof(struct ktermios), GFP_KERNEL);
if (!o_tp)
goto free_mem_out;
*o_tp = driver->other->init_termios;
}
if (!*o_ltp_loc) {
- o_ltp = (struct termios *)
- kmalloc(sizeof(struct termios), GFP_KERNEL);
+ o_ltp = (struct ktermios *)
+ kmalloc(sizeof(struct ktermios), GFP_KERNEL);
if (!o_ltp)
goto free_mem_out;
- memset(o_ltp, 0, sizeof(struct termios));
+ memset(o_ltp, 0, sizeof(struct ktermios));
}
/*
@@ -1296,7 +2026,7 @@
/*
* All structures have been allocated, so now we install them.
- * Failures after this point use release_mem to clean up, so
+ * Failures after this point use release_tty to clean up, so
* there's no need to null out the local pointers.
*/
if (!(driver->flags & TTY_DRIVER_DEVPTS_MEM)) {
@@ -1309,13 +2039,16 @@
*ltp_loc = ltp;
tty->termios = *tp_loc;
tty->termios_locked = *ltp_loc;
+ /* Compatibility until drivers always set this */
+ tty->termios->c_ispeed = tty_termios_input_baud_rate(tty->termios);
+ tty->termios->c_ospeed = tty_termios_baud_rate(tty->termios);
driver->refcount++;
tty->count++;
/*
* Structures all installed ... call the ldisc open routines.
- * If we fail here just call release_mem to clean up. No need
- * to decrement the use counts, as release_mem doesn't care.
+ * If we fail here just call release_tty to clean up. No need
+ * to decrement the use counts, as release_tty doesn't care.
*/
if (tty->ldisc.open) {
@@ -1367,20 +2100,17 @@
success:
*ret_tty = tty;
- /* All paths come through here to release the semaphore */
+ /* All paths come through here to release the mutex */
end_init:
return retval;
/* Release locally allocated memory ... nothing placed in slots */
free_mem_out:
- if (o_tp)
- kfree(o_tp);
+ kfree(o_tp);
if (o_tty)
free_tty_struct(o_tty);
- if (ltp)
- kfree(ltp);
- if (tp)
- kfree(tp);
+ kfree(ltp);
+ kfree(tp);
free_tty_struct(tty);
fail_no_mem:
@@ -1388,48 +2118,36 @@
retval = -ENOMEM;
goto end_init;
- /* call the tty release_mem routine to clean out this slot */
+ /* call the tty release_tty routine to clean out this slot */
release_mem_out:
- printk(KERN_INFO "init_dev: ldisc open failed, "
- "clearing slot %d\n", idx);
- release_mem(tty, idx);
+ if (printk_ratelimit())
+ printk(KERN_INFO "init_dev: ldisc open failed, "
+ "clearing slot %d\n", idx);
+ release_tty(tty, idx);
goto end_init;
}
-/*
- * Releases memory associated with a tty structure, and clears out the
- * driver table slots.
+/**
+ * release_one_tty - release tty structure memory
+ *
+ * Releases memory associated with a tty structure, and clears out the
+ * driver table slots. This function is called when a device is no longer
+ * in use. It also gets called when setup of a device fails.
+ *
+ * Locking:
+ * tty_mutex - sometimes only
+ * takes the file list lock internally when working on the list
+ * of ttys that the driver keeps.
+ * FIXME: should we require tty_mutex is held here ??
*/
-static void release_mem(struct tty_struct *tty, int idx)
+static void release_one_tty(struct tty_struct *tty, int idx)
{
- struct tty_struct *o_tty;
- struct termios *tp;
int devpts = tty->driver->flags & TTY_DRIVER_DEVPTS_MEM;
+ struct ktermios *tp;
- if ((o_tty = tty->link) != NULL) {
- if (!devpts)
- o_tty->driver->ttys[idx] = NULL;
- if (o_tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) {
- tp = o_tty->termios;
- if (!devpts)
- o_tty->driver->termios[idx] = NULL;
- kfree(tp);
-
- tp = o_tty->termios_locked;
- if (!devpts)
- o_tty->driver->termios_locked[idx] = NULL;
- kfree(tp);
- }
- o_tty->magic = 0;
- o_tty->driver->refcount--;
- file_list_lock();
- list_del_init(&o_tty->tty_files);
- file_list_unlock();
- free_tty_struct(o_tty);
- }
-
if (!devpts)
tty->driver->ttys[idx] = NULL;
+
if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) {
tp = tty->termios;
if (!devpts)
@@ -1442,15 +2160,39 @@
kfree(tp);
}
+
tty->magic = 0;
tty->driver->refcount--;
+
file_list_lock();
list_del_init(&tty->tty_files);
file_list_unlock();
- module_put(tty->driver->owner);
+
free_tty_struct(tty);
}
+/**
+ * release_tty - release tty structure memory
+ *
+ * Release both @tty and a possible linked partner (think pty pair),
+ * and decrement the refcount of the backing module.
+ *
+ * Locking:
+ * tty_mutex - sometimes only
+ * takes the file list lock internally when working on the list
+ * of ttys that the driver keeps.
+ * FIXME: should we require tty_mutex is held here ??
+ */
+static void release_tty(struct tty_struct *tty, int idx)
+{
+ struct tty_driver *driver = tty->driver;
+
+ if (tty->link)
+ release_one_tty(tty->link, idx);
+ release_one_tty(tty, idx);
+ module_put(driver->owner);
+}
+
/*
* Even releasing the tty structures is a tricky business.. We have
* to be very careful that the structures are all released at the
@@ -1463,13 +2205,13 @@
{
struct tty_struct *tty, *o_tty;
int pty_master, tty_closing, o_tty_closing, do_sleep;
- int devpts_master, devpts;
+ int devpts;
int idx;
char buf[64];
unsigned long flags;
tty = (struct tty_struct *)filp->private_data;
- if (tty_paranoia_check(tty, filp->f_dentry->d_inode, "release_dev"))
+ if (tty_paranoia_check(tty, filp->f_path.dentry->d_inode, "release_dev"))
return;
check_tty_count(tty, "release_dev");
@@ -1480,7 +2222,6 @@
pty_master = (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
tty->driver->subtype == PTY_TYPE_MASTER);
devpts = (tty->driver->flags & TTY_DRIVER_DEVPTS_MEM) != 0;
- devpts_master = pty_master && devpts;
o_tty = tty->link;
#ifdef TTY_PARANOIA_CHECK
@@ -1567,11 +2308,10 @@
/* Guard against races with tty->count changes elsewhere and
opens on /dev/tty */
- down(&tty_sem);
+ mutex_lock(&tty_mutex);
tty_closing = tty->count <= 1;
o_tty_closing = o_tty &&
(o_tty->count <= (pty_master ? 1 : 0));
- up(&tty_sem);
do_sleep = 0;
if (tty_closing) {
@@ -1599,6 +2339,7 @@
printk(KERN_WARNING "release_dev: %s: read/write wait queue "
"active!\n", tty_name(tty, buf));
+ mutex_unlock(&tty_mutex);
schedule();
}
@@ -1607,8 +2348,6 @@
* both sides, and we've completed the last operation that could
* block, so it's safe to proceed with closing.
*/
-
- down(&tty_sem);
if (pty_master) {
if (--o_tty->count < 0) {
printk(KERN_WARNING "release_dev: bad pty slave count "
@@ -1622,7 +2361,6 @@
tty->count, tty_name(tty, buf));
tty->count = 0;
}
- up(&tty_sem);
/*
* We've decremented tty->count, so we need to remove this file
@@ -1654,19 +2392,15 @@
* tty.
*/
if (tty_closing || o_tty_closing) {
- struct task_struct *p;
-
read_lock(&tasklist_lock);
- do_each_task_pid(tty->session, PIDTYPE_SID, p) {
- p->signal->tty = NULL;
- } while_each_task_pid(tty->session, PIDTYPE_SID, p);
+ session_clear_tty(tty->session);
if (o_tty)
- do_each_task_pid(o_tty->session, PIDTYPE_SID, p) {
- p->signal->tty = NULL;
- } while_each_task_pid(o_tty->session, PIDTYPE_SID, p);
+ session_clear_tty(o_tty->session);
read_unlock(&tasklist_lock);
}
+ mutex_unlock(&tty_mutex);
+
/* check whether both sides are closing ... */
if (!tty_closing || (o_tty && !o_tty_closing))
return;
@@ -1680,11 +2414,10 @@
* race with the set_ldisc code path.
*/
clear_bit(TTY_LDISC, &tty->flags);
- clear_bit(TTY_DONT_FLIP, &tty->flags);
- cancel_delayed_work(&tty->flip.work);
+ cancel_delayed_work(&tty->buf.work);
/*
- * Wait for ->hangup_work and ->flip.work handlers to terminate
+ * Wait for ->hangup_work and ->buf.work handlers to terminate
*/
flush_scheduled_work();
@@ -1727,10 +2460,10 @@
tty_set_termios_ldisc(o_tty,N_TTY);
}
/*
- * The release_mem function takes care of the details of clearing
+ * The release_tty function takes care of the details of clearing
* the slots and preserving the termios structure.
*/
- release_mem(tty, idx);
+ release_tty(tty, idx);
#ifdef CONFIG_UNIX98_PTYS
/* Make this pty number available for reallocation */
@@ -1743,18 +2476,27 @@
}
-/*
- * tty_open and tty_release keep up the tty count that contains the
- * number of opens done on a tty. We cannot use the inode-count, as
- * different inodes might point to the same tty.
+/**
+ * tty_open - open a tty device
+ * @inode: inode of device file
+ * @filp: file pointer to tty
*
- * Open-counting is needed for pty masters, as well as for keeping
- * track of serial lines: DTR is dropped when the last close happens.
- * (This is not done solely through tty->count, now. - Ted 1/27/92)
+ * tty_open and tty_release keep up the tty count that contains the
+ * number of opens done on a tty. We cannot use the inode-count, as
+ * different inodes might point to the same tty.
*
- * The termios state of a pty is reset on first open so that
- * settings don't persist across reuse.
+ * Open-counting is needed for pty masters, as well as for keeping
+ * track of serial lines: DTR is dropped when the last close happens.
+ * (This is not done solely through tty->count, now. - Ted 1/27/92)
+ *
+ * The termios state of a pty is reset on first open so that
+ * settings don't persist across reuse.
+ *
+ * Locking: tty_mutex protects tty, get_tty_driver and init_dev work.
+ * tty->count should protect the rest.
+ * ->siglock protects ->signal/->sighand
*/
+
static int tty_open(struct inode * inode, struct file * filp)
{
struct tty_struct *tty;
@@ -1763,6 +2505,7 @@
int index;
dev_t device = inode->i_rdev;
unsigned short saved_flags = filp->f_flags;
+ struct pid *old_pgrp;
nonseekable_open(inode, filp);
@@ -1771,15 +2514,16 @@
index = -1;
retval = 0;
- down(&tty_sem);
+ mutex_lock(&tty_mutex);
if (device == MKDEV(TTYAUX_MAJOR,0)) {
- if (!current->signal->tty) {
- up(&tty_sem);
+ tty = get_current_tty();
+ if (!tty) {
+ mutex_unlock(&tty_mutex);
return -ENXIO;
}
- driver = current->signal->tty->driver;
- index = current->signal->tty->index;
+ driver = tty->driver;
+ index = tty->index;
filp->f_flags |= O_NONBLOCK; /* Don't let /dev/tty block */
/* noctty = 1; */
goto got_driver;
@@ -1811,18 +2555,18 @@
noctty = 1;
goto got_driver;
}
- up(&tty_sem);
+ mutex_unlock(&tty_mutex);
return -ENODEV;
}
driver = get_tty_driver(device, &index);
if (!driver) {
- up(&tty_sem);
+ mutex_unlock(&tty_mutex);
return -ENODEV;
}
got_driver:
retval = init_dev(driver, index, &tty);
- up(&tty_sem);
+ mutex_unlock(&tty_mutex);
if (retval)
return retval;
@@ -1864,21 +2608,34 @@
filp->f_op = &tty_fops;
goto retry_open;
}
+
+ old_pgrp = NULL;
+ mutex_lock(&tty_mutex);
+ spin_lock_irq(¤t->sighand->siglock);
if (!noctty &&
current->signal->leader &&
!current->signal->tty &&
- tty->session == 0) {
- task_lock(current);
- current->signal->tty = tty;
- task_unlock(current);
- current->signal->tty_old_pgrp = 0;
- tty->session = current->signal->session;
- tty->pgrp = process_group(current);
- }
+ tty->session == NULL)
+ old_pgrp = __proc_set_tty(current, tty);
+ spin_unlock_irq(¤t->sighand->siglock);
+ mutex_unlock(&tty_mutex);
+ put_pid(old_pgrp);
return 0;
}
#ifdef CONFIG_UNIX98_PTYS
+/**
+ * ptmx_open - open a unix 98 pty master
+ * @inode: inode of device file
+ * @filp: file pointer to tty
+ *
+ * Allocate a unix98 pty master device from the ptmx driver.
+ *
+ * Locking: tty_mutex protects theinit_dev work. tty->count should
+ protect the rest.
+ * allocated_ptys_lock handles the list of free pty numbers
+ */
+
static int ptmx_open(struct inode * inode, struct file * filp)
{
struct tty_struct *tty;
@@ -1908,9 +2665,9 @@
}
up(&allocated_ptys_lock);
- down(&tty_sem);
+ mutex_lock(&tty_mutex);
retval = init_dev(ptm_driver, index, &tty);
- up(&tty_sem);
+ mutex_unlock(&tty_mutex);
if (retval)
goto out;
@@ -1929,6 +2686,7 @@
return 0;
out1:
release_dev(filp);
+ return retval;
out:
down(&allocated_ptys_lock);
idr_remove(&allocated_ptys, index);
@@ -1937,6 +2695,18 @@
}
#endif
+/**
+ * tty_release - vfs callback for close
+ * @inode: inode of tty
+ * @filp: file pointer for handle to tty
+ *
+ * Called the last time each file handle is closed that references
+ * this tty. There may however be several such references.
+ *
+ * Locking:
+ * Takes bkl. See release_dev
+ */
+
static int tty_release(struct inode * inode, struct file * filp)
{
lock_kernel();
@@ -1945,7 +2715,18 @@
return 0;
}
-/* No kernel lock held - fine */
+/**
+ * tty_poll - check tty status
+ * @filp: file being polled
+ * @wait: poll wait structures to update
+ *
+ * Call the line discipline polling method to obtain the poll
+ * status of the device.
+ *
+ * Locking: locks called line discipline but ldisc poll method
+ * may be re-entered freely by other callers.
+ */
+
static unsigned int tty_poll(struct file * filp, poll_table * wait)
{
struct tty_struct * tty;
@@ -1953,7 +2734,7 @@
int ret = 0;
tty = (struct tty_struct *)filp->private_data;
- if (tty_paranoia_check(tty, filp->f_dentry->d_inode, "tty_poll"))
+ if (tty_paranoia_check(tty, filp->f_path.dentry->d_inode, "tty_poll"))
return 0;
ld = tty_ldisc_ref_wait(tty);
@@ -1969,7 +2750,7 @@
int retval;
tty = (struct tty_struct *)filp->private_data;
- if (tty_paranoia_check(tty, filp->f_dentry->d_inode, "tty_fasync"))
+ if (tty_paranoia_check(tty, filp->f_path.dentry->d_inode, "tty_fasync"))
return 0;
retval = fasync_helper(fd, filp, on, &tty->fasync);
@@ -1977,9 +2758,18 @@
return retval;
if (on) {
+ enum pid_type type;
+ struct pid *pid;
if (!waitqueue_active(&tty->read_wait))
tty->minimum_to_wake = 1;
- retval = f_setown(filp, (-tty->pgrp) ? : current->pid, 0);
+ if (tty->pgrp) {
+ pid = tty->pgrp;
+ type = PIDTYPE_PGID;
+ } else {
+ pid = task_pid(current);
+ type = PIDTYPE_PID;
+ }
+ retval = __f_setown(filp, pid, type, 0);
if (retval)
return retval;
} else {
@@ -1989,6 +2779,23 @@
return 0;
}
+/**
+ * tiocsti - fake input character
+ * @tty: tty to fake input into
+ * @p: pointer to character
+ *
+ * Fake input to a tty device. Does the neccessary locking and
+ * input management.
+ *
+ * FIXME: does not honour flow control ??
+ *
+ * Locking:
+ * Called functions take tty_ldisc_lock
+ * current->signal->tty check is safe without locks
+ *
+ * FIXME: may race normal receive processing
+ */
+
static int tiocsti(struct tty_struct *tty, char __user *p)
{
char ch, mbz = 0;
@@ -2004,13 +2811,45 @@
return 0;
}
+/**
+ * tiocgwinsz - implement window query ioctl
+ * @tty; tty
+ * @arg: user buffer for result
+ *
+ * Copies the kernel idea of the window size into the user buffer.
+ *
+ * Locking: tty->termios_mutex is taken to ensure the winsize data
+ * is consistent.
+ */
+
static int tiocgwinsz(struct tty_struct *tty, struct winsize __user * arg)
{
- if (copy_to_user(arg, &tty->winsize, sizeof(*arg)))
- return -EFAULT;
- return 0;
+ int err;
+
+ mutex_lock(&tty->termios_mutex);
+ err = copy_to_user(arg, &tty->winsize, sizeof(*arg));
+ mutex_unlock(&tty->termios_mutex);
+
+ return err ? -EFAULT: 0;
}
+/**
+ * tiocswinsz - implement window size set ioctl
+ * @tty; tty
+ * @arg: user buffer for result
+ *
+ * Copies the user idea of the window size to the kernel. Traditionally
+ * this is just advisory information but for the Linux console it
+ * actually has driver level meaning and triggers a VC resize.
+ *
+ * Locking:
+ * Called function use the console_sem is used to ensure we do
+ * not try and resize the console twice at once.
+ * The tty->termios_mutex is used to ensure we don't double
+ * resize and get confused. Lock order - tty->termios_mutex before
+ * console sem
+ */
+
static int tiocswinsz(struct tty_struct *tty, struct tty_struct *real_tty,
struct winsize __user * arg)
{
@@ -2018,28 +2857,40 @@
if (copy_from_user(&tmp_ws, arg, sizeof(*arg)))
return -EFAULT;
+
+ mutex_lock(&tty->termios_mutex);
if (!memcmp(&tmp_ws, &tty->winsize, sizeof(*arg)))
- return 0;
+ goto done;
+
#ifdef CONFIG_VT
if (tty->driver->type == TTY_DRIVER_TYPE_CONSOLE) {
- int rc;
-
- acquire_console_sem();
- rc = vc_resize(tty->driver_data, tmp_ws.ws_col, tmp_ws.ws_row);
- release_console_sem();
- if (rc)
- return -ENXIO;
+ if (vc_lock_resize(tty->driver_data, tmp_ws.ws_col,
+ tmp_ws.ws_row)) {
+ mutex_unlock(&tty->termios_mutex);
+ return -ENXIO;
+ }
}
#endif
- if (tty->pgrp > 0)
- kill_pg(tty->pgrp, SIGWINCH, 1);
- if ((real_tty->pgrp != tty->pgrp) && (real_tty->pgrp > 0))
- kill_pg(real_tty->pgrp, SIGWINCH, 1);
+ if (tty->pgrp)
+ kill_pgrp(tty->pgrp, SIGWINCH, 1);
+ if ((real_tty->pgrp != tty->pgrp) && real_tty->pgrp)
+ kill_pgrp(real_tty->pgrp, SIGWINCH, 1);
tty->winsize = tmp_ws;
real_tty->winsize = tmp_ws;
+done:
+ mutex_unlock(&tty->termios_mutex);
return 0;
}
+/**
+ * tioccons - allow admin to move logical console
+ * @file: the file to become console
+ *
+ * Allow the adminstrator to move the redirected console device
+ *
+ * Locking: uses redirect_lock to guard the redirect information
+ */
+
static int tioccons(struct file *file)
{
if (!capable(CAP_SYS_ADMIN))
@@ -2065,6 +2916,17 @@
return 0;
}
+/**
+ * fionbio - non blocking ioctl
+ * @file: file to set blocking...
[truncated message content] |
|
From: <jsi...@us...> - 2007-04-11 19:49:20
|
Revision: 2370
http://linuxconsole.svn.sourceforge.net/linuxconsole/?rev=2370&view=rev
Author: jsimmons
Date: 2007-04-11 12:49:18 -0700 (Wed, 11 Apr 2007)
Log Message:
-----------
update to 2.6.12
Modified Paths:
--------------
branches/ruby-2.6.21/ruby-2.6/drivers/char/Makefile
Modified: branches/ruby-2.6.21/ruby-2.6/drivers/char/Makefile
===================================================================
--- branches/ruby-2.6.21/ruby-2.6/drivers/char/Makefile 2007-04-11 19:44:35 UTC (rev 2369)
+++ branches/ruby-2.6.21/ruby-2.6/drivers/char/Makefile 2007-04-11 19:49:18 UTC (rev 2370)
@@ -31,68 +31,81 @@
obj-$(CONFIG_A2232) += ser_a2232.o generic_serial.o
obj-$(CONFIG_ATARI_DSP56K) += dsp56k.o
obj-$(CONFIG_MOXA_SMARTIO) += mxser.o
-obj-$(CONFIG_COMPUTONE) += ip2.o ip2main.o
+obj-$(CONFIG_MOXA_SMARTIO_NEW) += mxser_new.o
+obj-$(CONFIG_COMPUTONE) += ip2/
obj-$(CONFIG_RISCOM8) += riscom8.o
obj-$(CONFIG_ISI) += isicom.o
obj-$(CONFIG_SYNCLINK) += synclink.o
obj-$(CONFIG_SYNCLINKMP) += synclinkmp.o
+obj-$(CONFIG_SYNCLINK_GT) += synclink_gt.o
obj-$(CONFIG_N_HDLC) += n_hdlc.o
obj-$(CONFIG_AMIGA_BUILTIN_SERIAL) += amiserial.o
obj-$(CONFIG_SX) += sx.o generic_serial.o
obj-$(CONFIG_RIO) += rio/ generic_serial.o
-obj-$(CONFIG_HVC_CONSOLE) += hvc_console.o hvsi.o
+obj-$(CONFIG_HVC_CONSOLE) += hvc_vio.o hvsi.o
+obj-$(CONFIG_HVC_ISERIES) += hvc_iseries.o
+obj-$(CONFIG_HVC_RTAS) += hvc_rtas.o
+obj-$(CONFIG_HVC_BEAT) += hvc_beat.o
+obj-$(CONFIG_HVC_DRIVER) += hvc_console.o
obj-$(CONFIG_RAW_DRIVER) += raw.o
obj-$(CONFIG_SGI_SNSC) += snsc.o snsc_event.o
+obj-$(CONFIG_MSPEC) += mspec.o
obj-$(CONFIG_MMTIMER) += mmtimer.o
-obj-$(CONFIG_VIOCONS) += viocons.o
+obj-$(CONFIG_VIOCONS) += viocons.o
obj-$(CONFIG_VIOTAPE) += viotape.o
obj-$(CONFIG_HVCS) += hvcs.o
obj-$(CONFIG_SGI_MBCS) += mbcs.o
+obj-$(CONFIG_BRIQ_PANEL) += briq_panel.o
-obj-$(CONFIG_PRINTER) += lp.o
-obj-$(CONFIG_TIPAR) += tipar.o
+obj-$(CONFIG_PRINTER) += lp.o
+obj-$(CONFIG_TIPAR) += tipar.o
-obj-$(CONFIG_DTLK) += dtlk.o
-obj-$(CONFIG_R3964) += n_r3964.o
-obj-$(CONFIG_APPLICOM) += applicom.o
-obj-$(CONFIG_SONYPI) += sonypi.o
-obj-$(CONFIG_RTC) += rtc.o
-obj-$(CONFIG_HPET) += hpet.o
-obj-$(CONFIG_GEN_RTC) += genrtc.o
-obj-$(CONFIG_EFI_RTC) += efirtc.o
-obj-$(CONFIG_SGI_DS1286) += ds1286.o
-obj-$(CONFIG_SGI_IP27_RTC) += ip27-rtc.o
-obj-$(CONFIG_DS1302) += ds1302.o
-obj-$(CONFIG_S3C2410_RTC) += s3c2410-rtc.o
-obj-$(CONFIG_RTC_VR41XX) += vr41xx_rtc.o
+obj-$(CONFIG_APM_EMULATION) += apm-emulation.o
+
+obj-$(CONFIG_DTLK) += dtlk.o
+obj-$(CONFIG_R3964) += n_r3964.o
+obj-$(CONFIG_APPLICOM) += applicom.o
+obj-$(CONFIG_SONYPI) += sonypi.o
+obj-$(CONFIG_RTC) += rtc.o
+obj-$(CONFIG_HPET) += hpet.o
+obj-$(CONFIG_GEN_RTC) += genrtc.o
+obj-$(CONFIG_EFI_RTC) += efirtc.o
+obj-$(CONFIG_SGI_DS1286) += ds1286.o
+obj-$(CONFIG_SGI_IP27_RTC) += ip27-rtc.o
+obj-$(CONFIG_DS1302) += ds1302.o
ifeq ($(CONFIG_GENERIC_NVRAM),y)
- obj-$(CONFIG_NVRAM) += generic_nvram.o
+ obj-$(CONFIG_NVRAM) += generic_nvram.o
else
- obj-$(CONFIG_NVRAM) += nvram.o
+ obj-$(CONFIG_NVRAM) += nvram.o
endif
-obj-$(CONFIG_TOSHIBA) += toshiba.o
-obj-$(CONFIG_I8K) += i8k.o
-obj-$(CONFIG_DS1620) += ds1620.o
-obj-$(CONFIG_HW_RANDOM) += hw_random.o
-obj-$(CONFIG_FTAPE) += ftape/
-obj-$(CONFIG_COBALT_LCD) += lcd.o
-obj-$(CONFIG_PPDEV) += ppdev.o
-obj-$(CONFIG_NWBUTTON) += nwbutton.o
-obj-$(CONFIG_NWFLASH) += nwflash.o
-obj-$(CONFIG_SCx200_GPIO) += scx200_gpio.o
-obj-$(CONFIG_TANBAC_TB0219) += tb0219.o
+obj-$(CONFIG_TOSHIBA) += toshiba.o
+obj-$(CONFIG_I8K) += i8k.o
+obj-$(CONFIG_DS1620) += ds1620.o
+obj-$(CONFIG_HW_RANDOM) += hw_random/
+obj-$(CONFIG_COBALT_LCD) += lcd.o
+obj-$(CONFIG_PPDEV) += ppdev.o
+obj-$(CONFIG_NWBUTTON) += nwbutton.o
+obj-$(CONFIG_NWFLASH) += nwflash.o
+obj-$(CONFIG_SCx200_GPIO) += scx200_gpio.o
+obj-$(CONFIG_PC8736x_GPIO) += pc8736x_gpio.o
+obj-$(CONFIG_NSC_GPIO) += nsc_gpio.o
+obj-$(CONFIG_CS5535_GPIO) += cs5535_gpio.o
+obj-$(CONFIG_GPIO_VR41XX) += vr41xx_giu.o
+obj-$(CONFIG_TANBAC_TB0219) += tb0219.o
+obj-$(CONFIG_TELCLOCK) += tlclk.o
-obj-$(CONFIG_WATCHDOG) += watchdog/
-obj-$(CONFIG_MWAVE) += mwave/
-obj-$(CONFIG_AGP) += agp/
-obj-$(CONFIG_DRM) += drm/
-obj-$(CONFIG_PCMCIA) += pcmcia/
-obj-$(CONFIG_IPMI_HANDLER) += ipmi/
+obj-$(CONFIG_WATCHDOG) += watchdog/
+obj-$(CONFIG_MWAVE) += mwave/
+obj-$(CONFIG_AGP) += agp/
+obj-$(CONFIG_DRM) += drm/
+obj-$(CONFIG_PCMCIA) += pcmcia/
+obj-$(CONFIG_IPMI_HANDLER) += ipmi/
-obj-$(CONFIG_HANGCHECK_TIMER) += hangcheck-timer.o
-obj-$(CONFIG_TCG_TPM) += tpm/
+obj-$(CONFIG_HANGCHECK_TIMER) += hangcheck-timer.o
+obj-$(CONFIG_TCG_TPM) += tpm/
+
# Files generated that shall be removed upon make clean
-clean-files := consolemap_deftbl.c defkeymap.c qtronixmap.c
+clean-files := consolemap_deftbl.c defkeymap.c
quiet_cmd_conmk = CONMK $@
cmd_conmk = scripts/conmakehash $< > $@
@@ -102,8 +115,6 @@
$(obj)/defkeymap.o: $(obj)/defkeymap.c
-$(obj)/qtronixmap.o: $(obj)/qtronixmap.c
-
# Uncomment if you're changing the keymap and have an appropriate
# loadkeys version for the map. By default, we'll use the shipped
# versions.
@@ -111,7 +122,7 @@
ifdef GENERATE_KEYMAP
-$(obj)/defkeymap.c $(obj)/qtronixmap.c: $(obj)/%.c: $(src)/%.map
+$(obj)/defkeymap.c $(obj)/%.c: $(src)/%.map
loadkeys --mktable $< > $@.tmp
sed -e 's/^static *//' $@.tmp > $@
rm $@.tmp
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <jsi...@us...> - 2007-04-11 19:44:48
|
Revision: 2369
http://linuxconsole.svn.sourceforge.net/linuxconsole/?rev=2369&view=rev
Author: jsimmons
Date: 2007-04-11 12:44:35 -0700 (Wed, 11 Apr 2007)
Log Message:
-----------
updated to 2.6.12
Modified Paths:
--------------
branches/ruby-2.6.21/ruby-2.6/drivers/char/selection.c
Modified: branches/ruby-2.6.21/ruby-2.6/drivers/char/selection.c
===================================================================
--- branches/ruby-2.6.21/ruby-2.6/drivers/char/selection.c 2007-04-11 19:38:01 UTC (rev 2368)
+++ branches/ruby-2.6.21/ruby-2.6/drivers/char/selection.c 2007-04-11 19:44:35 UTC (rev 2369)
@@ -31,7 +31,7 @@
/* Variables for selection control. */
/* Use a dynamic buffer, instead of static (Dec 1994) */
-struct vc_data *sel_cons; /* must not be disallocated */
+struct vc_data *sel_cons; /* must not be deallocated */
static volatile int sel_start = -1; /* cleared by clear_selection */
static int sel_end;
static int sel_buffer_lth;
@@ -68,12 +68,10 @@
return inverse_translate(sel_cons, screen_glyph(sel_cons, n));
}
-/*
- * remove the current selection highlight, if any,
- * from the console holding the selection.
- */
-void clear_selection(void)
-{
+/* remove the current selection highlight, if any,
+ from the console holding the selection. */
+void
+clear_selection(void) {
highlight_pointer(-1); /* hide the pointer */
if (sel_start != -1) {
highlight(sel_start, sel_end);
@@ -256,8 +254,7 @@
clear_selection();
return -ENOMEM;
}
- if (sel_buffer)
- kfree(sel_buffer);
+ kfree(sel_buffer);
sel_buffer = bp;
obp = bp;
@@ -285,9 +282,10 @@
*/
int paste_selection(struct tty_struct *tty)
{
- struct vc_data *vc = (struct vc_data *) tty->driver_data;
- struct tty_ldisc *ld;
- int pasted = 0, count;
+ struct vc_data *vc = (struct vc_data *)tty->driver_data;
+ int pasted = 0;
+ unsigned int count;
+ struct tty_ldisc *ld;
DECLARE_WAITQUEUE(wait, current);
acquire_console_sem();
@@ -304,7 +302,7 @@
continue;
}
count = sel_buffer_lth - pasted;
- count = min(count, tty->ldisc.receive_room(tty));
+ count = min(count, tty->receive_room);
tty->ldisc.receive_buf(tty, sel_buffer + pasted, NULL, count);
pasted += count;
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <jsi...@us...> - 2007-04-11 19:38:12
|
Revision: 2368
http://linuxconsole.svn.sourceforge.net/linuxconsole/?rev=2368&view=rev
Author: jsimmons
Date: 2007-04-11 12:38:01 -0700 (Wed, 11 Apr 2007)
Log Message:
-----------
update sysrq.c to 2.6.21
Modified Paths:
--------------
branches/ruby-2.6.21/ruby-2.6/drivers/char/sysrq.c
Modified: branches/ruby-2.6.21/ruby-2.6/drivers/char/sysrq.c
===================================================================
--- branches/ruby-2.6.21/ruby-2.6/drivers/char/sysrq.c 2007-04-11 19:30:20 UTC (rev 2367)
+++ branches/ruby-2.6.21/ruby-2.6/drivers/char/sysrq.c 2007-04-11 19:38:01 UTC (rev 2368)
@@ -12,7 +12,6 @@
* based upon discusions in irc://irc.openprojects.net/#kernelnewbies
*/
-#include <linux/config.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/mm.h>
@@ -34,22 +33,51 @@
#include <linux/spinlock.h>
#include <linux/vt_kern.h>
#include <linux/workqueue.h>
+#include <linux/kexec.h>
+#include <linux/irq.h>
+#include <linux/hrtimer.h>
#include <asm/ptrace.h>
+#include <asm/irq_regs.h>
/* Whether we react on sysrq keys or just ignore them */
-int sysrq_enabled = 1;
+int __read_mostly __sysrq_enabled = 1;
-/* Loglevel sysrq handler */
-static void sysrq_handle_loglevel(int key, struct pt_regs *pt_regs,
- struct tty_struct *tty)
+static int __read_mostly sysrq_always_enabled;
+
+int sysrq_on(void)
{
+ return __sysrq_enabled || sysrq_always_enabled;
+}
+
+/*
+ * A value of 1 means 'all', other nonzero values are an op mask:
+ */
+static inline int sysrq_on_mask(int mask)
+{
+ return sysrq_always_enabled || __sysrq_enabled == 1 ||
+ (__sysrq_enabled & mask);
+}
+
+static int __init sysrq_always_enabled_setup(char *str)
+{
+ sysrq_always_enabled = 1;
+ printk(KERN_INFO "debug: sysrq always enabled.\n");
+
+ return 1;
+}
+
+__setup("sysrq_always_enabled", sysrq_always_enabled_setup);
+
+
+static void sysrq_handle_loglevel(int key, struct tty_struct *tty)
+{
int i;
i = key - '0';
console_loglevel = 7;
printk("Loglevel set to %d\n", i);
console_loglevel = i;
-}
+}
static struct sysrq_key_op sysrq_loglevel_op = {
.handler = sysrq_handle_loglevel,
.help_msg = "loglevel0-8",
@@ -57,18 +85,14 @@
.enable_mask = SYSRQ_ENABLE_LOG,
};
-
-/* SAK sysrq handler */
#ifdef CONFIG_VT
-static void sysrq_handle_SAK(int key, struct pt_regs *pt_regs,
- struct tty_struct *tty)
+static void sysrq_handle_SAK(int key, struct tty_struct *tty)
{
- if (tty)
- do_SAK(tty);
-
if (tty->driver->type == TTY_DRIVER_TYPE_CONSOLE) {
struct vc_data *vc = (struct vc_data *) tty->driver_data;
- if (vc) reset_vc(vc);
+ struct work_struct *SAK_work = vc->SAK_work; // Should this be fg_console
+
+ schedule_work(SAK_work);
}
}
static struct sysrq_key_op sysrq_SAK_op = {
@@ -78,14 +102,13 @@
.enable_mask = SYSRQ_ENABLE_KEYBOARD,
};
-/* unraw sysrq handler */
-static void sysrq_handle_unraw(int key, struct pt_regs *pt_regs,
- struct tty_struct *tty)
+static void sysrq_handle_unraw(int key, struct tty_struct *tty)
{
if (tty->driver->type == TTY_DRIVER_TYPE_CONSOLE) {
struct vc_data *vc = (struct vc_data *) tty->driver_data;
- if (vc) vc->kbd_table.kbdmode = VC_XLATE;
+ if (vc)
+ vc->kbd_table.kbdmode = VC_XLATE;
}
}
static struct sysrq_key_op sysrq_unraw_op = {
@@ -94,16 +117,32 @@
.action_msg = "Keyboard mode set to XLATE",
.enable_mask = SYSRQ_ENABLE_KEYBOARD,
};
+#else
+#define sysrq_SAK_op (*(struct sysrq_key_op *)0)
+#define sysrq_unraw_op (*(struct sysrq_key_op *)0)
#endif /* CONFIG_VT */
-/* reboot sysrq handler */
-static void sysrq_handle_reboot(int key, struct pt_regs *pt_regs,
- struct tty_struct *tty)
+#ifdef CONFIG_KEXEC
+static void sysrq_handle_crashdump(int key, struct tty_struct *tty)
{
+ crash_kexec(get_irq_regs());
+}
+static struct sysrq_key_op sysrq_crashdump_op = {
+ .handler = sysrq_handle_crashdump,
+ .help_msg = "Crashdump",
+ .action_msg = "Trigger a crashdump",
+ .enable_mask = SYSRQ_ENABLE_DUMP,
+};
+#else
+#define sysrq_crashdump_op (*(struct sysrq_key_op *)0)
+#endif
+
+static void sysrq_handle_reboot(int key, struct tty_struct *tty)
+{
+ lockdep_off();
local_irq_enable();
- machine_restart(NULL);
+ emergency_restart();
}
-
static struct sysrq_key_op sysrq_reboot_op = {
.handler = sysrq_handle_reboot,
.help_msg = "reBoot",
@@ -111,12 +150,10 @@
.enable_mask = SYSRQ_ENABLE_BOOT,
};
-static void sysrq_handle_sync(int key, struct pt_regs *pt_regs,
- struct tty_struct *tty)
+static void sysrq_handle_sync(int key, struct tty_struct *tty)
{
emergency_sync();
}
-
static struct sysrq_key_op sysrq_sync_op = {
.handler = sysrq_handle_sync,
.help_msg = "Sync",
@@ -124,12 +161,21 @@
.enable_mask = SYSRQ_ENABLE_SYNC,
};
-static void sysrq_handle_mountro(int key, struct pt_regs *pt_regs,
- struct tty_struct *tty)
+static void sysrq_handle_show_timers(int key, struct tty_struct *tty)
{
+ sysrq_timer_list_show();
+}
+
+static struct sysrq_key_op sysrq_show_timers_op = {
+ .handler = sysrq_handle_show_timers,
+ .help_msg = "show-all-timers(Q)",
+ .action_msg = "Show Pending Timers",
+};
+
+static void sysrq_handle_mountro(int key, struct tty_struct *tty)
+{
emergency_remount();
}
-
static struct sysrq_key_op sysrq_mountro_op = {
.handler = sysrq_handle_mountro,
.help_msg = "Unmount",
@@ -137,16 +183,26 @@
.enable_mask = SYSRQ_ENABLE_REMOUNT,
};
-/* END SYNC SYSRQ HANDLERS BLOCK */
+#ifdef CONFIG_LOCKDEP
+static void sysrq_handle_showlocks(int key, struct tty_struct *tty)
+{
+ debug_show_all_locks();
+}
+static struct sysrq_key_op sysrq_showlocks_op = {
+ .handler = sysrq_handle_showlocks,
+ .help_msg = "show-all-locks(D)",
+ .action_msg = "Show Locks Held",
+};
+#else
+#define sysrq_showlocks_op (*(struct sysrq_key_op *)0)
+#endif
-/* SHOW SYSRQ HANDLERS BLOCK */
-
-static void sysrq_handle_showregs(int key, struct pt_regs *pt_regs,
- struct tty_struct *tty)
+static void sysrq_handle_showregs(int key, struct tty_struct *tty)
{
- if (pt_regs)
- show_regs(pt_regs);
+ struct pt_regs *regs = get_irq_regs();
+ if (regs)
+ show_regs(regs);
}
static struct sysrq_key_op sysrq_showregs_op = {
.handler = sysrq_handle_showregs,
@@ -155,9 +211,7 @@
.enable_mask = SYSRQ_ENABLE_DUMP,
};
-
-static void sysrq_handle_showstate(int key, struct pt_regs *pt_regs,
- struct tty_struct *tty)
+static void sysrq_handle_showstate(int key, struct tty_struct *tty)
{
show_state();
}
@@ -168,9 +222,19 @@
.enable_mask = SYSRQ_ENABLE_DUMP,
};
+static void sysrq_handle_showstate_blocked(int key, struct tty_struct *tty)
+{
+ show_state_filter(TASK_UNINTERRUPTIBLE);
+}
+static struct sysrq_key_op sysrq_showstate_blocked_op = {
+ .handler = sysrq_handle_showstate_blocked,
+ .help_msg = "shoW-blocked-tasks",
+ .action_msg = "Show Blocked State",
+ .enable_mask = SYSRQ_ENABLE_DUMP,
+};
-static void sysrq_handle_showmem(int key, struct pt_regs *pt_regs,
- struct tty_struct *tty)
+
+static void sysrq_handle_showmem(int key, struct tty_struct *tty)
{
show_mem();
}
@@ -181,26 +245,21 @@
.enable_mask = SYSRQ_ENABLE_DUMP,
};
-/* SHOW SYSRQ HANDLERS BLOCK */
-
-
-/* SIGNAL SYSRQ HANDLERS BLOCK */
-
-/* signal sysrq helper function
- * Sends a signal to all user processes */
+/*
+ * Signal sysrq helper function. Sends a signal to all user processes.
+ */
static void send_sig_all(int sig)
{
struct task_struct *p;
for_each_process(p) {
- if (p->mm && p->pid != 1)
+ if (p->mm && !is_init(p))
/* Not swapper, init nor kernel thread */
force_sig(sig, p);
}
}
-static void sysrq_handle_term(int key, struct pt_regs *pt_regs,
- struct tty_struct *tty)
+static void sysrq_handle_term(int key, struct tty_struct *tty)
{
send_sig_all(SIGTERM);
console_loglevel = 8;
@@ -212,15 +271,15 @@
.enable_mask = SYSRQ_ENABLE_SIGNAL,
};
-static void moom_callback(void *ignored)
+static void moom_callback(struct work_struct *ignored)
{
- out_of_memory(GFP_KERNEL);
+ out_of_memory(&NODE_DATA(0)->node_zonelists[ZONE_NORMAL],
+ GFP_KERNEL, 0);
}
-static DECLARE_WORK(moom_work, moom_callback, NULL);
+static DECLARE_WORK(moom_work, moom_callback);
-static void sysrq_handle_moom(int key, struct pt_regs *pt_regs,
- struct tty_struct *tty)
+static void sysrq_handle_moom(int key, struct tty_struct *tty)
{
schedule_work(&moom_work);
}
@@ -230,8 +289,7 @@
.action_msg = "Manual OOM execution",
};
-static void sysrq_handle_kill(int key, struct pt_regs *pt_regs,
- struct tty_struct *tty)
+static void sysrq_handle_kill(int key, struct tty_struct *tty)
{
send_sig_all(SIGKILL);
console_loglevel = 8;
@@ -243,10 +301,7 @@
.enable_mask = SYSRQ_ENABLE_SIGNAL,
};
-/* END SIGNAL SYSRQ HANDLERS BLOCK */
-
-static void sysrq_handle_unrt(int key, struct pt_regs *pt_regs,
- struct tty_struct *tty)
+static void sysrq_handle_unrt(int key, struct tty_struct *tty)
{
normalize_rt_tasks();
}
@@ -259,102 +314,100 @@
/* Key Operations table and lock */
static DEFINE_SPINLOCK(sysrq_key_table_lock);
-#define SYSRQ_KEY_TABLE_LENGTH 36
-static struct sysrq_key_op *sysrq_key_table[SYSRQ_KEY_TABLE_LENGTH] = {
-/* 0 */ &sysrq_loglevel_op,
-/* 1 */ &sysrq_loglevel_op,
-/* 2 */ &sysrq_loglevel_op,
-/* 3 */ &sysrq_loglevel_op,
-/* 4 */ &sysrq_loglevel_op,
-/* 5 */ &sysrq_loglevel_op,
-/* 6 */ &sysrq_loglevel_op,
-/* 7 */ &sysrq_loglevel_op,
-/* 8 */ &sysrq_loglevel_op,
-/* 9 */ &sysrq_loglevel_op,
-/* a */ NULL, /* Don't use for system provided sysrqs,
- it is handled specially on the sparc
- and will never arrive */
-/* b */ &sysrq_reboot_op,
-/* c */ NULL,
-/* d */ NULL,
-/* e */ &sysrq_term_op,
-/* f */ &sysrq_moom_op,
-/* g */ NULL,
-/* h */ NULL,
-/* i */ &sysrq_kill_op,
-/* j */ NULL,
-#ifdef CONFIG_VT
-/* k */ &sysrq_SAK_op,
-#else
-/* k */ NULL,
-#endif
-/* l */ NULL,
-/* m */ &sysrq_showmem_op,
-/* n */ &sysrq_unrt_op,
-/* o */ NULL, /* This will often be registered
- as 'Off' at init time */
-/* p */ &sysrq_showregs_op,
-/* q */ NULL,
-#ifdef CONFIG_VT
-/* r */ &sysrq_unraw_op,
-#else
-/* r */ NULL,
-#endif
-/* s */ &sysrq_sync_op,
-/* t */ &sysrq_showstate_op,
-/* u */ &sysrq_mountro_op,
-/* v */ NULL, /* May be assigned at init time by SMP VOYAGER */
-/* w */ NULL,
-/* x */ NULL,
-/* y */ NULL,
-/* z */ NULL
+
+static struct sysrq_key_op *sysrq_key_table[36] = {
+ &sysrq_loglevel_op, /* 0 */
+ &sysrq_loglevel_op, /* 1 */
+ &sysrq_loglevel_op, /* 2 */
+ &sysrq_loglevel_op, /* 3 */
+ &sysrq_loglevel_op, /* 4 */
+ &sysrq_loglevel_op, /* 5 */
+ &sysrq_loglevel_op, /* 6 */
+ &sysrq_loglevel_op, /* 7 */
+ &sysrq_loglevel_op, /* 8 */
+ &sysrq_loglevel_op, /* 9 */
+
+ /*
+ * a: Don't use for system provided sysrqs, it is handled specially on
+ * sparc and will never arrive.
+ */
+ NULL, /* a */
+ &sysrq_reboot_op, /* b */
+ &sysrq_crashdump_op, /* c & ibm_emac driver debug */
+ &sysrq_showlocks_op, /* d */
+ &sysrq_term_op, /* e */
+ &sysrq_moom_op, /* f */
+ /* g: May be registered by ppc for kgdb */
+ NULL, /* g */
+ NULL, /* h */
+ &sysrq_kill_op, /* i */
+ NULL, /* j */
+ &sysrq_SAK_op, /* k */
+ NULL, /* l */
+ &sysrq_showmem_op, /* m */
+ &sysrq_unrt_op, /* n */
+ /* o: This will often be registered as 'Off' at init time */
+ NULL, /* o */
+ &sysrq_showregs_op, /* p */
+ &sysrq_show_timers_op, /* q */
+ &sysrq_unraw_op, /* r */
+ &sysrq_sync_op, /* s */
+ &sysrq_showstate_op, /* t */
+ &sysrq_mountro_op, /* u */
+ /* v: May be registered at init time by SMP VOYAGER */
+ NULL, /* v */
+ &sysrq_showstate_blocked_op, /* w */
+ /* x: May be registered on ppc/powerpc for xmon */
+ NULL, /* x */
+ NULL, /* y */
+ NULL /* z */
};
/* key2index calculation, -1 on invalid index */
-static int sysrq_key_table_key2index(int key) {
+static int sysrq_key_table_key2index(int key)
+{
int retval;
- if ((key >= '0') && (key <= '9')) {
+
+ if ((key >= '0') && (key <= '9'))
retval = key - '0';
- } else if ((key >= 'a') && (key <= 'z')) {
+ else if ((key >= 'a') && (key <= 'z'))
retval = key + 10 - 'a';
- } else {
+ else
retval = -1;
- }
return retval;
}
/*
* get and put functions for the table, exposed to modules.
*/
+struct sysrq_key_op *__sysrq_get_key_op(int key)
+{
+ struct sysrq_key_op *op_p = NULL;
+ int i;
-struct sysrq_key_op *__sysrq_get_key_op (int key) {
- struct sysrq_key_op *op_p;
- int i;
-
i = sysrq_key_table_key2index(key);
- op_p = (i == -1) ? NULL : sysrq_key_table[i];
+ if (i != -1)
+ op_p = sysrq_key_table[i];
return op_p;
}
-void __sysrq_put_key_op (int key, struct sysrq_key_op *op_p) {
- int i;
+static void __sysrq_put_key_op(int key, struct sysrq_key_op *op_p)
+{
+ int i = sysrq_key_table_key2index(key);
- i = sysrq_key_table_key2index(key);
if (i != -1)
sysrq_key_table[i] = op_p;
}
/*
- * This is the non-locking version of handle_sysrq
- * It must/can only be called by sysrq key handlers,
- * as they are inside of the lock
+ * This is the non-locking version of handle_sysrq. It must/can only be called
+ * by sysrq key handlers, as they are inside of the lock
*/
-
-void __handle_sysrq(int key, struct pt_regs *pt_regs, struct tty_struct *tty, int check_mask)
+void __handle_sysrq(int key, struct tty_struct *tty, int check_mask)
{
struct sysrq_key_op *op_p;
int orig_log_level;
- int i, j;
+ int i;
unsigned long flags;
spin_lock_irqsave(&sysrq_key_table_lock, flags);
@@ -364,26 +417,33 @@
op_p = __sysrq_get_key_op(key);
if (op_p) {
- /* Should we check for enabled operations (/proc/sysrq-trigger should not)
- * and is the invoked operation enabled? */
- if (!check_mask || sysrq_enabled == 1 ||
- (sysrq_enabled & op_p->enable_mask)) {
- printk ("%s\n", op_p->action_msg);
+ /*
+ * Should we check for enabled operations (/proc/sysrq-trigger
+ * should not) and is the invoked operation enabled?
+ */
+ if (!check_mask || sysrq_on_mask(op_p->enable_mask)) {
+ printk("%s\n", op_p->action_msg);
console_loglevel = orig_log_level;
- op_p->handler(key, pt_regs, tty);
+ op_p->handler(key, tty);
+ } else {
+ printk("This sysrq operation is disabled.\n");
}
- else
- printk("This sysrq operation is disabled.\n");
} else {
printk("HELP : ");
/* Only print the help msg once per handler */
- for (i=0; i<SYSRQ_KEY_TABLE_LENGTH; i++)
- if (sysrq_key_table[i]) {
- for (j=0; sysrq_key_table[i] != sysrq_key_table[j]; j++);
- if (j == i)
- printk ("%s ", sysrq_key_table[i]->help_msg);
+ for (i = 0; i < ARRAY_SIZE(sysrq_key_table); i++) {
+ if (sysrq_key_table[i]) {
+ int j;
+
+ for (j = 0; sysrq_key_table[i] !=
+ sysrq_key_table[j]; j++)
+ ;
+ if (j != i)
+ continue;
+ printk("%s ", sysrq_key_table[i]->help_msg);
+ }
}
- printk ("\n");
+ printk("\n");
console_loglevel = orig_log_level;
}
spin_unlock_irqrestore(&sysrq_key_table_lock, flags);
@@ -393,16 +453,16 @@
* This function is called by the keyboard handler when SysRq is pressed
* and any other keycode arrives.
*/
-
-void handle_sysrq(int key, struct pt_regs *pt_regs, struct tty_struct *tty)
+void handle_sysrq(int key, struct tty_struct *tty)
{
- if (!sysrq_enabled)
- return;
- __handle_sysrq(key, pt_regs, tty, 1);
+ if (sysrq_on())
+ __handle_sysrq(key, tty, 1);
}
+EXPORT_SYMBOL(handle_sysrq);
-int __sysrq_swap_key_ops(int key, struct sysrq_key_op *insert_op_p,
- struct sysrq_key_op *remove_op_p) {
+static int __sysrq_swap_key_ops(int key, struct sysrq_key_op *insert_op_p,
+ struct sysrq_key_op *remove_op_p)
+{
int retval;
unsigned long flags;
@@ -415,7 +475,6 @@
retval = -1;
}
spin_unlock_irqrestore(&sysrq_key_table_lock, flags);
-
return retval;
}
@@ -423,12 +482,10 @@
{
return __sysrq_swap_key_ops(key, op_p, NULL);
}
+EXPORT_SYMBOL(register_sysrq_key);
int unregister_sysrq_key(int key, struct sysrq_key_op *op_p)
{
return __sysrq_swap_key_ops(key, NULL, op_p);
}
-
-EXPORT_SYMBOL(handle_sysrq);
-EXPORT_SYMBOL(register_sysrq_key);
EXPORT_SYMBOL(unregister_sysrq_key);
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <jsi...@us...> - 2007-04-11 19:30:23
|
Revision: 2367
http://linuxconsole.svn.sourceforge.net/linuxconsole/?rev=2367&view=rev
Author: jsimmons
Date: 2007-04-11 12:30:20 -0700 (Wed, 11 Apr 2007)
Log Message:
-----------
updated to 2.6.21
Modified Paths:
--------------
branches/ruby-2.6.21/ruby-2.6/drivers/char/keyboard.c
Modified: branches/ruby-2.6.21/ruby-2.6/drivers/char/keyboard.c
===================================================================
--- branches/ruby-2.6.21/ruby-2.6/drivers/char/keyboard.c 2007-04-11 18:05:07 UTC (rev 2366)
+++ branches/ruby-2.6.21/ruby-2.6/drivers/char/keyboard.c 2007-04-11 19:30:20 UTC (rev 2367)
@@ -14,7 +14,7 @@
* `Sticky' modifier keys, 951006.
*
* 11-11-96: SAK should now work in the raw mode (Martin Mares)
- *
+ *
* Modified to provide 'generic' keyboard support by Hamish Macdonald
* Merge with the m68k keyboard driver and split-off of the PC low-level
* parts by Geert Uytterhoeven, May 1997
@@ -24,7 +24,6 @@
* 21-08-02: Converted to input API, major cleanup. (Vojtech Pavlik)
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/tty.h>
@@ -33,14 +32,39 @@
#include <linux/string.h>
#include <linux/init.h>
#include <linux/slab.h>
+#include <linux/irq.h>
+#include <linux/kbd_kern.h>
#include <linux/kbd_diacr.h>
#include <linux/vt_kern.h>
#include <linux/sysrq.h>
#include <linux/input.h>
+#include <linux/reboot.h>
static void kbd_disconnect(struct input_handle *handle);
extern void ctrl_alt_del(void);
+
+/*
+ * Exported functions/variables
+ */
+
+#define KBD_DEFMODE ((1 << VC_REPEAT) | (1 << VC_META))
+
+/*
+ * Some laptops take the 789uiojklm,. keys as number pad when NumLock is on.
+ * This seems a good reason to start with NumLock off. On HIL keyboards
+ * of PARISC machines however there is no NumLock key and everyone expects the keypad
+ * to be used for numbers.
+ */
+
+#if defined(CONFIG_PARISC) && (defined(CONFIG_KEYBOARD_HIL) || defined(CONFIG_KEYBOARD_HIL_OLD))
+#define KBD_DEFLEDS (1 << VC_NUMLOCK)
+#else
+#define KBD_DEFLEDS 0
+#endif
+
+#define KBD_DEFLOCK 0
+
void compute_shiftstate(void);
/*
@@ -51,19 +75,19 @@
k_self, k_fn, k_spec, k_pad,\
k_dead, k_cons, k_cur, k_shift,\
k_meta, k_ascii, k_lock, k_lowercase,\
- k_slock, k_dead2, k_ignore, k_ignore
+ k_slock, k_dead2, k_brl, k_ignore
-typedef void (k_handler_fn)(struct vc_data *vc, unsigned char value,
+typedef void (k_handler_fn)(struct vc_data *vc, unsigned char value,
char up_flag);
static k_handler_fn K_HANDLERS;
static k_handler_fn *k_handler[16] = { K_HANDLERS };
#define FN_HANDLERS\
- fn_null, fn_enter, fn_show_ptregs, fn_show_mem,\
- fn_show_state, fn_send_intr, fn_lastcons, fn_caps_toggle,\
- fn_num, fn_hold, fn_scroll_forw, fn_scroll_back,\
- fn_boot_it, fn_caps_on, fn_compose, fn_SAK,\
- fn_dec_console, fn_inc_console, fn_spawn_con, fn_bare_num
+ fn_null, fn_enter, fn_show_ptregs, fn_show_mem,\
+ fn_show_state, fn_send_intr, fn_lastcons, fn_caps_toggle,\
+ fn_num, fn_hold, fn_scroll_forw, fn_scroll_back,\
+ fn_boot_it, fn_caps_on, fn_compose, fn_SAK,\
+ fn_dec_console, fn_inc_console, fn_spawn_con, fn_bare_num
typedef void (fn_handler_fn)(struct vc_data *vc);
static fn_handler_fn FN_HANDLERS;
@@ -77,12 +101,17 @@
const int max_vals[] = {
255, ARRAY_SIZE(func_table) - 1, ARRAY_SIZE(fn_handler) - 1, NR_PAD - 1,
NR_DEAD - 1, 255, 3, NR_SHIFT - 1, 255, NR_ASCII - 1, NR_LOCK - 1,
- 255, NR_LOCK - 1, 255
+ 255, NR_LOCK - 1, 255, NR_BRL - 1
};
const int NR_TYPES = ARRAY_SIZE(max_vals);
-int spawnpid, spawnsig;
+struct vt_spawn_console vt_spawn_con = {
+ .lock = SPIN_LOCK_UNLOCKED,
+ .pid = NULL,
+ .sig = 0,
+};
+
/*
* Variables exported for vt.c
*/
@@ -98,7 +127,7 @@
static unsigned char shift_down[NR_SHIFT]; /* shift state counters.. */
static int dead_key_next;
static int npadch = -1; /* -1 or number assembled on pad */
-static unsigned char diacr;
+static unsigned int diacr;
static char rep; /* flag telling character repeat */
static struct ledptr {
@@ -119,6 +148,7 @@
"230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */
"\r\000/"; /* 0x60 - 0x6f */
static int sysrq_down;
+static int sysrq_alt_use;
#endif
static int sysrq_alt;
@@ -147,8 +177,10 @@
if (!dev)
return -ENODEV;
- if (!dev->keycodesize || scancode >= dev->keycodemax || keycode > KEY_MAX)
+ if (scancode >= dev->keycodemax || keycode > KEY_MAX)
return -EINVAL;
+ if (dev->keycodesize < sizeof(keycode) && (keycode >> (dev->keycodesize * 8)))
+ return -EINVAL;
oldkey = SET_INPUT_KEYCODE(dev, scancode, keycode);
@@ -158,25 +190,26 @@
for (i = 0; i < dev->keycodemax; i++)
if (INPUT_KEYCODE(dev,i) == oldkey)
set_bit(oldkey, dev->keybit);
+
return 0;
}
/*
- * Making beeps and bells.
+ * Making beeps and bells.
*/
-void kd_nosound(unsigned long private)
+static void kd_nosound(unsigned long private)
{
struct input_handle *handle = (struct input_handle *) private;
if (test_bit(EV_SND, handle->dev->evbit)) {
if (test_bit(SND_TONE, handle->dev->sndbit))
- input_event(handle->dev, EV_SND, SND_TONE, 0);
+ input_inject_event(handle, EV_SND, SND_TONE, 0);
if (test_bit(SND_BELL, handle->dev->sndbit))
- input_event(handle->dev, EV_SND, SND_BELL, 0);
+ input_inject_event(handle, EV_SND, SND_BELL, 0);
}
}
-void kd_mksound(struct input_handle *handle, unsigned int hz, unsigned int ticks)
+static void kd_mksound(struct input_handle *handle, unsigned int hz, unsigned int ticks)
{
struct vt_struct *vt;
@@ -190,9 +223,9 @@
if (hz) {
if (test_bit(EV_SND, handle->dev->evbit)) {
if (test_bit(SND_TONE, handle->dev->sndbit))
- input_event(handle->dev, EV_SND, SND_TONE, hz);
+ input_inject_event(handle, EV_SND, SND_TONE, hz);
if (test_bit(SND_BELL, handle->dev->sndbit))
- input_event(handle->dev, EV_SND, SND_BELL, 1);
+ input_inject_event(handle, EV_SND, SND_BELL, 1);
}
if (ticks)
mod_timer(&vt->beep, jiffies + ticks);
@@ -212,9 +245,9 @@
if (test_bit(EV_REP, dev->evbit)) {
if (rep->delay > 0)
- input_event(dev, EV_REP, REP_DELAY, rep->delay);
+ input_inject_event(dev, EV_REP, REP_DELAY, rep->delay);
if (rep->period > 0)
- input_event(dev, EV_REP, REP_PERIOD, rep->period);
+ input_inject_event(dev, EV_REP, REP_PERIOD, rep->period);
d = dev->rep[REP_DELAY];
p = dev->rep[REP_PERIOD];
}
@@ -236,7 +269,7 @@
}
}
-void puts_queue(struct vc_data *vc, char *cp)
+static void puts_queue(struct vc_data *vc, char *cp)
{
struct tty_struct *tty = vc->vc_tty;
@@ -269,21 +302,21 @@
static void to_utf8(struct vc_data *vc, ushort c)
{
if (c < 0x80)
- /* 0******* */
+ /* 0******* */
put_queue(vc, c);
- else if (c < 0x800) {
+ else if (c < 0x800) {
/* 110***** 10****** */
- put_queue(vc, 0xc0 | (c >> 6));
+ put_queue(vc, 0xc0 | (c >> 6));
put_queue(vc, 0x80 | (c & 0x3f));
- } else {
+ } else {
/* 1110**** 10****** 10****** */
put_queue(vc, 0xe0 | (c >> 12));
put_queue(vc, 0x80 | ((c >> 6) & 0x3f));
put_queue(vc, 0x80 | (c & 0x3f));
- }
+ }
}
-/*
+/*
* Called after returning from RAW mode or when changing consoles - recompute
* shift_down[] and shift_state from key_down[] maybe called when keymap is
* undefined, so that shiftkey release is seen
@@ -294,7 +327,7 @@
shift_state = 0;
memset(shift_down, 0, sizeof(shift_down));
-
+
for (i = 0; i < ARRAY_SIZE(key_down); i++) {
if (!key_down[i])
@@ -328,22 +361,29 @@
* Otherwise, conclude that DIACR was not combining after all,
* queue it and return CH.
*/
-static unsigned char handle_diacr(struct vc_data *vc, unsigned char ch)
+static unsigned int handle_diacr(struct vc_data *vc, unsigned int ch)
{
- unsigned int i;
- int d = diacr;
+ unsigned int d = diacr, i;
diacr = 0;
- for (i = 0; i < accent_table_size; i++) {
- if (accent_table[i].diacr == d && accent_table[i].base == ch)
- return accent_table[i].result;
+ if ((d & ~0xff) == BRL_UC_ROW) {
+ if ((ch & ~0xff) == BRL_UC_ROW)
+ return d | ch;
+ } else {
+ for (i = 0; i < accent_table_size; i++)
+ if (accent_table[i].diacr == d && accent_table[i].base == ch)
+ return accent_table[i].result;
}
- if (ch == ' ' || ch == d)
+ if (ch == ' ' || ch == (BRL_UC_ROW|0) || ch == d)
return d;
- put_queue(vc, d);
+ if (vc->kbd_table.kbdmode == VC_UNICODE)
+ to_utf8(vc, d);
+ else if (d < 0x100)
+ put_queue(vc, d);
+
return ch;
}
@@ -353,7 +393,10 @@
static void fn_enter(struct vc_data *vc)
{
if (diacr) {
- put_queue(vc, diacr);
+ if (kbd->kbdmode == VC_UNICODE)
+ to_utf8(vc, diacr);
+ else if (diacr < 0x100)
+ put_queue(vc, diacr);
diacr = 0;
}
put_queue(vc, 13);
@@ -377,9 +420,7 @@
static void fn_show_ptregs(struct vc_data *vc)
{
- struct input_handle *handle = vc->display_fg->keyboard;
- struct pt_regs *regs = handle->dev->regs;
-
+ struct pt_regs *regs = get_irq_regs();
if (regs)
show_regs(regs);
}
@@ -502,9 +543,13 @@
static void fn_spawn_con(struct vc_data *vc)
{
- if (spawnpid)
- if(kill_proc(spawnpid, spawnsig, 1))
- spawnpid = 0;
+ spin_lock(&vt_spawn_con.lock);
+ if (vt_spawn_con.pid)
+ if (kill_pid(vt_spawn_con.pid, vt_spawn_con.sig, 1)) {
+ put_pid(vt_spawn_con.pid);
+ vt_spawn_con.pid = NULL;
+ }
+ spin_unlock(&vt_spawn_con.lock);
}
static void fn_SAK(struct vc_data *vc)
@@ -550,7 +595,7 @@
printk(KERN_ERR "keyboard.c: k_lowercase was called - impossible\n");
}
-static void k_self(struct vc_data *vc, unsigned char value, char up_flag)
+static void k_unicode(struct vc_data *vc, unsigned int value, char up_flag)
{
if (up_flag)
return; /* no action, if this is a key release */
@@ -563,7 +608,10 @@
diacr = value;
return;
}
- put_queue(vc, value);
+ if (kbd->kbdmode == VC_UNICODE)
+ to_utf8(vc, value);
+ else if (value < 0x100)
+ put_queue(vc, value);
}
/*
@@ -571,27 +619,37 @@
* dead keys modifying the same character. Very useful
* for Vietnamese.
*/
-static void k_dead2(struct vc_data *vc, unsigned char value, char up_flag)
+static void k_deadunicode(struct vc_data *vc, unsigned int value, char up_flag)
{
if (up_flag)
return;
diacr = (diacr ? handle_diacr(vc, value) : value);
}
+static void k_self(struct vc_data *vc, unsigned char value, char up_flag)
+{
+ k_unicode(vc, value, up_flag);
+}
+
+static void k_dead2(struct vc_data *vc, unsigned char value, char up_flag)
+{
+ k_deadunicode(vc, value, up_flag);
+}
+
/*
* Obsolete - for backwards compatibility only
*/
static void k_dead(struct vc_data *vc, unsigned char value, char up_flag)
{
- static unsigned char ret_diacr[NR_DEAD] = {'`', '\'', '^', '~', '"', ',' };
+ static const unsigned char ret_diacr[NR_DEAD] = {'`', '\'', '^', '~', '"', ',' };
value = ret_diacr[value];
- k_dead2(vc, value, up_flag);
+ k_deadunicode(vc, value, up_flag);
}
static void k_cons(struct vc_data *vc, unsigned char value, char up_flag)
{
struct vc_data *tmp = find_vc(value + vc->display_fg->first_vc);
-
+
if (up_flag || !tmp)
return;
set_console(tmp);
@@ -613,7 +671,7 @@
static void k_cur(struct vc_data *vc, unsigned char value, char up_flag)
{
- static const char *cur_chars = "BDCA";
+ static const char cur_chars[] = "BDCA";
if (up_flag)
return;
@@ -622,8 +680,8 @@
static void k_pad(struct vc_data *vc, unsigned char value, char up_flag)
{
- static const char *pad_chars = "0123456789+-*/\015,.?()#";
- static const char *app_map = "pqrstuvwxylSRQMnnmPQS";
+ static const char pad_chars[] = "0123456789+-*/\015,.?()#";
+ static const char app_map[] = "pqrstuvwxylSRQMnnmPQS";
if (up_flag)
return; /* no action, if this is a key release */
@@ -772,6 +830,80 @@
}
}
+/* by default, 300ms interval for combination release */
+static unsigned brl_timeout = 300;
+MODULE_PARM_DESC(brl_timeout, "Braille keys release delay in ms (0 for commit on first key release)");
+module_param(brl_timeout, uint, 0644);
+
+static unsigned brl_nbchords = 1;
+MODULE_PARM_DESC(brl_nbchords, "Number of chords that produce a braille pattern (0 for dead chords)");
+module_param(brl_nbchords, uint, 0644);
+
+static void k_brlcommit(struct vc_data *vc, unsigned int pattern, char up_flag)
+{
+ static unsigned long chords;
+ static unsigned committed;
+
+ if (!brl_nbchords)
+ k_deadunicode(vc, BRL_UC_ROW | pattern, up_flag);
+ else {
+ committed |= pattern;
+ chords++;
+ if (chords == brl_nbchords) {
+ k_unicode(vc, BRL_UC_ROW | committed, up_flag);
+ chords = 0;
+ committed = 0;
+ }
+ }
+}
+
+static void k_brl(struct vc_data *vc, unsigned char value, char up_flag)
+{
+ static unsigned pressed,committing;
+ static unsigned long releasestart;
+
+ if (vc->kbd_table.kbdmode != VC_UNICODE) {
+ if (!up_flag)
+ printk("keyboard mode must be unicode for braille patterns\n");
+ return;
+ }
+
+ if (!value) {
+ k_unicode(vc, BRL_UC_ROW, up_flag);
+ return;
+ }
+
+ if (value > 8)
+ return;
+
+ if (up_flag) {
+ if (brl_timeout) {
+ if (!committing ||
+ jiffies - releasestart > (brl_timeout * HZ) / 1000) {
+ committing = pressed;
+ releasestart = jiffies;
+ }
+ pressed &= ~(1 << (value - 1));
+ if (!pressed) {
+ if (committing) {
+ k_brlcommit(vc, committing, 0);
+ committing = 0;
+ }
+ }
+ } else {
+ if (committing) {
+ k_brlcommit(vc, committing, 0);
+ committing = 0;
+ }
+ pressed &= ~(1 << (value - 1));
+ }
+ } else {
+ pressed |= 1 << (value - 1);
+ if (!brl_timeout)
+ committing = pressed;
+ }
+}
+
/*
* The leds display either (i) the status of NumLock, CapsLock, ScrollLock,
* or (ii) whatever pattern of lights people want to show using KDSETLED,
@@ -802,6 +934,7 @@
kbd->ledmode = LED_SHOW_MEM;
} else
kbd->ledmode = LED_SHOW_FLAGS;
+ //setleds();
}
static inline unsigned char getleds(struct vc_data *vc)
@@ -837,7 +970,7 @@
* interrupt routines for this thing allows us to easily mask
* this when we don't want any of the above to happen.
* This allows for easy and efficient race-condition prevention
- * for kbd_refresh_leds => input_event(dev, EV_LED, ...) => ...
+ * for kbd_start => input_inject_event(dev, EV_LED, ...) => ...
*/
static void kbd_bh(unsigned long dummy)
@@ -853,57 +986,34 @@
leds = getleds(vt->fg_console);
if (leds != vt->vt_ledstate) {
- input_event(handle->dev, EV_LED, LED_SCROLLL, !!(leds & 0x01));
- input_event(handle->dev, EV_LED, LED_NUML, !!(leds & 0x02));
- input_event(handle->dev, EV_LED, LED_CAPSL, !!(leds & 0x04));
- input_sync(handle->dev);
+ input_inject_event(handle, EV_LED, LED_SCROLLL, !!(leds & 0x01));
+ input_inject_event(handle, EV_LED, LED_NUML, !!(leds & 0x02));
+ input_inject_event(handle, EV_LED, LED_CAPSL, !!(leds & 0x04));
+ input_inject_event(handle, EV_SYN, SYN_REPORT, 0);
vt->vt_ledstate = leds;
}
}
- }
+ }
}
DECLARE_TASKLET_DISABLED(keyboard_tasklet, kbd_bh, 0);
-/*
- * This allows a newly plugged keyboard to pick the LED state.
- */
-static void kbd_refresh_leds(struct input_handle *handle)
-{
- struct vt_struct *vt = handle->private;
- unsigned char leds;
-
- if (vt) {
- tasklet_disable(&keyboard_tasklet);
- leds = getleds(vt->fg_console);
-
- if (leds != vt->vt_ledstate) {
- input_event(handle->dev, EV_LED, LED_SCROLLL, !!(leds & 0x01));
- input_event(handle->dev, EV_LED, LED_NUML, !!(leds & 0x02));
- input_event(handle->dev, EV_LED, LED_CAPSL, !!(leds & 0x04));
- input_sync(handle->dev);
- vt->vt_ledstate = leds;
- }
- tasklet_enable(&keyboard_tasklet);
- }
-}
-
#if defined(CONFIG_X86) || defined(CONFIG_IA64) || defined(CONFIG_ALPHA) ||\
- defined(CONFIG_MIPS) || defined(CONFIG_PPC) || defined(CONFIG_SPARC32) ||\
- defined(CONFIG_SPARC64) || defined(CONFIG_PARISC) || defined(CONFIG_SUPERH) ||\
+ defined(CONFIG_MIPS) || defined(CONFIG_PPC) || defined(CONFIG_SPARC) ||\
+ defined(CONFIG_PARISC) || defined(CONFIG_SUPERH) ||\
(defined(CONFIG_ARM) && defined(CONFIG_KEYBOARD_ATKBD) && !defined(CONFIG_ARCH_RPC))
#define HW_RAW(dev) (test_bit(EV_MSC, dev->evbit) && test_bit(MSC_RAW, dev->mscbit) &&\
((dev)->id.bustype == BUS_I8042) && ((dev)->id.vendor == 0x0001) && ((dev)->id.product == 0x0001))
-static unsigned short x86_keycodes[256] =
+static const unsigned short x86_keycodes[256] =
{ 0, 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,118, 86, 87, 88,115,120,119,121,112,123, 92,
- 284,285,309,298,312, 91,327,328,329,331,333,335,336,337,338,339,
+ 284,285,309, 0,312, 91,327,328,329,331,333,335,336,337,338,339,
367,288,302,304,350, 89,334,326,267,126,268,269,125,347,348,349,
360,261,262,263,268,376,100,101,321,316,373,286,289,102,351,355,
103,104,105,275,287,279,306,106,274,107,294,364,358,363,362,361,
@@ -917,44 +1027,63 @@
extern int mac_hid_mouse_emulate_buttons(int, int, int);
#endif /* CONFIG_MAC_EMUMOUSEBTN */
-#if defined(CONFIG_SPARC32) || defined(CONFIG_SPARC64)
+#ifdef CONFIG_SPARC
static int sparc_l1_a_state = 0;
extern void sun_do_break(void);
#endif
-static int emulate_raw(struct vc_data *vc, unsigned int keycode,
+static int emulate_raw(struct vc_data *vc, unsigned int keycode,
unsigned char up_flag)
{
- if (keycode > 255 || !x86_keycodes[keycode])
- return -1;
+ int code;
switch (keycode) {
case KEY_PAUSE:
put_queue(vc, 0xe1);
put_queue(vc, 0x1d | up_flag);
put_queue(vc, 0x45 | up_flag);
- return 0;
+ break;
+
case KEY_HANGUEL:
- if (!up_flag) put_queue(vc, 0xf1);
- return 0;
+ if (!up_flag)
+ put_queue(vc, 0xf2);
+ break;
+
case KEY_HANJA:
- if (!up_flag) put_queue(vc, 0xf2);
- return 0;
- }
+ if (!up_flag)
+ put_queue(vc, 0xf1);
+ break;
- if (keycode == KEY_SYSRQ && sysrq_alt) {
- put_queue(vc, 0x54 | up_flag);
- return 0;
- }
+ case KEY_SYSRQ:
+ /*
+ * Real AT keyboards (that's what we're trying
+ * to emulate here emit 0xe0 0x2a 0xe0 0x37 when
+ * pressing PrtSc/SysRq alone, but simply 0x54
+ * when pressing Alt+PrtSc/SysRq.
+ */
+ if (sysrq_alt) {
+ put_queue(vc, 0x54 | up_flag);
+ } else {
+ put_queue(vc, 0xe0);
+ put_queue(vc, 0x2a | up_flag);
+ put_queue(vc, 0xe0);
+ put_queue(vc, 0x37 | up_flag);
+ }
+ break;
- if (x86_keycodes[keycode] & 0x100)
- put_queue(vc, 0xe0);
+ default:
+ if (keycode > 255)
+ return -1;
- put_queue(vc, (x86_keycodes[keycode] & 0x7f) | up_flag);
+ code = x86_keycodes[keycode];
+ if (!code)
+ return -1;
- if (keycode == KEY_SYSRQ) {
- put_queue(vc, 0xe0);
- put_queue(vc, 0x37 | up_flag);
+ if (code & 0x100)
+ put_queue(vc, 0xe0);
+ put_queue(vc, (code & 0x7f) | up_flag);
+
+ break;
}
return 0;
@@ -998,8 +1127,8 @@
}
if (keycode == KEY_LEFTALT || keycode == KEY_RIGHTALT)
- sysrq_alt = down;
-#if defined(CONFIG_SPARC32) || defined(CONFIG_SPARC64)
+ sysrq_alt = down ? keycode : 0;
+#ifdef CONFIG_SPARC
if (keycode == KEY_STOP)
sparc_l1_a_state = down;
#endif
@@ -1018,15 +1147,18 @@
#ifdef CONFIG_MAGIC_SYSRQ /* Handle the SysRq Hack */
if (keycode == KEY_SYSRQ && (sysrq_down || (down == 1 && sysrq_alt))) {
- sysrq_down = down;
+ if (!sysrq_down) {
+ sysrq_down = down;
+ sysrq_alt_use = sysrq_alt;
+ }
return;
}
- if (sysrq_down && down && !rep) {
- handle_sysrq(kbd_sysrq_xlate[keycode], vt->keyboard->dev->regs, tty);
+ if (sysrq_down && !down && keycode == sysrq_alt_use) {
+ handle_sysrq(kbd_sysrq_xlate[keycode], tty);
return;
}
#endif
-#if defined(CONFIG_SPARC32) || defined(CONFIG_SPARC64)
+#ifdef CONFIG_SPARC
if (keycode == KEY_A && sparc_l1_a_state) {
sparc_l1_a_state = 0;
sun_do_break();
@@ -1062,7 +1194,7 @@
(!L_ECHO(tty) && tty->driver->chars_in_buffer(tty))))) {
/*
* Don't repeat a key if the input buffers are not empty and the
- * characters get aren't echoed locally. This makes key repeat
+ * characters get aren't echoed locally. This makes key repeat
* usable with slow applications and under heavy loads.
*/
return;
@@ -1078,13 +1210,18 @@
}
if (keycode > NR_KEYS)
- return;
+ if (keycode >= KEY_BRL_DOT1 && keycode <= KEY_BRL_DOT8)
+ keysym = K(KT_BRL, keycode - KEY_BRL_DOT1 + 1);
+ else
+ return;
+ else
+ keysym = key_map[keycode];
- keysym = key_map[keycode];
type = KTYP(keysym);
if (type < 0xf0) {
- if (down && !raw_mode) to_utf8(vc, keysym);
+ if (down && !raw_mode)
+ to_utf8(vc, keysym);
return;
}
@@ -1108,7 +1245,7 @@
vc->kbd_table.slockstate = 0;
}
-static void kbd_event(struct input_handle *handle, unsigned int event_type,
+static void kbd_event(struct input_handle *handle, unsigned int event_type,
unsigned int event_code, int value)
{
struct vt_struct *vt = handle->private;
@@ -1124,35 +1261,34 @@
schedule_work(&vt->vt_work);
}
-static char kbd_name[] = "kbd";
-
/*
* When a keyboard (or other input device) is found, the kbd_connect
* function is called. The function then looks at the device, and if it
* likes it, it can open it and get events from it. In this (kbd_connect)
* function, we should decide which VT to bind that keyboard to initially.
*/
-static struct input_handle *kbd_connect(struct input_handler *handler,
+static struct input_handle *kbd_connect(struct input_handler *handler,
struct input_dev *dev,
- struct input_device_id *id)
+ const struct input_device_id *id)
{
struct vt_struct *vt = NULL;
struct input_handle *handle;
int i;
for (i = KEY_RESERVED; i < BTN_MISC; i++)
- if (test_bit(i, dev->keybit)) break;
+ if (test_bit(i, dev->keybit))
+ break;
- if ((i == BTN_MISC) && !test_bit(EV_SND, dev->evbit))
+ if (i == BTN_MISC && !test_bit(EV_SND, dev->evbit))
return NULL;
- if (!(handle = kmalloc(sizeof(struct input_handle), GFP_KERNEL)))
+ handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL);
+ if (!handle)
return NULL;
- memset(handle, 0, sizeof(struct input_handle));
handle->dev = dev;
handle->handler = handler;
- handle->name = kbd_name;
+ handle->name = "kbd";
input_open_device(handle);
/*
@@ -1180,7 +1316,7 @@
break;
}
}
- kbd_refresh_leds(handle);
+ kbd_start(handle);
} else if (test_bit(EV_SND, dev->evbit) && admin_vt && !admin_vt->beeper) {
admin_vt->beeper = handle;
handle->private = admin_vt;
@@ -1201,16 +1337,40 @@
kfree(handle);
}
-static struct input_device_id kbd_ids[] = {
+/*
+ * Start keyboard handler on the new keyboard by refreshing LED state to
+ * match the rest of the system.
+ */
+static void kbd_start(struct input_handle *handle)
+{
+ struct vt_struct *vt = handle->private;
+ unsigned char leds;
+
+ if (vt) {
+ tasklet_disable(&keyboard_tasklet);
+ leds = getleds(vt->fg_console);
+
+ if (leds != vt->vt_ledstate) {
+ input_inject_event(handle, EV_LED, LED_SCROLLL, !!(leds & 0x01));
+ input_inject_event(handle, EV_LED, LED_NUML, !!(leds & 0x02));
+ input_inject_event(handle, EV_LED, LED_CAPSL, !!(leds & 0x04));
+ input_inject_event(handle, EV_SYN, SYN_REPORT, 0);
+ vt->vt_ledstate = leds;
+ }
+ tasklet_enable(&keyboard_tasklet);
+ }
+}
+
+static const struct input_device_id kbd_ids[] = {
{
.flags = INPUT_DEVICE_ID_MATCH_EVBIT,
.evbit = { BIT(EV_KEY) },
},
-
+
{
.flags = INPUT_DEVICE_ID_MATCH_EVBIT,
.evbit = { BIT(EV_SND) },
- },
+ },
{ }, /* Terminating entry */
};
@@ -1221,14 +1381,18 @@
.event = kbd_event,
.connect = kbd_connect,
.disconnect = kbd_disconnect,
+ .start = kbd_start,
.name = "kbd",
.id_table = kbd_ids,
};
int __init kbd_init(void)
{
- input_register_handler(&kbd_handler);
- tasklet_enable(&keyboard_tasklet);
- tasklet_schedule(&keyboard_tasklet);
- return 0;
+ int error = input_register_handler(&kbd_handler);
+
+ if (!error) {
+ tasklet_enable(&keyboard_tasklet);
+ tasklet_schedule(&keyboard_tasklet);
+ }
+ return error;
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <jsi...@us...> - 2007-04-11 18:05:38
|
Revision: 2366
http://linuxconsole.svn.sourceforge.net/linuxconsole/?rev=2366&view=rev
Author: jsimmons
Date: 2007-04-11 11:05:07 -0700 (Wed, 11 Apr 2007)
Log Message:
-----------
Since X org is now standard we don't need this
Removed Paths:
-------------
branches/ruby-2.6.21/ruby-2.6/drivers/pci/
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <jsi...@us...> - 2007-04-11 14:10:23
|
Revision: 2365
http://linuxconsole.svn.sourceforge.net/linuxconsole/?rev=2365&view=rev
Author: jsimmons
Date: 2007-04-11 07:10:15 -0700 (Wed, 11 Apr 2007)
Log Message:
-----------
updated to 2.6.21
Modified Paths:
--------------
branches/ruby-2.6.21/ruby-2.6/drivers/char/consolemap.c
Modified: branches/ruby-2.6.21/ruby-2.6/drivers/char/consolemap.c
===================================================================
--- branches/ruby-2.6.21/ruby-2.6/drivers/char/consolemap.c 2007-04-11 13:47:21 UTC (rev 2364)
+++ branches/ruby-2.6.21/ruby-2.6/drivers/char/consolemap.c 2007-04-11 14:10:15 UTC (rev 2365)
@@ -190,10 +190,9 @@
if (!q) {
q = p->inverse_translations[i] = (unsigned char *)
- kmalloc(MAX_GLYPH, GFP_KERNEL);
+ kzalloc(MAX_GLYPH, GFP_KERNEL);
if (!q) return;
}
- memset(q, 0, MAX_GLYPH);
for (j = 0; j < E_TABSZ; j++) {
glyph = conv_uni_to_pc(vc, t[j]);
@@ -343,27 +342,27 @@
for (i = 0; i < 32; i++) {
if ((p1 = p->uni_pgdir[i]) != NULL) {
for (j = 0; j < 32; j++)
- if (p1[j])
- kfree(p1[j]);
+ kfree(p1[j]);
kfree(p1);
}
p->uni_pgdir[i] = NULL;
}
- for (i = 0; i < 4; i++)
- if (p->inverse_translations[i]) {
- kfree(p->inverse_translations[i]);
- p->inverse_translations[i] = NULL;
- }
+ for (i = 0; i < 4; i++) {
+ kfree(p->inverse_translations[i]);
+ p->inverse_translations[i] = NULL;
+ }
}
void con_free_unimap(struct vc_data *vc)
{
struct uni_pagedir *p;
-
+
p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
- if (!p) return;
+ if (!p)
+ return;
*vc->vc_uni_pagedir_loc = 0;
- if (--p->refcount) return;
+ if (--p->refcount)
+ return;
con_release_unimap(p);
kfree(p);
}
@@ -417,16 +416,14 @@
u16 **p1, *p2;
if (!(p1 = p->uni_pgdir[n = unicode >> 11])) {
- p1 = p->uni_pgdir[n] = kmalloc(32*sizeof(u16 *), GFP_KERNEL);
+ p1 = p->uni_pgdir[n] = kzalloc(32*sizeof(u16 *), GFP_KERNEL);
if (!p1) return -ENOMEM;
- for (i = 0; i < 32; i++)
- p1[i] = NULL;
}
if (!(p2 = p1[n = (unicode >> 6) & 0x1f])) {
- p2 = p1[n] = kmalloc(64*sizeof(u16), GFP_KERNEL);
+ /* No glyphs for the characters (yet) */
+ p2 = p1[n] = kzalloc(64*sizeof(u16), GFP_KERNEL);
if (!p2) return -ENOMEM;
- memset(p2, 0xff, 64*sizeof(u16)); /* No glyphs for the characters (yet) */
}
p2[unicode & 0x3f] = fontpos;
@@ -444,12 +441,11 @@
p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
if (p && p->readonly) return -EIO;
if (!p || --p->refcount) {
- q = (struct uni_pagedir *)kmalloc(sizeof(*p), GFP_KERNEL);
+ q = kzalloc(sizeof(*p), GFP_KERNEL);
if (!q) {
if (p) p->refcount++;
return -ENOMEM;
}
- memset(q, 0, sizeof(*q));
q->refcount=1;
*vc->vc_uni_pagedir_loc = (unsigned long)q;
} else {
@@ -512,6 +508,7 @@
for (i = 0; i <= 3; i++)
set_inverse_transl(vc, p, i); /* Update all inverse translations */
+
return err;
}
@@ -525,7 +522,7 @@
int i, j, err = 0, err1;
u16 *q;
struct uni_pagedir *p;
-
+
if (dflt) {
p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
if (p == dflt)
@@ -568,7 +565,7 @@
int con_copy_unimap(struct vc_data *dst, struct vc_data *src)
{
struct uni_pagedir *q;
-
+
if (!src || !*src->vc_uni_pagedir_loc)
return -EINVAL;
if (*dst->vc_uni_pagedir_loc == *src->vc_uni_pagedir_loc)
@@ -610,9 +607,10 @@
void con_protect_unimap(struct vc_data *vc, int rdonly)
{
- struct uni_pagedir *p = (struct uni_pagedir *) *vc->vc_uni_pagedir_loc;
+ struct uni_pagedir *p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
- if (p) p->readonly = rdonly;
+ if (p)
+ p->readonly = rdonly;
}
int
@@ -651,7 +649,7 @@
/*
* This is called at sys_setup time, after memory and the console are
- * initialized. It must be possible to call kmalloc(..., GFP_KERNEL)
+ * initialized. It must be possible to call kzalloc(..., GFP_KERNEL)
* from this function, hence the call from sys_setup.
*/
void __init
@@ -671,4 +669,3 @@
}
EXPORT_SYMBOL(con_copy_unimap);
-
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <jsi...@us...> - 2007-04-11 13:47:43
|
Revision: 2364
http://linuxconsole.svn.sourceforge.net/linuxconsole/?rev=2364&view=rev
Author: jsimmons
Date: 2007-04-11 06:47:21 -0700 (Wed, 11 Apr 2007)
Log Message:
-----------
updated to 2.6.21
Modified Paths:
--------------
branches/ruby-2.6.21/ruby-2.6/drivers/input/input.c
Modified: branches/ruby-2.6.21/ruby-2.6/drivers/input/input.c
===================================================================
--- branches/ruby-2.6.21/ruby-2.6/drivers/input/input.c 2007-04-10 13:36:51 UTC (rev 2363)
+++ branches/ruby-2.6.21/ruby-2.6/drivers/input/input.c 2007-04-11 13:47:21 UTC (rev 2364)
@@ -11,36 +11,22 @@
*/
#include <linux/init.h>
-#include <linux/sched.h>
#include <linux/smp_lock.h>
#include <linux/input.h>
#include <linux/module.h>
#include <linux/random.h>
#include <linux/major.h>
#include <linux/proc_fs.h>
-#include <linux/kobject_uevent.h>
+#include <linux/seq_file.h>
#include <linux/interrupt.h>
#include <linux/poll.h>
#include <linux/device.h>
-#include <linux/devfs_fs_kernel.h>
+#include <linux/mutex.h>
MODULE_AUTHOR("Vojtech Pavlik <vo...@su...>");
MODULE_DESCRIPTION("Input core");
MODULE_LICENSE("GPL");
-EXPORT_SYMBOL(input_register_device);
-EXPORT_SYMBOL(input_unregister_device);
-EXPORT_SYMBOL(input_register_handler);
-EXPORT_SYMBOL(input_unregister_handler);
-EXPORT_SYMBOL(input_grab_device);
-EXPORT_SYMBOL(input_release_device);
-EXPORT_SYMBOL(input_open_device);
-EXPORT_SYMBOL(input_close_device);
-EXPORT_SYMBOL(input_accept_process);
-EXPORT_SYMBOL(input_flush_device);
-EXPORT_SYMBOL(input_event);
-EXPORT_SYMBOL(input_class);
-
#define INPUT_DEVICES 256
static LIST_HEAD(input_dev_list);
@@ -48,12 +34,16 @@
static struct input_handler *input_table[8];
-#ifdef CONFIG_PROC_FS
-static struct proc_dir_entry *proc_bus_input_dir;
-static DECLARE_WAIT_QUEUE_HEAD(input_devices_poll_wait);
-static int input_devices_state;
-#endif
-
+/**
+ * input_event() - report new input event
+ * @dev: device that generated the event
+ * @type: type of the event
+ * @code: event code
+ * @value: value of the event
+ *
+ * This function should be used by drivers implementing various input devices
+ * See also input_inject_event()
+ */
void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
{
struct input_handle *handle;
@@ -68,11 +58,13 @@
case EV_SYN:
switch (code) {
case SYN_CONFIG:
- if (dev->event) dev->event(dev, type, code, value);
+ if (dev->event)
+ dev->event(dev, type, code, value);
break;
case SYN_REPORT:
- if (dev->sync) return;
+ if (dev->sync)
+ return;
dev->sync = 1;
break;
}
@@ -95,6 +87,15 @@
break;
+ case EV_SW:
+
+ if (code > SW_MAX || !test_bit(code, dev->swbit) || !!test_bit(code, dev->sw) == value)
+ return;
+
+ change_bit(code, dev->sw);
+
+ break;
+
case EV_ABS:
if (code > ABS_MAX || !test_bit(code, dev->absbit))
@@ -132,7 +133,8 @@
if (code > MSC_MAX || !test_bit(code, dev->mscbit))
return;
- if (dev->event) dev->event(dev, type, code, value);
+ if (dev->event)
+ dev->event(dev, type, code, value);
break;
@@ -142,8 +144,10 @@
return;
change_bit(code, dev->led);
- if (dev->event) dev->event(dev, type, code, value);
+ if (dev->event)
+ dev->event(dev, type, code, value);
+
break;
case EV_SND:
@@ -151,21 +155,32 @@
if (code > SND_MAX || !test_bit(code, dev->sndbit))
return;
- if (dev->event) dev->event(dev, type, code, value);
+ if (!!test_bit(code, dev->snd) != !!value)
+ change_bit(code, dev->snd);
+ if (dev->event)
+ dev->event(dev, type, code, value);
+
break;
case EV_REP:
- if (code > REP_MAX || value < 0 || dev->rep[code] == value) return;
+ if (code > REP_MAX || value < 0 || dev->rep[code] == value)
+ return;
dev->rep[code] = value;
- if (dev->event) dev->event(dev, type, code, value);
+ if (dev->event)
+ dev->event(dev, type, code, value);
break;
case EV_FF:
- if (dev->event) dev->event(dev, type, code, value);
+
+ if (value < 0)
+ return;
+
+ if (dev->event)
+ dev->event(dev, type, code, value);
break;
}
@@ -179,7 +194,25 @@
if (handle->open)
handle->handler->event(handle, type, code, value);
}
+EXPORT_SYMBOL(input_event);
+/**
+ * input_inject_event() - send input event from input handler
+ * @handle: input handle to send event through
+ * @type: type of the event
+ * @code: event code
+ * @value: value of the event
+ *
+ * Similar to input_event() but will ignore event if device is "grabbed" and handle
+ * injecting event is not the one that owns the device.
+ */
+void input_inject_event(struct input_handle *handle, unsigned int type, unsigned int code, int value)
+{
+ if (!handle->dev->grab || handle->dev->grab == handle)
+ input_event(handle->dev, type, code, value);
+}
+EXPORT_SYMBOL(input_inject_event);
+
static void input_repeat_key(unsigned long data)
{
struct input_dev *dev = (void *) data;
@@ -194,14 +227,6 @@
mod_timer(&dev->timer, jiffies + msecs_to_jiffies(dev->rep[REP_PERIOD]));
}
-int input_accept_process(struct input_handle *handle, struct file *file)
-{
- if (handle->dev->accept)
- return handle->dev->accept(handle->dev, file);
-
- return 0;
-}
-
int input_grab_device(struct input_handle *handle)
{
if (handle->dev->grab)
@@ -210,20 +235,44 @@
handle->dev->grab = handle;
return 0;
}
+EXPORT_SYMBOL(input_grab_device);
void input_release_device(struct input_handle *handle)
{
- if (handle->dev->grab == handle)
- handle->dev->grab = NULL;
+ struct input_dev *dev = handle->dev;
+
+ if (dev->grab == handle) {
+ dev->grab = NULL;
+
+ list_for_each_entry(handle, &dev->h_list, d_node)
+ if (handle->handler->start)
+ handle->handler->start(handle);
+ }
}
+EXPORT_SYMBOL(input_release_device);
int input_open_device(struct input_handle *handle)
{
+ struct input_dev *dev = handle->dev;
+ int err;
+
+ err = mutex_lock_interruptible(&dev->mutex);
+ if (err)
+ return err;
+
handle->open++;
- if (handle->dev->open)
- return handle->dev->open(handle->dev);
- return 0;
+
+ if (!dev->users++ && dev->open)
+ err = dev->open(dev);
+
+ if (err)
+ handle->open--;
+
+ mutex_unlock(&dev->mutex);
+
+ return err;
}
+EXPORT_SYMBOL(input_open_device);
int input_flush_device(struct input_handle* handle, struct file* file)
{
@@ -232,14 +281,23 @@
return 0;
}
+EXPORT_SYMBOL(input_flush_device);
void input_close_device(struct input_handle *handle)
{
+ struct input_dev *dev = handle->dev;
+
input_release_device(handle);
- if (handle->dev->close)
- handle->dev->close(handle->dev);
+
+ mutex_lock(&dev->mutex);
+
+ if (!--dev->users && dev->close)
+ dev->close(dev);
handle->open--;
+
+ mutex_unlock(&dev->mutex);
}
+EXPORT_SYMBOL(input_close_device);
static void input_link_handle(struct input_handle *handle)
{
@@ -254,26 +312,27 @@
if (i != NBITS(max)) \
continue;
-static struct input_device_id *input_match_device(struct input_device_id *id, struct input_dev *dev)
+static const struct input_device_id *input_match_device(const struct input_device_id *id,
+ struct input_dev *dev)
{
int i;
for (; id->flags || id->driver_info; id++) {
if (id->flags & INPUT_DEVICE_ID_MATCH_BUS)
- if (id->id.bustype != dev->id.bustype)
+ if (id->bustype != dev->id.bustype)
continue;
if (id->flags & INPUT_DEVICE_ID_MATCH_VENDOR)
- if (id->id.vendor != dev->id.vendor)
+ if (id->vendor != dev->id.vendor)
continue;
if (id->flags & INPUT_DEVICE_ID_MATCH_PRODUCT)
- if (id->id.product != dev->id.product)
+ if (id->product != dev->id.product)
continue;
if (id->flags & INPUT_DEVICE_ID_MATCH_VERSION)
- if (id->id.version != dev->id.version)
+ if (id->version != dev->id.version)
continue;
MATCH_BIT(evbit, EV_MAX);
@@ -284,6 +343,7 @@
MATCH_BIT(ledbit, LED_MAX);
MATCH_BIT(sndbit, SND_MAX);
MATCH_BIT(ffbit, FF_MAX);
+ MATCH_BIT(swbit, SW_MAX);
return id;
}
@@ -291,127 +351,623 @@
return NULL;
}
+#ifdef CONFIG_PROC_FS
+
+static struct proc_dir_entry *proc_bus_input_dir;
+static DECLARE_WAIT_QUEUE_HEAD(input_devices_poll_wait);
+static int input_devices_state;
+
+static inline void input_wakeup_procfs_readers(void)
+{
+ input_devices_state++;
+ wake_up(&input_devices_poll_wait);
+}
+
+static unsigned int input_proc_devices_poll(struct file *file, poll_table *wait)
+{
+ int state = input_devices_state;
+
+ poll_wait(file, &input_devices_poll_wait, wait);
+ if (state != input_devices_state)
+ return POLLIN | POLLRDNORM;
+
+ return 0;
+}
+
+static struct list_head *list_get_nth_element(struct list_head *list, loff_t *pos)
+{
+ struct list_head *node;
+ loff_t i = 0;
+
+ list_for_each(node, list)
+ if (i++ == *pos)
+ return node;
+
+ return NULL;
+}
+
+static struct list_head *list_get_next_element(struct list_head *list, struct list_head *element, loff_t *pos)
+{
+ if (element->next == list)
+ return NULL;
+
+ ++(*pos);
+ return element->next;
+}
+
+static void *input_devices_seq_start(struct seq_file *seq, loff_t *pos)
+{
+ /* acquire lock here ... Yes, we do need locking, I knowi, I know... */
+
+ return list_get_nth_element(&input_dev_list, pos);
+}
+
+static void *input_devices_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+ return list_get_next_element(&input_dev_list, v, pos);
+}
+
+static void input_devices_seq_stop(struct seq_file *seq, void *v)
+{
+ /* release lock here */
+}
+
+static void input_seq_print_bitmap(struct seq_file *seq, const char *name,
+ unsigned long *bitmap, int max)
+{
+ int i;
+
+ for (i = NBITS(max) - 1; i > 0; i--)
+ if (bitmap[i])
+ break;
+
+ seq_printf(seq, "B: %s=", name);
+ for (; i >= 0; i--)
+ seq_printf(seq, "%lx%s", bitmap[i], i > 0 ? " " : "");
+ seq_putc(seq, '\n');
+}
+
+static int input_devices_seq_show(struct seq_file *seq, void *v)
+{
+ struct input_dev *dev = container_of(v, struct input_dev, node);
+ const char *path = kobject_get_path(&dev->cdev.kobj, GFP_KERNEL);
+ struct input_handle *handle;
+
+ seq_printf(seq, "I: Bus=%04x Vendor=%04x Product=%04x Version=%04x\n",
+ dev->id.bustype, dev->id.vendor, dev->id.product, dev->id.version);
+
+ seq_printf(seq, "N: Name=\"%s\"\n", dev->name ? dev->name : "");
+ seq_printf(seq, "P: Phys=%s\n", dev->phys ? dev->phys : "");
+ seq_printf(seq, "S: Sysfs=%s\n", path ? path : "");
+ seq_printf(seq, "H: Handlers=");
+
+ list_for_each_entry(handle, &dev->h_list, d_node)
+ seq_printf(seq, "%s ", handle->name);
+ seq_putc(seq, '\n');
+
+ input_seq_print_bitmap(seq, "EV", dev->evbit, EV_MAX);
+ if (test_bit(EV_KEY, dev->evbit))
+ input_seq_print_bitmap(seq, "KEY", dev->keybit, KEY_MAX);
+ if (test_bit(EV_REL, dev->evbit))
+ input_seq_print_bitmap(seq, "REL", dev->relbit, REL_MAX);
+ if (test_bit(EV_ABS, dev->evbit))
+ input_seq_print_bitmap(seq, "ABS", dev->absbit, ABS_MAX);
+ if (test_bit(EV_MSC, dev->evbit))
+ input_seq_print_bitmap(seq, "MSC", dev->mscbit, MSC_MAX);
+ if (test_bit(EV_LED, dev->evbit))
+ input_seq_print_bitmap(seq, "LED", dev->ledbit, LED_MAX);
+ if (test_bit(EV_SND, dev->evbit))
+ input_seq_print_bitmap(seq, "SND", dev->sndbit, SND_MAX);
+ if (test_bit(EV_FF, dev->evbit))
+ input_seq_print_bitmap(seq, "FF", dev->ffbit, FF_MAX);
+ if (test_bit(EV_SW, dev->evbit))
+ input_seq_print_bitmap(seq, "SW", dev->swbit, SW_MAX);
+
+ seq_putc(seq, '\n');
+
+ kfree(path);
+ return 0;
+}
+
+static struct seq_operations input_devices_seq_ops = {
+ .start = input_devices_seq_start,
+ .next = input_devices_seq_next,
+ .stop = input_devices_seq_stop,
+ .show = input_devices_seq_show,
+};
+
+static int input_proc_devices_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &input_devices_seq_ops);
+}
+
+static const struct file_operations input_devices_fileops = {
+ .owner = THIS_MODULE,
+ .open = input_proc_devices_open,
+ .poll = input_proc_devices_poll,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
+static void *input_handlers_seq_start(struct seq_file *seq, loff_t *pos)
+{
+ /* acquire lock here ... Yes, we do need locking, I knowi, I know... */
+ seq->private = (void *)(unsigned long)*pos;
+ return list_get_nth_element(&input_handler_list, pos);
+}
+
+static void *input_handlers_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+ seq->private = (void *)(unsigned long)(*pos + 1);
+ return list_get_next_element(&input_handler_list, v, pos);
+}
+
+static void input_handlers_seq_stop(struct seq_file *seq, void *v)
+{
+ /* release lock here */
+}
+
+static int input_handlers_seq_show(struct seq_file *seq, void *v)
+{
+ struct input_handler *handler = container_of(v, struct input_handler, node);
+
+ seq_printf(seq, "N: Number=%ld Name=%s",
+ (unsigned long)seq->private, handler->name);
+ if (handler->fops)
+ seq_printf(seq, " Minor=%d", handler->minor);
+ seq_putc(seq, '\n');
+
+ return 0;
+}
+static struct seq_operations input_handlers_seq_ops = {
+ .start = input_handlers_seq_start,
+ .next = input_handlers_seq_next,
+ .stop = input_handlers_seq_stop,
+ .show = input_handlers_seq_show,
+};
+
+static int input_proc_handlers_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &input_handlers_seq_ops);
+}
+
+static const struct file_operations input_handlers_fileops = {
+ .owner = THIS_MODULE,
+ .open = input_proc_handlers_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
+static int __init input_proc_init(void)
+{
+ struct proc_dir_entry *entry;
+
+ proc_bus_input_dir = proc_mkdir("input", proc_bus);
+ if (!proc_bus_input_dir)
+ return -ENOMEM;
+
+ proc_bus_input_dir->owner = THIS_MODULE;
+
+ entry = create_proc_entry("devices", 0, proc_bus_input_dir);
+ if (!entry)
+ goto fail1;
+
+ entry->owner = THIS_MODULE;
+ entry->proc_fops = &input_devices_fileops;
+
+ entry = create_proc_entry("handlers", 0, proc_bus_input_dir);
+ if (!entry)
+ goto fail2;
+
+ entry->owner = THIS_MODULE;
+ entry->proc_fops = &input_handlers_fileops;
+
+ return 0;
+
+ fail2: remove_proc_entry("devices", proc_bus_input_dir);
+ fail1: remove_proc_entry("input", proc_bus);
+ return -ENOMEM;
+}
+
+static void input_proc_exit(void)
+{
+ remove_proc_entry("devices", proc_bus_input_dir);
+ remove_proc_entry("handlers", proc_bus_input_dir);
+ remove_proc_entry("input", proc_bus);
+}
+
+#else /* !CONFIG_PROC_FS */
+static inline void input_wakeup_procfs_readers(void) { }
+static inline int input_proc_init(void) { return 0; }
+static inline void input_proc_exit(void) { }
+#endif
+
+struct input_handle *input_find_handle(char *phys_descr)
+{
+ struct input_handle *handle;
+ struct input_dev *dev;
+
+ list_for_each_entry(dev, &input_dev_list, node) {
+ list_for_each_entry(handle, &dev->h_list, d_node) {
+ if(!strcmp(handle->name,"kbd") && !strcmp(phys_descr,dev->phys) )
+ return handle;
+ }
+ }
+ printk(KERN_WARNING "input: no matching device for \"%s\"\n", phys_descr);
+ return NULL;
+}
+
+#define INPUT_DEV_STRING_ATTR_SHOW(name) \
+static ssize_t input_dev_show_##name(struct class_device *dev, char *buf) \
+{ \
+ struct input_dev *input_dev = to_input_dev(dev); \
+ \
+ return scnprintf(buf, PAGE_SIZE, "%s\n", \
+ input_dev->name ? input_dev->name : ""); \
+} \
+static CLASS_DEVICE_ATTR(name, S_IRUGO, input_dev_show_##name, NULL);
+
+INPUT_DEV_STRING_ATTR_SHOW(name);
+INPUT_DEV_STRING_ATTR_SHOW(phys);
+INPUT_DEV_STRING_ATTR_SHOW(uniq);
+
+static int input_print_modalias_bits(char *buf, int size,
+ char name, unsigned long *bm,
+ unsigned int min_bit, unsigned int max_bit)
+{
+ int len = 0, i;
+
+ len += snprintf(buf, max(size, 0), "%c", name);
+ for (i = min_bit; i < max_bit; i++)
+ if (bm[LONG(i)] & BIT(i))
+ len += snprintf(buf + len, max(size - len, 0), "%X,", i);
+ return len;
+}
+
+static int input_print_modalias(char *buf, int size, struct input_dev *id,
+ int add_cr)
+{
+ int len;
+
+ len = snprintf(buf, max(size, 0),
+ "input:b%04Xv%04Xp%04Xe%04X-",
+ id->id.bustype, id->id.vendor,
+ id->id.product, id->id.version);
+
+ len += input_print_modalias_bits(buf + len, size - len,
+ 'e', id->evbit, 0, EV_MAX);
+ len += input_print_modalias_bits(buf + len, size - len,
+ 'k', id->keybit, KEY_MIN_INTERESTING, KEY_MAX);
+ len += input_print_modalias_bits(buf + len, size - len,
+ 'r', id->relbit, 0, REL_MAX);
+ len += input_print_modalias_bits(buf + len, size - len,
+ 'a', id->absbit, 0, ABS_MAX);
+ len += input_print_modalias_bits(buf + len, size - len,
+ 'm', id->mscbit, 0, MSC_MAX);
+ len += input_print_modalias_bits(buf + len, size - len,
+ 'l', id->ledbit, 0, LED_MAX);
+ len += input_print_modalias_bits(buf + len, size - len,
+ 's', id->sndbit, 0, SND_MAX);
+ len += input_print_modalias_bits(buf + len, size - len,
+ 'f', id->ffbit, 0, FF_MAX);
+ len += input_print_modalias_bits(buf + len, size - len,
+ 'w', id->swbit, 0, SW_MAX);
+
+ if (add_cr)
+ len += snprintf(buf + len, max(size - len, 0), "\n");
+
+ return len;
+}
+
+static ssize_t input_dev_show_modalias(struct class_device *dev, char *buf)
+{
+ struct input_dev *id = to_input_dev(dev);
+ ssize_t len;
+
+ len = input_print_modalias(buf, PAGE_SIZE, id, 1);
+
+ return min_t(int, len, PAGE_SIZE);
+}
+static CLASS_DEVICE_ATTR(modalias, S_IRUGO, input_dev_show_modalias, NULL);
+
+static struct attribute *input_dev_attrs[] = {
+ &class_device_attr_name.attr,
+ &class_device_attr_phys.attr,
+ &class_device_attr_uniq.attr,
+ &class_device_attr_modalias.attr,
+ NULL
+};
+
+static struct attribute_group input_dev_attr_group = {
+ .attrs = input_dev_attrs,
+};
+
+#define INPUT_DEV_ID_ATTR(name) \
+static ssize_t input_dev_show_id_##name(struct class_device *dev, char *buf) \
+{ \
+ struct input_dev *input_dev = to_input_dev(dev); \
+ return scnprintf(buf, PAGE_SIZE, "%04x\n", input_dev->id.name); \
+} \
+static CLASS_DEVICE_ATTR(name, S_IRUGO, input_dev_show_id_##name, NULL);
+
+INPUT_DEV_ID_ATTR(bustype);
+INPUT_DEV_ID_ATTR(vendor);
+INPUT_DEV_ID_ATTR(product);
+INPUT_DEV_ID_ATTR(version);
+
+static struct attribute *input_dev_id_attrs[] = {
+ &class_device_attr_bustype.attr,
+ &class_device_attr_vendor.attr,
+ &class_device_attr_product.attr,
+ &class_device_attr_version.attr,
+ NULL
+};
+
+static struct attribute_group input_dev_id_attr_group = {
+ .name = "id",
+ .attrs = input_dev_id_attrs,
+};
+
+static int input_print_bitmap(char *buf, int buf_size, unsigned long *bitmap,
+ int max, int add_cr)
+{
+ int i;
+ int len = 0;
+
+ for (i = NBITS(max) - 1; i > 0; i--)
+ if (bitmap[i])
+ break;
+
+ for (; i >= 0; i--)
+ len += snprintf(buf + len, max(buf_size - len, 0),
+ "%lx%s", bitmap[i], i > 0 ? " " : "");
+
+ if (add_cr)
+ len += snprintf(buf + len, max(buf_size - len, 0), "\n");
+
+ return len;
+}
+
+#define INPUT_DEV_CAP_ATTR(ev, bm) \
+static ssize_t input_dev_show_cap_##bm(struct class_device *dev, char *buf) \
+{ \
+ struct input_dev *input_dev = to_input_dev(dev); \
+ int len = input_print_bitmap(buf, PAGE_SIZE, \
+ input_dev->bm##bit, ev##_MAX, 1); \
+ return min_t(int, len, PAGE_SIZE); \
+} \
+static CLASS_DEVICE_ATTR(bm, S_IRUGO, input_dev_show_cap_##bm, NULL);
+
+INPUT_DEV_CAP_ATTR(EV, ev);
+INPUT_DEV_CAP_ATTR(KEY, key);
+INPUT_DEV_CAP_ATTR(REL, rel);
+INPUT_DEV_CAP_ATTR(ABS, abs);
+INPUT_DEV_CAP_ATTR(MSC, msc);
+INPUT_DEV_CAP_ATTR(LED, led);
+INPUT_DEV_CAP_ATTR(SND, snd);
+INPUT_DEV_CAP_ATTR(FF, ff);
+INPUT_DEV_CAP_ATTR(SW, sw);
+
+static struct attribute *input_dev_caps_attrs[] = {
+ &class_device_attr_ev.attr,
+ &class_device_attr_key.attr,
+ &class_device_attr_rel.attr,
+ &class_device_attr_abs.attr,
+ &class_device_attr_msc.attr,
+ &class_device_attr_led.attr,
+ &class_device_attr_snd.attr,
+ &class_device_attr_ff.attr,
+ &class_device_attr_sw.attr,
+ NULL
+};
+
+static struct attribute_group input_dev_caps_attr_group = {
+ .name = "capabilities",
+ .attrs = input_dev_caps_attrs,
+};
+
+static void input_dev_release(struct class_device *class_dev)
+{
+ struct input_dev *dev = to_input_dev(class_dev);
+
+ input_ff_destroy(dev);
+ kfree(dev);
+
+ module_put(THIS_MODULE);
+}
+
/*
- * Input hotplugging interface - loading event handlers based on
+ * Input uevent interface - loading event handlers based on
* device bitfields.
*/
+static int input_add_uevent_bm_var(char **envp, int num_envp, int *cur_index,
+ char *buffer, int buffer_size, int *cur_len,
+ const char *name, unsigned long *bitmap, int max)
+{
+ if (*cur_index >= num_envp - 1)
+ return -ENOMEM;
-#ifdef CONFIG_HOTPLUG
+ envp[*cur_index] = buffer + *cur_len;
-/*
- * Input hotplugging invokes what /proc/sys/kernel/hotplug says
- * (normally /sbin/hotplug) when input devices get added or removed.
- *
- * This invokes a user mode policy agent, typically helping to load driver
- * or other modules, configure the device, and more. Drivers can provide
- * a MODULE_DEVICE_TABLE to help with module loading subtasks.
- *
- */
+ *cur_len += snprintf(buffer + *cur_len, max(buffer_size - *cur_len, 0), name);
+ if (*cur_len >= buffer_size)
+ return -ENOMEM;
-#define SPRINTF_BIT_A(bit, name, max) \
- do { \
- envp[i++] = scratch; \
- scratch += sprintf(scratch, name); \
- for (j = NBITS(max) - 1; j >= 0; j--) \
- if (dev->bit[j]) break; \
- for (; j >= 0; j--) \
- scratch += sprintf(scratch, "%lx ", dev->bit[j]); \
- scratch++; \
+ *cur_len += input_print_bitmap(buffer + *cur_len,
+ max(buffer_size - *cur_len, 0),
+ bitmap, max, 0) + 1;
+ if (*cur_len > buffer_size)
+ return -ENOMEM;
+
+ (*cur_index)++;
+ return 0;
+}
+
+static int input_add_uevent_modalias_var(char **envp, int num_envp, int *cur_index,
+ char *buffer, int buffer_size, int *cur_len,
+ struct input_dev *dev)
+{
+ if (*cur_index >= num_envp - 1)
+ return -ENOMEM;
+
+ envp[*cur_index] = buffer + *cur_len;
+
+ *cur_len += snprintf(buffer + *cur_len, max(buffer_size - *cur_len, 0),
+ "MODALIAS=");
+ if (*cur_len >= buffer_size)
+ return -ENOMEM;
+
+ *cur_len += input_print_modalias(buffer + *cur_len,
+ max(buffer_size - *cur_len, 0),
+ dev, 0) + 1;
+ if (*cur_len > buffer_size)
+ return -ENOMEM;
+
+ (*cur_index)++;
+ return 0;
+}
+
+#define INPUT_ADD_HOTPLUG_VAR(fmt, val...) \
+ do { \
+ int err = add_uevent_var(envp, num_envp, &i, \
+ buffer, buffer_size, &len, \
+ fmt, val); \
+ if (err) \
+ return err; \
} while (0)
-#define SPRINTF_BIT_A2(bit, name, max, ev) \
- do { \
- if (test_bit(ev, dev->evbit)) \
- SPRINTF_BIT_A(bit, name, max); \
+#define INPUT_ADD_HOTPLUG_BM_VAR(name, bm, max) \
+ do { \
+ int err = input_add_uevent_bm_var(envp, num_envp, &i, \
+ buffer, buffer_size, &len, \
+ name, bm, max); \
+ if (err) \
+ return err; \
} while (0)
-static void input_call_hotplug(char *verb, struct input_dev *dev)
+#define INPUT_ADD_HOTPLUG_MODALIAS_VAR(dev) \
+ do { \
+ int err = input_add_uevent_modalias_var(envp, \
+ num_envp, &i, \
+ buffer, buffer_size, &len, \
+ dev); \
+ if (err) \
+ return err; \
+ } while (0)
+
+static int input_dev_uevent(struct class_device *cdev, char **envp,
+ int num_envp, char *buffer, int buffer_size)
{
- char *argv[3], **envp, *buf, *scratch;
- int i = 0, j, value;
+ struct input_dev *dev = to_input_dev(cdev);
+ int i = 0;
+ int len = 0;
- if (!hotplug_path[0]) {
- printk(KERN_ERR "input.c: calling hotplug without a hotplug agent defined\n");
- return;
- }
- if (in_interrupt()) {
- printk(KERN_ERR "input.c: calling hotplug from interrupt\n");
- return;
- }
- if (!current->fs->root) {
- printk(KERN_WARNING "input.c: calling hotplug without valid filesystem\n");
- return;
- }
- if (!(envp = (char **) kmalloc(20 * sizeof(char *), GFP_KERNEL))) {
- printk(KERN_ERR "input.c: not enough memory allocating hotplug environment\n");
- return;
- }
- if (!(buf = kmalloc(1024, GFP_KERNEL))) {
- kfree (envp);
- printk(KERN_ERR "input.c: not enough memory allocating hotplug environment\n");
- return;
- }
+ INPUT_ADD_HOTPLUG_VAR("PRODUCT=%x/%x/%x/%x",
+ dev->id.bustype, dev->id.vendor,
+ dev->id.product, dev->id.version);
+ if (dev->name)
+ INPUT_ADD_HOTPLUG_VAR("NAME=\"%s\"", dev->name);
+ if (dev->phys)
+ INPUT_ADD_HOTPLUG_VAR("PHYS=\"%s\"", dev->phys);
+ if (dev->uniq)
+ INPUT_ADD_HOTPLUG_VAR("UNIQ=\"%s\"", dev->uniq);
- argv[0] = hotplug_path;
- argv[1] = "input";
- argv[2] = NULL;
+ INPUT_ADD_HOTPLUG_BM_VAR("EV=", dev->evbit, EV_MAX);
+ if (test_bit(EV_KEY, dev->evbit))
+ INPUT_ADD_HOTPLUG_BM_VAR("KEY=", dev->keybit, KEY_MAX);
+ if (test_bit(EV_REL, dev->evbit))
+ INPUT_ADD_HOTPLUG_BM_VAR("REL=", dev->relbit, REL_MAX);
+ if (test_bit(EV_ABS, dev->evbit))
+ INPUT_ADD_HOTPLUG_BM_VAR("ABS=", dev->absbit, ABS_MAX);
+ if (test_bit(EV_MSC, dev->evbit))
+ INPUT_ADD_HOTPLUG_BM_VAR("MSC=", dev->mscbit, MSC_MAX);
+ if (test_bit(EV_LED, dev->evbit))
+ INPUT_ADD_HOTPLUG_BM_VAR("LED=", dev->ledbit, LED_MAX);
+ if (test_bit(EV_SND, dev->evbit))
+ INPUT_ADD_HOTPLUG_BM_VAR("SND=", dev->sndbit, SND_MAX);
+ if (test_bit(EV_FF, dev->evbit))
+ INPUT_ADD_HOTPLUG_BM_VAR("FF=", dev->ffbit, FF_MAX);
+ if (test_bit(EV_SW, dev->evbit))
+ INPUT_ADD_HOTPLUG_BM_VAR("SW=", dev->swbit, SW_MAX);
- envp[i++] = "HOME=/";
- envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
+ INPUT_ADD_HOTPLUG_MODALIAS_VAR(dev);
- scratch = buf;
+ envp[i] = NULL;
+ return 0;
+}
- envp[i++] = scratch;
- scratch += sprintf(scratch, "ACTION=%s", verb) + 1;
+struct class input_class = {
+ .name = "input",
+ .release = input_dev_release,
+ .uevent = input_dev_uevent,
+};
+EXPORT_SYMBOL_GPL(input_class);
- envp[i++] = scratch;
- scratch += sprintf(scratch, "PRODUCT=%x/%x/%x/%x",
- dev->id.bustype, dev->id.vendor, dev->id.product, dev->id.version) + 1;
+/**
+ * input_allocate_device - allocate memory for new input device
+ *
+ * Returns prepared struct input_dev or NULL.
+ *
+ * NOTE: Use input_free_device() to free devices that have not been
+ * registered; input_unregister_device() should be used for already
+ * registered devices.
+ */
+struct input_dev *input_allocate_device(void)
+{
+ struct input_dev *dev;
- if (dev->name) {
- envp[i++] = scratch;
- scratch += sprintf(scratch, "NAME=%s", dev->name) + 1;
- }
+ dev = kzalloc(sizeof(struct input_dev), GFP_KERNEL);
+ if (dev) {
+ dev->cdev.class = &input_class;
+ class_device_initialize(&dev->cdev);
+ mutex_init(&dev->mutex);
+ INIT_LIST_HEAD(&dev->h_list);
+ INIT_LIST_HEAD(&dev->node);
- if (dev->phys) {
- envp[i++] = scratch;
- scratch += sprintf(scratch, "PHYS=%s", dev->phys) + 1;
+ __module_get(THIS_MODULE);
}
- SPRINTF_BIT_A(evbit, "EV=", EV_MAX);
- SPRINTF_BIT_A2(keybit, "KEY=", KEY_MAX, EV_KEY);
- SPRINTF_BIT_A2(relbit, "REL=", REL_MAX, EV_REL);
- SPRINTF_BIT_A2(absbit, "ABS=", ABS_MAX, EV_ABS);
- SPRINTF_BIT_A2(mscbit, "MSC=", MSC_MAX, EV_MSC);
- SPRINTF_BIT_A2(ledbit, "LED=", LED_MAX, EV_LED);
- SPRINTF_BIT_A2(sndbit, "SND=", SND_MAX, EV_SND);
- SPRINTF_BIT_A2(ffbit, "FF=", FF_MAX, EV_FF);
+ return dev;
+}
+EXPORT_SYMBOL(input_allocate_device);
- envp[i++] = NULL;
+/**
+ * input_free_device - free memory occupied by input_dev structure
+ * @dev: input device to free
+ *
+ * This function should only be used if input_register_device()
+ * was not called yet or if it failed. Once device was registered
+ * use input_unregister_device() and memory will be freed once last
+ * refrence to the device is dropped.
+ *
+ * Device should be allocated by input_allocate_device().
+ *
+ * NOTE: If there are references to the input device then memory
+ * will not be freed until last reference is dropped.
+ */
+void input_free_device(struct input_dev *dev)
+{
+ if (dev) {
-#ifdef INPUT_DEBUG
- printk(KERN_DEBUG "input.c: calling %s %s [%s %s %s %s %s]\n",
- argv[0], argv[1], envp[0], envp[1], envp[2], envp[3], envp[4]);
-#endif
+ mutex_lock(&dev->mutex);
+ dev->name = dev->phys = dev->uniq = NULL;
+ mutex_unlock(&dev->mutex);
- value = call_usermodehelper(argv [0], argv, envp, 0);
-
- kfree(buf);
- kfree(envp);
-
-#ifdef INPUT_DEBUG
- if (value != 0)
- printk(KERN_DEBUG "input.c: hotplug returned %d\n", value);
-#endif
+ input_put_device(dev);
+ }
}
+EXPORT_SYMBOL(input_free_device);
-#endif
-
-void input_register_device(struct input_dev *dev)
+int input_register_device(struct input_dev *dev)
{
+ static atomic_t input_no = ATOMIC_INIT(0);
struct input_handle *handle;
struct input_handler *handler;
- struct input_device_id *id;
+ const struct input_device_id *id;
+ const char *path;
+ int error;
set_bit(EV_SYN, dev->evbit);
@@ -428,30 +984,61 @@
dev->rep[REP_PERIOD] = 33;
}
- INIT_LIST_HEAD(&dev->h_list);
list_add_tail(&dev->node, &input_dev_list);
+ snprintf(dev->cdev.class_id, sizeof(dev->cdev.class_id),
+ "input%ld", (unsigned long) atomic_inc_return(&input_no) - 1);
+
+ error = class_device_add(&dev->cdev);
+ if (error)
+ return error;
+
+ error = sysfs_create_group(&dev->cdev.kobj, &input_dev_attr_group);
+ if (error)
+ goto fail1;
+
+ error = sysfs_create_group(&dev->cdev.kobj, &input_dev_id_attr_group);
+ if (error)
+ goto fail2;
+
+ error = sysfs_create_group(&dev->cdev.kobj, &input_dev_caps_attr_group);
+ if (error)
+ goto fail3;
+
+ path = kobject_get_path(&dev->cdev.kobj, GFP_KERNEL);
+ printk(KERN_INFO "input: %s as %s\n",
+ dev->name ? dev->name : "Unspecified device", path ? path : "N/A");
+ kfree(path);
+
list_for_each_entry(handler, &input_handler_list, node)
if (!handler->blacklist || !input_match_device(handler->blacklist, dev))
if ((id = input_match_device(handler->id_table, dev)))
- if ((handle = handler->connect(handler, dev, id)))
+ if ((handle = handler->connect(handler, dev, id))) {
input_link_handle(handle);
+ if (handler->start)
+ handler->start(handle);
+ }
-#ifdef CONFIG_HOTPLUG
- input_call_hotplug("add", dev);
-#endif
+ input_wakeup_procfs_readers();
-#ifdef CONFIG_PROC_FS
- input_devices_state++;
- wake_up(&input_devices_poll_wait);
-#endif
+ return 0;
+
+ fail3: sysfs_remove_group(&dev->cdev.kobj, &input_dev_id_attr_group);
+ fail2: sysfs_remove_group(&dev->cdev.kobj, &input_dev_attr_group);
+ fail1: class_device_del(&dev->cdev);
+ return error;
}
+EXPORT_SYMBOL(input_register_device);
void input_unregister_device(struct input_dev *dev)
{
- struct list_head * node, * next;
+ struct list_head *node, *next;
+ int code;
- if (!dev) return;
+ for (code = 0; code <= KEY_MAX; code++)
+ if (test_bit(code, dev->key))
+ input_report_key(dev, code, 0);
+ input_sync(dev);
del_timer_sync(&dev->timer);
@@ -462,48 +1049,52 @@
handle->handler->disconnect(handle);
}
-#ifdef CONFIG_HOTPLUG
- input_call_hotplug("remove", dev);
-#endif
-
list_del_init(&dev->node);
-#ifdef CONFIG_PROC_FS
- input_devices_state++;
- wake_up(&input_devices_poll_wait);
-#endif
+ sysfs_remove_group(&dev->cdev.kobj, &input_dev_caps_attr_group);
+ sysfs_remove_group(&dev->cdev.kobj, &input_dev_id_attr_group);
+ sysfs_remove_group(&dev->cdev.kobj, &input_dev_attr_group);
+
+ class_device_unregister(&dev->cdev);
+
+ input_wakeup_procfs_readers();
}
+EXPORT_SYMBOL(input_unregister_device);
-void input_register_handler(struct input_handler *handler)
+int input_register_handler(struct input_handler *handler)
{
struct input_dev *dev;
struct input_handle *handle;
- struct input_device_id *id;
+ const struct input_device_id *id;
- if (!handler) return;
-
INIT_LIST_HEAD(&handler->h_list);
- if (handler->fops != NULL)
+ if (handler->fops != NULL) {
+ if (input_table[handler->minor >> 5])
+ return -EBUSY;
+
input_table[handler->minor >> 5] = handler;
+ }
list_add_tail(&handler->node, &input_handler_list);
list_for_each_entry(dev, &input_dev_list, node)
if (!handler->blacklist || !input_match_device(handler->blacklist, dev))
if ((id = input_match_device(handler->id_table, dev)))
- if ((handle = handler->connect(handler, dev, id)))
+ if ((handle = handler->connect(handler, dev, id))) {
input_link_handle(handle);
+ if (handler->start)
+ handler->start(handle);
+ }
-#ifdef CONFIG_PROC_FS
- input_devices_state++;
- wake_up(&input_devices_poll_wait);
-#endif
+ input_wakeup_procfs_readers();
+ return 0;
}
+EXPORT_SYMBOL(input_register_handler);
void input_unregister_handler(struct input_handler *handler)
{
- struct list_head * node, * next;
+ struct list_head *node, *next;
list_for_each_safe(node, next, &handler->h_list) {
struct input_handle * handle = to_handle_h(node);
@@ -517,16 +1108,14 @@
if (handler->fops != NULL)
input_table[handler->minor >> 5] = NULL;
-#ifdef CONFIG_PROC_FS
- input_devices_state++;
- wake_up(&input_devices_poll_wait);
-#endif
+ input_wakeup_procfs_readers();
}
+EXPORT_SYMBOL(input_unregister_handler);
static int input_open_file(struct inode *inode, struct file *file)
{
struct input_handler *handler = input_table[iminor(inode) >> 5];
- struct file_operations *old_fops, *new_fops = NULL;
+ const struct file_operations *old_fops, *new_fops = NULL;
int err;
/* No load-on-demand here? */
@@ -554,210 +1143,43 @@
return err;
}
-static struct file_operations input_fops = {
+static const struct file_operations input_fops = {
.owner = THIS_MODULE,
.open = input_open_file,
};
-#ifdef CONFIG_PROC_FS
-
-#define SPRINTF_BIT_B(bit, name, max) \
- do { \
- len += sprintf(buf + len, "B: %s", name); \
- for (i = NBITS(max) - 1; i >= 0; i--) \
- if (dev->bit[i]) break; \
- for (; i >= 0; i--) \
- len += sprintf(buf + len, "%lx ", dev->bit[i]); \
- len += sprintf(buf + len, "\n"); \
- } while (0)
-
-#define SPRINTF_BIT_B2(bit, name, max, ev) \
- do { \
- if (test_bit(ev, dev->evbit)) \
- SPRINTF_BIT_B(bit, name, max); \
- } while (0)
-
-
-static unsigned int input_devices_poll(struct file *file, poll_table *wait)
+static int __init input_init(void)
{
- int state = input_devices_state;
- poll_wait(file, &input_devices_poll_wait, wait);
- if (state != input_devices_state)
- return POLLIN | POLLRDNORM;
- return 0;
-}
+ int err;
-static int input_devices_read(char *buf, char **start, off_t pos, int count, int *eof, void *data)
-{
- struct input_dev *dev;
- struct input_handle *handle;
-
- off_t at = 0;
- int i, len, cnt = 0;
-
- list_for_each_entry(dev, &input_dev_list, node) {
-
- len = sprintf(buf, "I: Bus=%04x Vendor=%04x Product=%04x Version=%04x\n",
- dev->id.bustype, dev->id.vendor, dev->id.product, dev->id.version);
-
- len += sprintf(buf + len, "N: Name=\"%s\"\n", dev->name ? dev->name : "");
- len += sprintf(buf + len, "P: Phys=%s\n", dev->phys ? dev->phys : "");
- len += sprintf(buf + len, "H: Handlers=");
-
- list_for_each_entry(handle, &dev->h_list, d_node)
- len += sprintf(buf + len, "%s ", handle->name);
-
- len += sprintf(buf + len, "\n");
-
- SPRINTF_BIT_B(evbit, "EV=", EV_MAX);
- SPRINTF_BIT_B2(keybit, "KEY=", KEY_MAX, EV_KEY);
- SPRINTF_BIT_B2(relbit, "REL=", REL_MAX, EV_REL);
- SPRINTF_BIT_B2(absbit, "ABS=", ABS_MAX, EV_ABS);
- SPRINTF_BIT_B2(mscbit, "MSC=", MSC_MAX, EV_MSC);
- SPRINTF_BIT_B2(ledbit, "LED=", LED_MAX, EV_LED);
- SPRINTF_BIT_B2(sndbit, "SND=", SND_MAX, EV_SND);
- SPRINTF_BIT_B2(ffbit, "FF=", FF_MAX, EV_FF);
-
- len += sprintf(buf + len, "\n");
-
- at += len;
-
- if (at >= pos) {
- if (!*start) {
- *start = buf + (pos - (at - len));
- cnt = at - pos;
- } else cnt += len;
- buf += len;
- if (cnt >= count)
- break;
- }
+ err = class_register(&input_class);
+ if (err) {
+ printk(KERN_ERR "input: unable to register input_dev class\n");
+ return err;
}
- if (&dev->node == &input_dev_list)
- *eof = 1;
+ err = input_proc_init();
+ if (err)
+ goto fail1;
- return (count > cnt) ? cnt : count;
-}
-
-static int input_handlers_read(char *buf, char **start, off_t pos, int count, int *eof, void *data)
-{
- struct input_handler *handler;
-
- off_t at = 0;
- int len = 0, cnt = 0;
- int i = 0;
-
- list_for_each_entry(handler, &input_handler_list, node) {
-
- if (handler->fops)
- len = sprintf(buf, "N: Number=%d Name=%s Minor=%d\n",
- i++, handler->name, handler->minor);
- else
- len = sprintf(buf, "N: Number=%d Name=%s\n",
- i++, handler->name);
-
- at += len;
-
- if (at >= pos) {
- if (!*start) {
- *start = buf + (pos - (at - len));
- cnt = at - pos;
- } else cnt += len;
- buf += len;
- if (cnt >= count)
- break;
- }
+ err = register_chrdev(INPUT_MAJOR, "input", &input_fops);
+ if (err) {
+ printk(KERN_ERR "input: unable to register char major %d", INPUT_MAJOR);
+ goto fail2;
}
- if (&handler->node == &input_handler_list)
- *eof = 1;
- return (count > cnt) ? cnt : count;
-}
-
-static int __init input_proc_init(void)
-{
- struct proc_dir_entry *entry;
-
- proc_bus_input_dir = proc_mkdir("input", proc_bus);
- if (proc_bus_input_dir == NULL)
- return -ENOMEM;
- proc_bus_input_dir->owner = THIS_MODULE;
- entry = create_proc_read_entry("devices", 0, proc_bus_input_dir, input_devices_read, NULL);
- if (entry == NULL) {
- remove_proc_entry("input", proc_bus);
- return -ENOMEM;
- }
- entry->owner = THIS_MODULE;
- entry->proc_fops->poll = input_devices_poll;
- entry = create_proc_read_entry("handlers", 0, proc_bus_input_dir, input_handlers_read, NULL);
- if (entry == NULL) {
- remove_proc_entry("devices", proc_bus_input_dir);
- remove_proc_entry("input", proc_bus);
- return -ENOMEM;
- }
- entry->owner = THIS_MODULE;
return 0;
-}
-struct input_handle *input_find_handle(char *phys_descr)
-{
- struct input_dev *dev;
- struct input_handle *handle;
-
- list_for_each_entry(dev, &input_dev_list, node) {
- list_for_each_entry(handle, &dev->h_list, d_node) {
- if(!strcmp(handle->name,"kbd") && !strcmp(phys_descr,dev->phys) )
- return handle;
- }
- }
- printk(KERN_WARNING "input: no matching device for \"%s\"\n", phys_descr);
- return NULL;
-}
-
-#else /* !CONFIG_PROC_FS */
-static inline int input_proc_init(void) { return 0; }
-#endif
-
-struct class_simple *input_class;
-
-static int __init input_init(void)
-{
- int retval = -ENOMEM;
-
- input_class = class_simple_create(THIS_MODULE, "input");
- if (IS_ERR(input_class))
- return PTR_ERR(input_class);
- input_proc_init();
- retval = register_chrdev(INPUT_MAJOR, "input", &input_fops);
- if (retval) {
- printk(KERN_ERR "input: unable to register char major %d", INPUT_MAJOR);
- remove_proc_entry("devices", proc_bus_input_dir);
- remove_proc_entry("handlers", proc_bus_input_dir);
- remove_proc_entry("input", proc_bus);
- class_simple_destroy(input_class);
- return retval;
- }
-
- retval = devfs_mk_dir("input");
- if (retval) {
- remove_proc_entry("devices", proc_bus_input_dir);
- remove_proc_entry("handlers", proc_bus_input_dir);
- remove_proc_entry("input", proc_bus);
- unregister_chrdev(INPUT_MAJOR, "input");
- class_simple_destroy(input_class);
- }
- return retval;
+ fail2: input_proc_exit();
+ fail1: class_unregister(&input_class);
+ return err;
}
static void __exit input_exit(void)
{
- remove_proc_entry("devices", proc_bus_input_dir);
- remove_proc_entry("handlers", proc_bus_input_dir);
- remove_proc_entry("input", proc_bus);
-
- devfs_remove("input");
+ input_proc_exit();
unregister_chrdev(INPUT_MAJOR, "input");
- class_simple_destroy(input_class);
+ class_unregister(&input_class);
}
subsys_initcall(input_init);
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <jsi...@us...> - 2007-04-10 13:39:59
|
Revision: 2363
http://linuxconsole.svn.sourceforge.net/linuxconsole/?rev=2363&view=rev
Author: jsimmons
Date: 2007-04-10 06:36:51 -0700 (Tue, 10 Apr 2007)
Log Message:
-----------
merge vgacon to 2.6.21
Modified Paths:
--------------
branches/ruby-2.6.21/ruby-2.6/drivers/video/console/vgacon.c
Modified: branches/ruby-2.6.21/ruby-2.6/drivers/video/console/vgacon.c
===================================================================
--- branches/ruby-2.6.21/ruby-2.6/drivers/video/console/vgacon.c 2007-04-10 02:01:16 UTC (rev 2362)
+++ branches/ruby-2.6.21/ruby-2.6/drivers/video/console/vgacon.c 2007-04-10 13:36:51 UTC (rev 2363)
@@ -33,13 +33,10 @@
* more details.
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/types.h>
-#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/kernel.h>
-#include <linux/tty.h>
#include <linux/console.h>
#include <linux/string.h>
#include <linux/slab.h>
@@ -48,6 +45,8 @@
#include <linux/spinlock.h>
#include <linux/ioport.h>
#include <linux/init.h>
+#include <linux/screen_info.h>
+#include <linux/smp_lock.h>
#ifdef CONFIG_IA64
#include <linux/efi.h>
#endif
@@ -96,22 +95,22 @@
static void vgacon_invert_region(struct vc_data *c, u16 * p, int count);
static unsigned long vgacon_uni_pagedir[2];
-
/* Description of the hardware situation */
-static unsigned long vga_vram_base; /* Base of video memory */
-static unsigned long vga_vram_end; /* End of video memory */
-static int vga_vram_size; /* Size of video memory */
-static u16 vga_video_port_reg; /* Video register select port */
-static u16 vga_video_port_val; /* Video register value port */
-static unsigned char vga_video_type; /* Card type */
-static unsigned char vga_hardscroll_enabled;
-static unsigned char vga_hardscroll_user_enable = 1;
+static int vga_init_done __read_mostly;
+static unsigned long vga_vram_base __read_mostly; /* Base of video memory */
+static unsigned long vga_vram_end __read_mostly; /* End of video memory */
+static unsigned int vga_vram_size __read_mostly; /* Size of video memory */
+static u16 vga_video_port_reg __read_mostly; /* Video register select port */
+static u16 vga_video_port_val __read_mostly; /* Video register value port */
+static unsigned char vga_video_type __read_mostly; /* Card type */
+static unsigned char vga_hardscroll_enabled __read_mostly;
+static unsigned char vga_hardscroll_user_enable __read_mostly = 1;
static unsigned char vga_font_is_default = 1;
static int vga_vesa_blanked;
static int vga_palette_blanked;
static int vga_is_gfx;
static int vga_512_chars;
-static unsigned int vga_rolled_over = 0;
+static unsigned int vga_rolled_over;
static int __init no_scroll(char *str)
{
@@ -158,8 +157,203 @@
spin_unlock_irqrestore(&vga_lock, flags);
}
-static const char __init *vgacon_startup(struct vt_struct *vt, int init)
+static inline void vga_set_mem_top(struct vc_data *c)
{
+ write_vga(12, (c->vc_visible_origin - vga_vram_base) / 2);
+}
+
+#ifdef CONFIG_VGACON_SOFT_SCROLLBACK
+#include <linux/bootmem.h>
+/* software scrollback */
+static void *vgacon_scrollback;
+static int vgacon_scrollback_tail;
+static int vgacon_scrollback_size;
+static int vgacon_scrollback_rows;
+static int vgacon_scrollback_cnt;
+static int vgacon_scrollback_cur;
+static int vgacon_scrollback_save;
+static int vgacon_scrollback_restore;
+
+static void vgacon_scrollback_init(int pitch)
+{
+ int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
+
+ if (vgacon_scrollback) {
+ vgacon_scrollback_cnt = 0;
+ vgacon_scrollback_tail = 0;
+ vgacon_scrollback_cur = 0;
+ vgacon_scrollback_rows = rows - 1;
+ vgacon_scrollback_size = rows * pitch;
+ }
+}
+
+static void vgacon_scrollback_startup(void)
+{
+ vgacon_scrollback = alloc_bootmem(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE
+ * 1024);
+ vgacon_scrollback_init(vga_video_num_columns * 2);
+}
+
+static void vgacon_scrollback_update(struct vc_data *c, int t, int count)
+{
+ void *p;
+
+ if (!vgacon_scrollback_size || c->vc_num != fg_console)
+ return;
+
+ p = (void *) (c->vc_origin + t * c->vc_size_row);
+
+ while (count--) {
+ scr_memcpyw(vgacon_scrollback + vgacon_scrollback_tail,
+ p, c->vc_size_row);
+ vgacon_scrollback_cnt++;
+ p += c->vc_size_row;
+ vgacon_scrollback_tail += c->vc_size_row;
+
+ if (vgacon_scrollback_tail >= vgacon_scrollback_size)
+ vgacon_scrollback_tail = 0;
+
+ if (vgacon_scrollback_cnt > vgacon_scrollback_rows)
+ vgacon_scrollback_cnt = vgacon_scrollback_rows;
+
+ vgacon_scrollback_cur = vgacon_scrollback_cnt;
+ }
+}
+
+static void vgacon_restore_screen(struct vc_data *c)
+{
+ vgacon_scrollback_save = 0;
+
+ if (!vga_is_gfx && !vgacon_scrollback_restore) {
+ scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf,
+ c->vc_screenbuf_size > vga_vram_size ?
+ vga_vram_size : c->vc_screenbuf_size);
+ vgacon_scrollback_restore = 1;
+ vgacon_scrollback_cur = vgacon_scrollback_cnt;
+ }
+}
+
+static int vgacon_scroll(struct vc_data *c, int lines)
+{
+ int start, end, count, soff, diff;
+ void *d, *s;
+
+ if (!lines) {
+ c->vc_visible_origin = c->vc_origin;
+ vga_set_mem_top(c);
+ return 1;
+ }
+
+ if (!vgacon_scrollback)
+ return 1;
+
+ if (!vgacon_scrollback_save) {
+ vgacon_cursor(c, CM_ERASE);
+ vgacon_save_screen(c);
+ vgacon_scrollback_save = 1;
+ }
+
+ vgacon_scrollback_restore = 0;
+ start = vgacon_scrollback_cur + lines;
+ end = start + abs(lines);
+
+ if (start < 0)
+ start = 0;
+
+ if (start > vgacon_scrollback_cnt)
+ start = vgacon_scrollback_cnt;
+
+ if (end < 0)
+ end = 0;
+
+ if (end > vgacon_scrollback_cnt)
+ end = vgacon_scrollback_cnt;
+
+ vgacon_scrollback_cur = start;
+ count = end - start;
+ soff = vgacon_scrollback_tail - ((vgacon_scrollback_cnt - end) *
+ c->vc_size_row);
+ soff -= count * c->vc_size_row;
+
+ if (soff < 0)
+ soff += vgacon_scrollback_size;
+
+ count = vgacon_scrollback_cnt - start;
+
+ if (count > c->vc_rows)
+ count = c->vc_rows;
+
+ diff = c->vc_rows - count;
+
+ d = (void *) c->vc_origin;
+ s = (void *) c->vc_screenbuf;
+
+ while (count--) {
+ scr_memcpyw(d, vgacon_scrollback + soff, c->vc_size_row);
+ d += c->vc_size_row;
+ soff += c->vc_size_row;
+
+ if (soff >= vgacon_scrollback_size)
+ soff = 0;
+ }
+
+ if (diff == c->vc_rows) {
+ vgacon_cursor(c, CM_MOVE);
+ } else {
+ while (diff--) {
+ scr_memcpyw(d, s, c->vc_size_row);
+ d += c->vc_size_row;
+ s += c->vc_size_row;
+ }
+ }
+
+ return 1;
+}
+#else
+#define vgacon_scrollback_startup(...) do { } while (0)
+#define vgacon_scrollback_init(...) do { } while (0)
+#define vgacon_scrollback_update(...) do { } while (0)
+
+static void vgacon_restore_screen(struct vc_data *c)
+{
+ if (c->vc_origin != c->vc_visible_origin)
+ vgacon_scroll(c, 0);
+}
+
+static int vgacon_scroll(struct vc_data *c, int lines)
+{
+ if (!lines) /* Turn scrollback off */
+ c->vc_visible_origin = c->vc_origin;
+ else {
+ int margin = c->vc_size_row * 4;
+ int ul, we, p, st;
+
+ if (vga_rolled_over >
+ (c->vc_scr_end - vga_vram_base) + margin) {
+ ul = c->vc_scr_end - vga_vram_base;
+ we = vga_rolled_over + c->vc_size_row;
+ } else {
+ ul = 0;
+ we = vga_vram_size;
+ }
+ p = (c->vc_visible_origin - vga_vram_base - ul + we) % we +
+ lines * c->vc_size_row;
+ st = (c->vc_origin - vga_vram_base - ul + we) % we;
+ if (st < 2 * margin)
+ margin = 0;
+ if (p < margin)
+ p = 0;
+ if (p > st - margin)
+ p = st;
+ c->vc_visible_origin = vga_vram_base + (p + ul) % we;
+ }
+ vga_set_mem_top(c);
+ return 1;
+}
+#endif /* CONFIG_VGACON_SOFT_SCROLLBACK */
+
+static const char *vgacon_startup(struct vt_struct *vt, int init)
+{
struct vc_data *vc = &vga_default;
const char *display_desc = NULL;
u16 saved1, saved2;
@@ -194,19 +388,19 @@
vga_video_port_val = VGA_CRT_DM;
if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10) {
static struct resource ega_console_resource =
- { "ega", 0x3B0, 0x3BF };
+ { .name = "ega", .start = 0x3B0, .end = 0x3BF };
vga_video_type = VIDEO_TYPE_EGAM;
- vga_vram_end = 0xb8000;
+ vga_vram_size = 0x8000;
display_desc = "EGA+";
request_resource(&ioport_resource,
&ega_console_resource);
} else {
static struct resource mda1_console_resource =
- { "mda", 0x3B0, 0x3BB };
+ { .name = "mda", .start = 0x3B0, .end = 0x3BB };
static struct resource mda2_console_resource =
- { "mda", 0x3BF, 0x3BF };
+ { .name = "mda", .start = 0x3BF, .end = 0x3BF };
vga_video_type = VIDEO_TYPE_MDA;
- vga_vram_end = 0xb2000;
+ vga_vram_size = 0x2000;
display_desc = "*MDA";
request_resource(&ioport_resource,
&mda1_console_resource);
@@ -223,18 +417,18 @@
if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10) {
int i;
- vga_vram_end = 0xc0000;
+ vga_vram_size = 0x8000;
if (!ORIG_VIDEO_ISVGA) {
static struct resource ega_console_resource
- = { "ega", 0x3C0, 0x3DF };
+ = { .name = "ega", .start = 0x3C0, .end = 0x3DF };
vga_video_type = VIDEO_TYPE_EGAC;
display_desc = "EGA";
request_resource(&ioport_resource,
&ega_console_resource);
} else {
static struct resource vga_console_resource
- = { "vga+", 0x3C0, 0x3DF };
+ = { .name = "vga+", .start = 0x3C0, .end = 0x3DF };
vga_video_type = VIDEO_TYPE_VGAC;
display_desc = "VGA+";
request_resource(&ioport_resource,
@@ -248,7 +442,7 @@
* and COE=1 isn't necessarily a good idea)
*/
vga_vram_base = 0xa0000;
- vga_vram_end = 0xb0000;
+ vga_vram_size = 0x10000;
outb_p(6, VGA_GFX_I);
outb_p(6, VGA_GFX_D);
#endif
@@ -278,9 +472,9 @@
}
} else {
static struct resource cga_console_resource =
- { "cga", 0x3D4, 0x3D5 };
+ { .name = "cga", .start = 0x3D4, .end = 0x3D5 };
vga_video_type = VIDEO_TYPE_CGA;
- vga_vram_end = 0xba000;
+ vga_vram_size = 0x2000;
display_desc = "*CGA";
request_resource(&ioport_resource,
&cga_console_resource);
@@ -288,9 +482,8 @@
}
}
- vga_vram_base = VGA_MAP_MEM(vga_vram_base);
- vga_vram_end = VGA_MAP_MEM(vga_vram_end);
- vga_vram_size = vga_vram_end - vga_vram_base;
+ vga_vram_base = VGA_MAP_MEM(vga_vram_base, vga_vram_size);
+ vga_vram_end = vga_vram_base + vga_vram_size;
/*
* Find out if there is a graphics card present.
@@ -324,6 +517,12 @@
/* This may be suboptimal but is a safe bet - go with it */
vc->vc_scan_lines = vc->vc_font.height * vc->vc_rows;
}
+
+ if (!vga_init_done) {
+ vgacon_scrollback_startup();
+ vga_init_done = 1;
+ }
+
return display_desc;
}
@@ -332,13 +531,22 @@
struct vc_data *default_mode = c->display_fg->default_mode;
unsigned long p;
- /* We cannot be loaded as a module, therefore init is always 1 */
+ /*
+ * We cannot be loaded as a module, therefore init is always 1,
+ * but vgacon_init can be called more than once, and init will
+ * not be 1.
+ */
c->vc_can_do_color = default_mode->vc_can_do_color;
+
+ /* set dimensions manually if init != 0 since vc_resize() will fail */
c->vc_cols = default_mode->vc_cols;
c->vc_rows = default_mode->vc_rows;
+
c->vc_scan_lines = default_mode->vc_scan_lines;
c->vc_font.height = default_mode->vc_font.height;
c->vc_complement_mask = 0x7700;
+ if (vga_512_chars)
+ c->vc_hi_font_mask = 0x0800;
p = *c->vc_uni_pagedir_loc;
if (c->vc_uni_pagedir_loc == &c->vc_uni_pagedir ||
!--c->vc_uni_pagedir_loc[1])
@@ -349,11 +557,6 @@
con_set_default_unimap(c);
}
-static inline void vga_set_mem_top(struct vc_data *c)
-{
- write_vga(12, (c->vc_visible_origin - vga_vram_base) / 2);
-}
-
static void vgacon_deinit(struct vc_data *c)
{
/* When closing the last console, reset video origin */
@@ -425,28 +628,37 @@
cursor_size_lastto = to;
spin_lock_irqsave(&vga_lock, flags);
- outb_p(0x0a, vga_video_port_reg); /* Cursor start */
- curs = inb_p(vga_video_port_val);
- outb_p(0x0b, vga_video_port_reg); /* Cursor end */
- cure = inb_p(vga_video_port_val);
+ if (vga_video_type >= VIDEO_TYPE_VGAC) {
+ outb_p(VGA_CRTC_CURSOR_START, vga_video_port_reg);
+ curs = inb_p(vga_video_port_val);
+ outb_p(VGA_CRTC_CURSOR_END, vga_video_port_reg);
+ cure = inb_p(vga_video_port_val);
+ } else {
+ curs = 0;
+ cure = 0;
+ }
curs = (curs & 0xc0) | from;
cure = (cure & 0xe0) | to;
- outb_p(0x0a, vga_video_port_reg); /* Cursor start */
+ outb_p(VGA_CRTC_CURSOR_START, vga_video_port_reg);
outb_p(curs, vga_video_port_val);
- outb_p(0x0b, vga_video_port_reg); /* Cursor end */
+ outb_p(VGA_CRTC_CURSOR_END, vga_video_port_reg);
outb_p(cure, vga_video_port_val);
spin_unlock_irqrestore(&vga_lock, flags);
}
static void vgacon_cursor(struct vc_data *c, int mode)
{
- if (c->vc_origin != c->vc_visible_origin)
- vgacon_scroll(c, 0);
+ vgacon_restore_screen(c);
+
switch (mode) {
case CM_ERASE:
- write_vga(14, (vga_vram_end - vga_vram_base - 1) / 2);
+ write_vga(14, (c->vc_pos - vga_vram_base) / 2);
+ if (vga_video_type >= VIDEO_TYPE_VGAC)
+ vgacon_set_cursor_size(c->vc_x, 31, 30);
+ else
+ vgacon_set_cursor_size(c->vc_x, 31, 31);
break;
case CM_MOVE:
@@ -484,7 +696,10 @@
10 ? 1 : 2));
break;
case CUR_NONE:
- vgacon_set_cursor_size(c->vc_x, 31, 30);
+ if (vga_video_type >= VIDEO_TYPE_VGAC)
+ vgacon_set_cursor_size(c->vc_x, 31, 30);
+ else
+ vgacon_set_cursor_size(c->vc_x, 31, 31);
break;
default:
vgacon_set_cursor_size(c->vc_x, 1,
@@ -495,14 +710,88 @@
}
}
+static int vgacon_doresize(struct vc_data *c,
+ unsigned int width, unsigned int height)
+{
+ unsigned long flags;
+ unsigned int scanlines = height * c->vc_font.height;
+ u8 scanlines_lo = 0, r7 = 0, vsync_end = 0, mode, max_scan;
+
+ spin_lock_irqsave(&vga_lock, flags);
+
+ vgacon_xres = width * VGA_FONTWIDTH;
+ vgacon_yres = height * c->vc_font.height;
+ if (vga_video_type >= VIDEO_TYPE_VGAC) {
+ outb_p(VGA_CRTC_MAX_SCAN, vga_video_port_reg);
+ max_scan = inb_p(vga_video_port_val);
+
+ if (max_scan & 0x80)
+ scanlines <<= 1;
+
+ outb_p(VGA_CRTC_MODE, vga_video_port_reg);
+ mode = inb_p(vga_video_port_val);
+
+ if (mode & 0x04)
+ scanlines >>= 1;
+
+ scanlines -= 1;
+ scanlines_lo = scanlines & 0xff;
+
+ outb_p(VGA_CRTC_OVERFLOW, vga_video_port_reg);
+ r7 = inb_p(vga_video_port_val) & ~0x42;
+
+ if (scanlines & 0x100)
+ r7 |= 0x02;
+ if (scanlines & 0x200)
+ r7 |= 0x40;
+
+ /* deprotect registers */
+ outb_p(VGA_CRTC_V_SYNC_END, vga_video_port_reg);
+ vsync_end = inb_p(vga_video_port_val);
+ outb_p(VGA_CRTC_V_SYNC_END, vga_video_port_reg);
+ outb_p(vsync_end & ~0x80, vga_video_port_val);
+ }
+
+ outb_p(VGA_CRTC_H_DISP, vga_video_port_reg);
+ outb_p(width - 1, vga_video_port_val);
+ outb_p(VGA_CRTC_OFFSET, vga_video_port_reg);
+ outb_p(width >> 1, vga_video_port_val);
+
+ if (vga_video_type >= VIDEO_TYPE_VGAC) {
+ outb_p(VGA_CRTC_V_DISP_END, vga_video_port_reg);
+ outb_p(scanlines_lo, vga_video_port_val);
+ outb_p(VGA_CRTC_OVERFLOW, vga_video_port_reg);
+ outb_p(r7,vga_video_port_val);
+
+ /* reprotect registers */
+ outb_p(VGA_CRTC_V_SYNC_END, vga_video_port_reg);
+ outb_p(vsync_end, vga_video_port_val);
+ }
+
+ spin_unlock_irqrestore(&vga_lock, flags);
+ return 0;
+}
+
static int vgacon_switch(struct vc_data *c)
{
/* We can only copy out the size of the video buffer here,
- * otherwise we get into VGA BIOS */
+ * otherwise we get into VGA BIOS. We can only copy out
+ * the size of the video buffer here, otherwise we get
+ * into VGA BIOS */
- if (!vga_is_gfx)
+ if (!vga_is_gfx) {
scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf,
- c->vc_screenbuf_size > vga_vram_size ? vga_vram_size : c->vc_screenbuf_size);
+ c->vc_screenbuf_size > vga_vram_size ?
+ vga_vram_size : c->vc_screenbuf_size);
+
+ if ((vgacon_xres != x || vgacon_yres != y) &&
+ (!(vga_video_num_columns % 2) &&
+ vga_video_num_columns <= ORIG_VIDEO_COLS &&
+ vga_video_num_lines <= rows))
+ vgacon_doresize(c, c->vc_cols, c->vc_rows);
+ }
+
+ vgacon_scrollback_init(c->vc_size_row);
return 0; /* Redrawing not needed */
}
@@ -510,6 +799,7 @@
{
int i, j;
+ vga_w(state.vgabase, VGA_PEL_MSK, 0xff);
for (i = j = 0; i < 16; i++) {
vga_w(state.vgabase, VGA_PEL_IW, table[i]);
vga_w(state.vgabase, VGA_PEL_D, vc->vc_palette[j++] >> 2);
@@ -651,6 +941,7 @@
{
int i;
+ vga_w(state->vgabase, VGA_PEL_MSK, 0xff);
for (i = 0; i < 16; i++) {
vga_w(state->vgabase, VGA_PEL_IW, i);
vga_w(state->vgabase, VGA_PEL_D, 0);
@@ -724,14 +1015,14 @@
char *charmap;
if (vga_video_type != VIDEO_TYPE_EGAM) {
- charmap = (char *) VGA_MAP_MEM(colourmap);
+ charmap = (char *) VGA_MAP_MEM(colourmap, 0);
beg = 0x0e;
#ifdef VGA_CAN_DO_64KB
if (vga_video_type == VIDEO_TYPE_VGAC)
beg = 0x06;
#endif
} else {
- charmap = (char *) VGA_MAP_MEM(blackwmap);
+ charmap = (char *) VGA_MAP_MEM(blackwmap, 0);
beg = 0x0a;
}
@@ -951,35 +1242,18 @@
#endif
-static int vgacon_scroll(struct vc_data *c, int lines)
+static int vgacon_resize(struct vc_data *c, unsigned int width,
+ unsigned int height)
{
- if (!lines) /* Turn scrollback off */
- c->vc_visible_origin = c->vc_origin;
- else {
- int margin = c->vc_size_row * 4;
- int ul, we, p, st;
+ if (width % 2 || width > ORIG_VIDEO_COLS ||
+ height > (ORIG_VIDEO_LINES * vga_default_font_height)/
+ c->vc_font.height)
+ /* let svgatextmode tinker with video timings */
+ return 0;
- if (vga_rolled_over >
- (c->vc_scr_end - vga_vram_base) + margin) {
- ul = c->vc_scr_end - vga_vram_base;
- we = vga_rolled_over + c->vc_size_row;
- } else {
- ul = 0;
- we = vga_vram_size;
- }
- p = (c->vc_visible_origin - vga_vram_base - ul + we) % we +
- lines * c->vc_size_row;
- st = (c->vc_origin - vga_vram_base - ul + we) % we;
- if (st < 2 * margin)
- margin = 0;
- if (p < margin)
- p = 0;
- if (p > st - margin)
- p = st;
- c->vc_visible_origin = vga_vram_base + (p + ul) % we;
- }
- vga_set_mem_top(c);
- return 1;
+ if (IS_VISIBLE && !vga_is_gfx) /* who knows */
+ vgacon_doresize(c, width, height);
+ return 0;
}
static int vgacon_set_origin(struct vc_data *c)
@@ -997,6 +1271,7 @@
{
/* We can't copy in more then the size of the video buffer,
* or we'll be copying in VGA BIOS */
+
if (!vga_is_gfx)
scr_memcpyw((u16 *) c->vc_screenbuf, (u16 *) c->vc_origin,
c->vc_screenbuf_size > vga_vram_size ? vga_vram_size : c->vc_screenbuf_size);
@@ -1011,15 +1286,14 @@
if (t || b != c->vc_rows || vga_is_gfx)
return 0;
- if (c->vc_origin != c->vc_visible_origin)
- vgacon_scroll(c, 0);
-
if (!vga_hardscroll_enabled || lines >= c->vc_rows / 2)
return 0;
+ vgacon_restore_screen(c);
oldo = c->vc_origin;
delta = lines * c->vc_size_row;
if (dir == SM_UP) {
+ vgacon_scrollback_update(c, t, lines);
if (c->vc_scr_end + delta >= vga_vram_end) {
scr_memcpyw((u16 *) vga_vram_base,
(u16 *) (oldo + delta),
@@ -1079,6 +1353,7 @@
.con_blank = vgacon_blank,
.con_font_set = vgacon_font_set,
.con_font_get = vgacon_font_get,
+ .con_resize = vgacon_resize,
.con_set_palette = vgacon_set_palette,
.con_scroll = vgacon_scroll,
.con_set_origin = vgacon_set_origin,
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <jsi...@us...> - 2007-04-10 02:01:17
|
Revision: 2362
http://linuxconsole.svn.sourceforge.net/linuxconsole/?rev=2362&view=rev
Author: jsimmons
Date: 2007-04-09 19:01:16 -0700 (Mon, 09 Apr 2007)
Log Message:
-----------
files ported over to 2.6.21. More to go
Modified Paths:
--------------
branches/ruby-2.6.21/ruby-2.6/arch/i386/kernel/setup.c
branches/ruby-2.6.21/ruby-2.6/arch/x86_64/kernel/setup.c
branches/ruby-2.6.21/ruby-2.6/fs/compat_ioctl.c
branches/ruby-2.6.21/ruby-2.6/include/linux/console.h
branches/ruby-2.6.21/ruby-2.6/include/linux/consolemap.h
branches/ruby-2.6.21/ruby-2.6/include/linux/kbd_kern.h
branches/ruby-2.6.21/ruby-2.6/include/linux/selection.h
branches/ruby-2.6.21/ruby-2.6/include/linux/tty.h
branches/ruby-2.6.21/ruby-2.6/include/linux/vt_kern.h
Modified: branches/ruby-2.6.21/ruby-2.6/arch/i386/kernel/setup.c
===================================================================
--- branches/ruby-2.6.21/ruby-2.6/arch/i386/kernel/setup.c 2007-04-10 01:57:48 UTC (rev 2361)
+++ branches/ruby-2.6.21/ruby-2.6/arch/i386/kernel/setup.c 2007-04-10 02:01:16 UTC (rev 2362)
@@ -25,7 +25,8 @@
#include <linux/sched.h>
#include <linux/mm.h>
-#include <linux/tty.h>
+#include <linux/mmzone.h>
+#include <linux/screen_info.h>
#include <linux/ioport.h>
#include <linux/acpi.h>
#include <linux/apm_bios.h>
@@ -40,16 +41,25 @@
#include <linux/init.h>
#include <linux/edd.h>
#include <linux/nodemask.h>
+#include <linux/kexec.h>
+#include <linux/crash_dump.h>
+#include <linux/dmi.h>
+#include <linux/pfn.h>
+
#include <video/edid.h>
+
+#include <asm/apic.h>
#include <asm/e820.h>
#include <asm/mpspec.h>
+#include <asm/mmzone.h>
#include <asm/setup.h>
#include <asm/arch_hooks.h>
#include <asm/sections.h>
#include <asm/io_apic.h>
#include <asm/ist.h>
#include <asm/io.h>
-#include "setup_arch_pre.h"
+#include <asm/vmi.h>
+#include <setup_arch.h>
#include <bios_ebda.h>
/* This value is set up by the early boot code to point to the value
@@ -57,45 +67,31 @@
address, and must not be in the .bss segment! */
unsigned long init_pg_tables_end __initdata = ~0UL;
-int disable_pse __initdata = 0;
+int disable_pse __devinitdata = 0;
/*
* Machine setup..
*/
+extern struct resource code_resource;
+extern struct resource data_resource;
-#ifdef CONFIG_EFI
-int efi_enabled = 0;
-EXPORT_SYMBOL(efi_enabled);
-#endif
-
/* cpu data as detected by the assembly code in head.S */
-struct cpuinfo_x86 new_cpu_data __initdata = { 0, 0, 0, 0, -1, 1, 0, 0, -1 };
+struct cpuinfo_x86 new_cpu_data __cpuinitdata = { 0, 0, 0, 0, -1, 1, 0, 0, -1 };
/* common cpu data for all cpus */
-struct cpuinfo_x86 boot_cpu_data = { 0, 0, 0, 0, -1, 1, 0, 0, -1 };
+struct cpuinfo_x86 boot_cpu_data __read_mostly = { 0, 0, 0, 0, -1, 1, 0, 0, -1 };
+EXPORT_SYMBOL(boot_cpu_data);
unsigned long mmu_cr4_features;
-#ifdef CONFIG_ACPI_INTERPRETER
- int acpi_disabled = 0;
-#else
- int acpi_disabled = 1;
-#endif
-EXPORT_SYMBOL(acpi_disabled);
-
-#ifdef CONFIG_ACPI_BOOT
-int __initdata acpi_force = 0;
-extern acpi_interrupt_flags acpi_sci_flags;
-#endif
-
/* for MCA, but anyone else can use it if they want */
unsigned int machine_id;
+#ifdef CONFIG_MCA
+EXPORT_SYMBOL(machine_id);
+#endif
unsigned int machine_submodel_id;
unsigned int BIOS_revision;
unsigned int mca_pentium_flag;
-/* For PCI or other memory-mapped resources */
-unsigned long pci_mem_start = 0x10000000;
-
/* Boot loader ID as an integer, for the benefit of proc_dointvec */
int bootloader_type;
@@ -106,19 +102,27 @@
* Setup options
*/
struct drive_info_struct { char dummy[32]; } drive_info;
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_HD) || \
+ defined(CONFIG_BLK_DEV_IDE_MODULE) || defined(CONFIG_BLK_DEV_HD_MODULE)
+EXPORT_SYMBOL(drive_info);
+#endif
struct screen_info screen_info;
+EXPORT_SYMBOL(screen_info);
struct apm_info apm_info;
+EXPORT_SYMBOL(apm_info);
struct sys_desc_table_struct {
unsigned short length;
unsigned char table[0];
};
struct edid_info edid_info;
+EXPORT_SYMBOL_GPL(edid_info);
struct ist_info ist_info;
-struct e820map e820;
+#if defined(CONFIG_X86_SPEEDSTEP_SMI) || \
+ defined(CONFIG_X86_SPEEDSTEP_SMI_MODULE)
+EXPORT_SYMBOL(ist_info);
+#endif
extern void early_cpu_init(void);
-extern void dmi_scan_machine(void);
-extern void generic_apic_probe(char *);
extern int root_mountflags;
unsigned long saved_videomode;
@@ -127,512 +131,10 @@
#define RAMDISK_PROMPT_FLAG 0x8000
#define RAMDISK_LOAD_FLAG 0x4000
-static char command_line[COMMAND_LINE_SIZE];
+static char __initdata command_line[COMMAND_LINE_SIZE];
unsigned char __initdata boot_params[PARAM_SIZE];
-static struct resource data_resource = {
- .name = "Kernel data",
- .start = 0,
- .end = 0,
- .flags = IORESOURCE_BUSY | IORESOURCE_MEM
-};
-
-static struct resource code_resource = {
- .name = "Kernel code",
- .start = 0,
- .end = 0,
- .flags = IORESOURCE_BUSY | IORESOURCE_MEM
-};
-
-static struct resource system_rom_resource = {
- .name = "System ROM",
- .start = 0xf0000,
- .end = 0xfffff,
- .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
-};
-
-static struct resource extension_rom_resource = {
- .name = "Extension ROM",
- .start = 0xe0000,
- .end = 0xeffff,
- .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
-};
-
-static struct resource adapter_rom_resources[] = { {
- .name = "Adapter ROM",
- .start = 0xc8000,
- .end = 0,
- .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
-}, {
- .name = "Adapter ROM",
- .start = 0,
- .end = 0,
- .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
-}, {
- .name = "Adapter ROM",
- .start = 0,
- .end = 0,
- .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
-}, {
- .name = "Adapter ROM",
- .start = 0,
- .end = 0,
- .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
-}, {
- .name = "Adapter ROM",
- .start = 0,
- .end = 0,
- .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
-}, {
- .name = "Adapter ROM",
- .start = 0,
- .end = 0,
- .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
-} };
-
-#define ADAPTER_ROM_RESOURCES \
- (sizeof adapter_rom_resources / sizeof adapter_rom_resources[0])
-
-static struct resource video_rom_resource = {
- .name = "Video ROM",
- .start = 0xc0000,
- .end = 0xc7fff,
- .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
-};
-
-static struct resource video_ram_resource = {
- .name = "Video RAM area",
- .start = 0xa0000,
- .end = 0xbffff,
- .flags = IORESOURCE_BUSY | IORESOURCE_MEM
-};
-
-static struct resource standard_io_resources[] = { {
- .name = "dma1",
- .start = 0x0000,
- .end = 0x001f,
- .flags = IORESOURCE_BUSY | IORESOURCE_IO
-}, {
- .name = "pic1",
- .start = 0x0020,
- .end = 0x0021,
- .flags = IORESOURCE_BUSY | IORESOURCE_IO
-}, {
- .name = "timer0",
- .start = 0x0040,
- .end = 0x0043,
- .flags = IORESOURCE_BUSY | IORESOURCE_IO
-}, {
- .name = "timer1",
- .start = 0x0050,
- .end = 0x0053,
- .flags = IORESOURCE_BUSY | IORESOURCE_IO
-}, {
- .name = "keyboard",
- .start = 0x0060,
- .end = 0x006f,
- .flags = IORESOURCE_BUSY | IORESOURCE_IO
-}, {
- .name = "dma page reg",
- .start = 0x0080,
- .end = 0x008f,
- .flags = IORESOURCE_BUSY | IORESOURCE_IO
-}, {
- .name = "pic2",
- .start = 0x00a0,
- .end = 0x00a1,
- .flags = IORESOURCE_BUSY | IORESOURCE_IO
-}, {
- .name = "dma2",
- .start = 0x00c0,
- .end = 0x00df,
- .flags = IORESOURCE_BUSY | IORESOURCE_IO
-}, {
- .name = "fpu",
- .start = 0x00f0,
- .end = 0x00ff,
- .flags = IORESOURCE_BUSY | IORESOURCE_IO
-} };
-
-#define STANDARD_IO_RESOURCES \
- (sizeof standard_io_resources / sizeof standard_io_resources[0])
-
-#define romsignature(x) (*(unsigned short *)(x) == 0xaa55)
-
-static int __init romchecksum(unsigned char *rom, unsigned long length)
-{
- unsigned char *p, sum = 0;
-
- for (p = rom; p < rom + length; p++)
- sum += *p;
- return sum == 0;
-}
-
-static void __init probe_roms(void)
-{
- unsigned long start, length, upper;
- unsigned char *rom;
- int i;
-
- /* video rom */
- upper = adapter_rom_resources[0].start;
- for (start = video_rom_resource.start; start < upper; start += 2048) {
- rom = isa_bus_to_virt(start);
- if (!romsignature(rom))
- continue;
-
- video_rom_resource.start = start;
-
- /* 0 < length <= 0x7f * 512, historically */
- length = rom[2] * 512;
-
- /* if checksum okay, trust length byte */
- if (length && romchecksum(rom, length))
- video_rom_resource.end = start + length - 1;
-
- request_resource(&iomem_resource, &video_rom_resource);
- break;
- }
-
- start = (video_rom_resource.end + 1 + 2047) & ~2047UL;
- if (start < upper)
- start = upper;
-
- /* system rom */
- request_resource(&iomem_resource, &system_rom_resource);
- upper = system_rom_resource.start;
-
- /* check for extension rom (ignore length byte!) */
- rom = isa_bus_to_virt(extension_rom_resource.start);
- if (romsignature(rom)) {
- length = extension_rom_resource.end - extension_rom_resource.start + 1;
- if (romchecksum(rom, length)) {
- request_resource(&iomem_resource, &extension_rom_resource);
- upper = extension_rom_resource.start;
- }
- }
-
- /* check for adapter roms on 2k boundaries */
- for (i = 0; i < ADAPTER_ROM_RESOURCES && start < upper; start += 2048) {
- rom = isa_bus_to_virt(start);
- if (!romsignature(rom))
- continue;
-
- /* 0 < length <= 0x7f * 512, historically */
- length = rom[2] * 512;
-
- /* but accept any length that fits if checksum okay */
- if (!length || start + length > upper || !romchecksum(rom, length))
- continue;
-
- adapter_rom_resources[i].start = start;
- adapter_rom_resources[i].end = start + length - 1;
- request_resource(&iomem_resource, &adapter_rom_resources[i]);
-
- start = adapter_rom_resources[i++].end & ~2047UL;
- }
-}
-
-static void __init limit_regions(unsigned long long size)
-{
- unsigned long long current_addr = 0;
- int i;
-
- if (efi_enabled) {
- for (i = 0; i < memmap.nr_map; i++) {
- current_addr = memmap.map[i].phys_addr +
- (memmap.map[i].num_pages << 12);
- if (memmap.map[i].type == EFI_CONVENTIONAL_MEMORY) {
- if (current_addr >= size) {
- memmap.map[i].num_pages -=
- (((current_addr-size) + PAGE_SIZE-1) >> PAGE_SHIFT);
- memmap.nr_map = i + 1;
- return;
- }
- }
- }
- }
- for (i = 0; i < e820.nr_map; i++) {
- if (e820.map[i].type == E820_RAM) {
- current_addr = e820.map[i].addr + e820.map[i].size;
- if (current_addr >= size) {
- e820.map[i].size -= current_addr-size;
- e820.nr_map = i + 1;
- return;
- }
- }
- }
-}
-
-static void __init add_memory_region(unsigned long long start,
- unsigned long long size, int type)
-{
- int x;
-
- if (!efi_enabled) {
- x = e820.nr_map;
-
- if (x == E820MAX) {
- printk(KERN_ERR "Ooops! Too many entries in the memory map!\n");
- return;
- }
-
- e820.map[x].addr = start;
- e820.map[x].size = size;
- e820.map[x].type = type;
- e820.nr_map++;
- }
-} /* add_memory_region */
-
-#define E820_DEBUG 1
-
-static void __init print_memory_map(char *who)
-{
- int i;
-
- for (i = 0; i < e820.nr_map; i++) {
- printk(" %s: %016Lx - %016Lx ", who,
- e820.map[i].addr,
- e820.map[i].addr + e820.map[i].size);
- switch (e820.map[i].type) {
- case E820_RAM: printk("(usable)\n");
- break;
- case E820_RESERVED:
- printk("(reserved)\n");
- break;
- case E820_ACPI:
- printk("(ACPI data)\n");
- break;
- case E820_NVS:
- printk("(ACPI NVS)\n");
- break;
- default: printk("type %lu\n", e820.map[i].type);
- break;
- }
- }
-}
-
-/*
- * Sanitize the BIOS e820 map.
- *
- * Some e820 responses include overlapping entries. The following
- * replaces the original e820 map with a new one, removing overlaps.
- *
- */
-struct change_member {
- struct e820entry *pbios; /* pointer to original bios entry */
- unsigned long long addr; /* address for this change point */
-};
-static struct change_member change_point_list[2*E820MAX] __initdata;
-static struct change_member *change_point[2*E820MAX] __initdata;
-static struct e820entry *overlap_list[E820MAX] __initdata;
-static struct e820entry new_bios[E820MAX] __initdata;
-
-static int __init sanitize_e820_map(struct e820entry * biosmap, char * pnr_map)
-{
- struct change_member *change_tmp;
- unsigned long current_type, last_type;
- unsigned long long last_addr;
- int chgidx, still_changing;
- int overlap_entries;
- int new_bios_entry;
- int old_nr, new_nr, chg_nr;
- int i;
-
- /*
- Visually we're performing the following (1,2,3,4 = memory types)...
-
- Sample memory map (w/overlaps):
- ____22__________________
- ______________________4_
- ____1111________________
- _44_____________________
- 11111111________________
- ____________________33__
- ___________44___________
- __________33333_________
- ______________22________
- ___________________2222_
- _________111111111______
- _____________________11_
- _________________4______
-
- Sanitized equivalent (no overlap):
- 1_______________________
- _44_____________________
- ___1____________________
- ____22__________________
- ______11________________
- _________1______________
- __________3_____________
- ___________44___________
- _____________33_________
- _______________2________
- ________________1_______
- _________________4______
- ___________________2____
- ____________________33__
- ______________________4_
- */
-
- /* if there's only one memory region, don't bother */
- if (*pnr_map < 2)
- return -1;
-
- old_nr = *pnr_map;
-
- /* bail out if we find any unreasonable addresses in bios map */
- for (i=0; i<old_nr; i++)
- if (biosmap[i].addr + biosmap[i].size < biosmap[i].addr)
- return -1;
-
- /* create pointers for initial change-point information (for sorting) */
- for (i=0; i < 2*old_nr; i++)
- change_point[i] = &change_point_list[i];
-
- /* record all known change-points (starting and ending addresses),
- omitting those that are for empty memory regions */
- chgidx = 0;
- for (i=0; i < old_nr; i++) {
- if (biosmap[i].size != 0) {
- change_point[chgidx]->addr = biosmap[i].addr;
- change_point[chgidx++]->pbios = &biosmap[i];
- change_point[chgidx]->addr = biosmap[i].addr + biosmap[i].size;
- change_point[chgidx++]->pbios = &biosmap[i];
- }
- }
- chg_nr = chgidx; /* true number of change-points */
-
- /* sort change-point list by memory addresses (low -> high) */
- still_changing = 1;
- while (still_changing) {
- still_changing = 0;
- for (i=1; i < chg_nr; i++) {
- /* if <current_addr> > <last_addr>, swap */
- /* or, if current=<start_addr> & last=<end_addr>, swap */
- if ((change_point[i]->addr < change_point[i-1]->addr) ||
- ((change_point[i]->addr == change_point[i-1]->addr) &&
- (change_point[i]->addr == change_point[i]->pbios->addr) &&
- (change_point[i-1]->addr != change_point[i-1]->pbios->addr))
- )
- {
- change_tmp = change_point[i];
- change_point[i] = change_point[i-1];
- change_point[i-1] = change_tmp;
- still_changing=1;
- }
- }
- }
-
- /* create a new bios memory map, removing overlaps */
- overlap_entries=0; /* number of entries in the overlap table */
- new_bios_entry=0; /* index for creating new bios map entries */
- last_type = 0; /* start with undefined memory type */
- last_addr = 0; /* start with 0 as last starting address */
- /* loop through change-points, determining affect on the new bios map */
- for (chgidx=0; chgidx < chg_nr; chgidx++)
- {
- /* keep track of all overlapping bios entries */
- if (change_point[chgidx]->addr == change_point[chgidx]->pbios->addr)
- {
- /* add map entry to overlap list (> 1 entry implies an overlap) */
- overlap_list[overlap_entries++]=change_point[chgidx]->pbios;
- }
- else
- {
- /* remove entry from list (order independent, so swap with last) */
- for (i=0; i<overlap_entries; i++)
- {
- if (overlap_list[i] == change_point[chgidx]->pbios)
- overlap_list[i] = overlap_list[overlap_entries-1];
- }
- overlap_entries--;
- }
- /* if there are overlapping entries, decide which "type" to use */
- /* (larger value takes precedence -- 1=usable, 2,3,4,4+=unusable) */
- current_type = 0;
- for (i=0; i<overlap_entries; i++)
- if (overlap_list[i]->type > current_type)
- current_type = overlap_list[i]->type;
- /* continue building up new bios map based on this information */
- if (current_type != last_type) {
- if (last_type != 0) {
- new_bios[new_bios_entry].size =
- change_point[chgidx]->addr - last_addr;
- /* move forward only if the new size was non-zero */
- if (new_bios[new_bios_entry].size != 0)
- if (++new_bios_entry >= E820MAX)
- break; /* no more space left for new bios entries */
- }
- if (current_type != 0) {
- new_bios[new_bios_entry].addr = change_point[chgidx]->addr;
- new_bios[new_bios_entry].type = current_type;
- last_addr=change_point[chgidx]->addr;
- }
- last_type = current_type;
- }
- }
- new_nr = new_bios_entry; /* retain count for new bios entries */
-
- /* copy new bios mapping into original location */
- memcpy(biosmap, new_bios, new_nr*sizeof(struct e820entry));
- *pnr_map = new_nr;
-
- return 0;
-}
-
-/*
- * Copy the BIOS e820 map into a safe place.
- *
- * Sanity-check it while we're at it..
- *
- * If we're lucky and live on a modern system, the setup code
- * will have given us a memory map that we can use to properly
- * set up memory. If we aren't, we'll fake a memory map.
- *
- * We check to see that the memory map contains at least 2 elements
- * before we'll use it, because the detection code in setup.S may
- * not be perfect and most every PC known to man has two memory
- * regions: one from 0 to 640k, and one from 1mb up. (The IBM
- * thinkpad 560x, for example, does not cooperate with the memory
- * detection code.)
- */
-static int __init copy_e820_map(struct e820entry * biosmap, int nr_map)
-{
- /* Only one memory region (or negative)? Ignore it */
- if (nr_map < 2)
- return -1;
-
- do {
- unsigned long long start = biosmap->addr;
- unsigned long long size = biosmap->size;
- unsigned long long end = start + size;
- unsigned long type = biosmap->type;
-
- /* Overflow in 64 bits? Ignore the memory map. */
- if (start > end)
- return -1;
-
- /*
- * Some BIOSes claim RAM in the 640k - 1M region.
- * Not right. Fix it up.
- */
- if (type == E820_RAM) {
- if (start < 0x100000ULL && end > 0xA0000ULL) {
- if (start < 0xA0000ULL)
- add_memory_region(start, 0xA0000ULL-start, type);
- if (end <= 0x100000ULL)
- continue;
- start = 0x100000ULL;
- size = end - start;
- }
- }
- add_memory_region(start, size, type);
- } while (biosmap++,--nr_map);
- return 0;
-}
-
#if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)
struct edd edd;
#ifdef CONFIG_EDD_MODULE
@@ -656,238 +158,105 @@
}
#endif
+int __initdata user_defined_memmap = 0;
+
/*
- * Do NOT EVER look at the BIOS memory size location.
- * It does not work on many machines.
+ * "mem=nopentium" disables the 4MB page tables.
+ * "mem=XXX[kKmM]" defines a memory region from HIGH_MEM
+ * to <mem>, overriding the bios size.
+ * "memmap=XXX[KkmM]@XXX[KkmM]" defines a memory region from
+ * <start> to <start>+<mem>, overriding the bios size.
+ *
+ * HPA tells me bootloaders need to parse mem=, so no new
+ * option should be mem= [also see Documentation/i386/boot.txt]
*/
-#define LOWMEMSIZE() (0x9f000)
-
-static void __init parse_cmdline_early (char ** cmdline_p)
+static int __init parse_mem(char *arg)
{
- char c = ' ', *to = command_line, *from = saved_command_line;
- int len = 0;
- int userdef = 0;
+ if (!arg)
+ return -EINVAL;
- /* Save unparsed command line copy for /proc/cmdline */
- saved_command_line[COMMAND_LINE_SIZE-1] = '\0';
-
- for (;;) {
- if (c != ' ')
- goto next_char;
- /*
- * "mem=nopentium" disables the 4MB page tables.
- * "mem=XXX[kKmM]" defines a memory region from HIGH_MEM
- * to <mem>, overriding the bios size.
- * "memmap=XXX[KkmM]@XXX[KkmM]" defines a memory region from
- * <start> to <start>+<mem>, overriding the bios size.
- *
- * HPA tells me bootloaders need to parse mem=, so no new
- * option should be mem= [also see Documentation/i386/boot.txt]
+ if (strcmp(arg, "nopentium") == 0) {
+ clear_bit(X86_FEATURE_PSE, boot_cpu_data.x86_capability);
+ disable_pse = 1;
+ } else {
+ /* If the user specifies memory size, we
+ * limit the BIOS-provided memory map to
+ * that size. exactmap can be used to specify
+ * the exact map. mem=number can be used to
+ * trim the existing memory map.
*/
- if (!memcmp(from, "mem=", 4)) {
- if (to != command_line)
- to--;
- if (!memcmp(from+4, "nopentium", 9)) {
- from += 9+4;
- clear_bit(X86_FEATURE_PSE, boot_cpu_data.x86_capability);
- disable_pse = 1;
- } else {
- /* If the user specifies memory size, we
- * limit the BIOS-provided memory map to
- * that size. exactmap can be used to specify
- * the exact map. mem=number can be used to
- * trim the existing memory map.
- */
- unsigned long long mem_size;
+ unsigned long long mem_size;
- mem_size = memparse(from+4, &from);
- limit_regions(mem_size);
- userdef=1;
- }
- }
+ mem_size = memparse(arg, &arg);
+ limit_regions(mem_size);
+ user_defined_memmap = 1;
+ }
+ return 0;
+}
+early_param("mem", parse_mem);
- else if (!memcmp(from, "memmap=", 7)) {
- if (to != command_line)
- to--;
- if (!memcmp(from+7, "exactmap", 8)) {
- from += 8+7;
- e820.nr_map = 0;
- userdef = 1;
- } else {
- /* If the user specifies memory size, we
- * limit the BIOS-provided memory map to
- * that size. exactmap can be used to specify
- * the exact map. mem=number can be used to
- * trim the existing memory map.
- */
- unsigned long long start_at, mem_size;
-
- mem_size = memparse(from+7, &from);
- if (*from == '@') {
- start_at = memparse(from+1, &from);
- add_memory_region(start_at, mem_size, E820_RAM);
- } else if (*from == '#') {
- start_at = memparse(from+1, &from);
- add_memory_region(start_at, mem_size, E820_ACPI);
- } else if (*from == '$') {
- start_at = memparse(from+1, &from);
- add_memory_region(start_at, mem_size, E820_RESERVED);
- } else {
- limit_regions(mem_size);
- userdef=1;
- }
- }
- }
+#ifdef CONFIG_PROC_VMCORE
+/* elfcorehdr= specifies the location of elf core header
+ * stored by the crashed kernel.
+ */
+static int __init parse_elfcorehdr(char *arg)
+{
+ if (!arg)
+ return -EINVAL;
- else if (!memcmp(from, "noexec=", 7))
- noexec_setup(from + 7);
+ elfcorehdr_addr = memparse(arg, &arg);
+ return 0;
+}
+early_param("elfcorehdr", parse_elfcorehdr);
+#endif /* CONFIG_PROC_VMCORE */
+/*
+ * highmem=size forces highmem to be exactly 'size' bytes.
+ * This works even on boxes that have no highmem otherwise.
+ * This also works to reduce highmem size on bigger boxes.
+ */
+static int __init parse_highmem(char *arg)
+{
+ if (!arg)
+ return -EINVAL;
-#ifdef CONFIG_X86_SMP
- /*
- * If the BIOS enumerates physical processors before logical,
- * maxcpus=N at enumeration-time can be used to disable HT.
- */
- else if (!memcmp(from, "maxcpus=", 8)) {
- extern unsigned int maxcpus;
-
- maxcpus = simple_strtoul(from + 8, NULL, 0);
- }
-#endif
-
-#ifdef CONFIG_ACPI_BOOT
- /* "acpi=off" disables both ACPI table parsing and interpreter */
- else if (!memcmp(from, "acpi=off", 8)) {
- disable_acpi();
- }
-
- /* acpi=force to over-ride black-list */
- else if (!memcmp(from, "acpi=force", 10)) {
- acpi_force = 1;
- acpi_ht = 1;
- acpi_disabled = 0;
- }
-
- /* acpi=strict disables out-of-spec workarounds */
- else if (!memcmp(from, "acpi=strict", 11)) {
- acpi_strict = 1;
- }
-
- /* Limit ACPI just to boot-time to enable HT */
- else if (!memcmp(from, "acpi=ht", 7)) {
- if (!acpi_force)
- disable_acpi();
- acpi_ht = 1;
- }
-
- /* "pci=noacpi" disable ACPI IRQ routing and PCI scan */
- else if (!memcmp(from, "pci=noacpi", 10)) {
- acpi_disable_pci();
- }
- /* "acpi=noirq" disables ACPI interrupt routing */
- else if (!memcmp(from, "acpi=noirq", 10)) {
- acpi_noirq_set();
- }
-
- else if (!memcmp(from, "acpi_sci=edge", 13))
- acpi_sci_flags.trigger = 1;
-
- else if (!memcmp(from, "acpi_sci=level", 14))
- acpi_sci_flags.trigger = 3;
-
- else if (!memcmp(from, "acpi_sci=high", 13))
- acpi_sci_flags.polarity = 1;
-
- else if (!memcmp(from, "acpi_sci=low", 12))
- acpi_sci_flags.polarity = 3;
-
-#ifdef CONFIG_X86_IO_APIC
- else if (!memcmp(from, "acpi_skip_timer_override", 24))
- acpi_skip_timer_override = 1;
-#endif
-
-#ifdef CONFIG_X86_LOCAL_APIC
- /* disable IO-APIC */
- else if (!memcmp(from, "noapic", 6))
- disable_ioapic_setup();
-#endif /* CONFIG_X86_LOCAL_APIC */
-#endif /* CONFIG_ACPI_BOOT */
-
- /*
- * highmem=size forces highmem to be exactly 'size' bytes.
- * This works even on boxes that have no highmem otherwise.
- * This also works to reduce highmem size on bigger boxes.
- */
- else if (!memcmp(from, "highmem=", 8))
- highmem_pages = memparse(from+8, &from) >> PAGE_SHIFT;
-
- /*
- * vmalloc=size forces the vmalloc area to be exactly 'size'
- * bytes. This can be used to increase (or decrease) the
- * vmalloc area - the default is 128m.
- */
- else if (!memcmp(from, "vmalloc=", 8))
- __VMALLOC_RESERVE = memparse(from+8, &from);
-
- next_char:
- c = *(from++);
- if (!c)
- break;
- if (COMMAND_LINE_SIZE <= ++len)
- break;
- *(to++) = c;
- }
- *to = '\0';
- *cmdline_p = command_line;
- if (userdef) {
- printk(KERN_INFO "user-defined physical RAM map:\n");
- print_memory_map("user");
- }
+ highmem_pages = memparse(arg, &arg) >> PAGE_SHIFT;
+ return 0;
}
+early_param("highmem", parse_highmem);
/*
- * Callback for efi_memory_walk.
+ * vmalloc=size forces the vmalloc area to be exactly 'size'
+ * bytes. This can be used to increase (or decrease) the
+ * vmalloc area - the default is 128m.
*/
-static int __init
-efi_find_max_pfn(unsigned long start, unsigned long end, void *arg)
+static int __init parse_vmalloc(char *arg)
{
- unsigned long *max_pfn = arg, pfn;
+ if (!arg)
+ return -EINVAL;
- if (start < end) {
- pfn = PFN_UP(end -1);
- if (pfn > *max_pfn)
- *max_pfn = pfn;
- }
+ __VMALLOC_RESERVE = memparse(arg, &arg);
return 0;
}
+early_param("vmalloc", parse_vmalloc);
-
/*
- * Find the highest page frame number we have available
+ * reservetop=size reserves a hole at the top of the kernel address space which
+ * a hypervisor can load into later. Needed for dynamically loaded hypervisors,
+ * so relocating the fixmap can be done before paging initialization.
*/
-void __init find_max_pfn(void)
+static int __init parse_reservetop(char *arg)
{
- int i;
+ unsigned long address;
- max_pfn = 0;
- if (efi_enabled) {
- efi_memmap_walk(efi_find_max_pfn, &max_pfn);
- return;
- }
+ if (!arg)
+ return -EINVAL;
- for (i = 0; i < e820.nr_map; i++) {
- unsigned long start, end;
- /* RAM? */
- if (e820.map[i].type != E820_RAM)
- continue;
- start = PFN_UP(e820.map[i].addr);
- end = PFN_DOWN(e820.map[i].addr + e820.map[i].size);
- if (start >= end)
- continue;
- if (end > max_pfn)
- max_pfn = end;
- }
+ address = memparse(arg, &arg);
+ reserve_top_address(address);
+ return 0;
}
+early_param("reservetop", parse_reservetop);
/*
* Determine low and high memory ranges:
@@ -949,68 +318,6 @@
}
/*
- * Free all available memory for boot time allocation. Used
- * as a callback function by efi_memory_walk()
- */
-
-static int __init
-free_available_memory(unsigned long start, unsigned long end, void *arg)
-{
- /* check max_low_pfn */
- if (start >= ((max_low_pfn + 1) << PAGE_SHIFT))
- return 0;
- if (end >= ((max_low_pfn + 1) << PAGE_SHIFT))
- end = (max_low_pfn + 1) << PAGE_SHIFT;
- if (start < end)
- free_bootmem(start, end - start);
-
- return 0;
-}
-/*
- * Register fully available low RAM pages with the bootmem allocator.
- */
-static void __init register_bootmem_low_pages(unsigned long max_low_pfn)
-{
- int i;
-
- if (efi_enabled) {
- efi_memmap_walk(free_available_memory, NULL);
- return;
- }
- for (i = 0; i < e820.nr_map; i++) {
- unsigned long curr_pfn, last_pfn, size;
- /*
- * Reserve usable low memory
- */
- if (e820.map[i].type != E820_RAM)
- continue;
- /*
- * We are rounding up the start address of usable memory:
- */
- curr_pfn = PFN_UP(e820.map[i].addr);
- if (curr_pfn >= max_low_pfn)
- continue;
- /*
- * ... and at the end of the usable range downwards:
- */
- last_pfn = PFN_DOWN(e820.map[i].addr + e820.map[i].size);
-
- if (last_pfn > max_low_pfn)
- last_pfn = max_low_pfn;
-
- /*
- * .. finally, did all the rounding and playing
- * around just make the area go away?
- */
- if (last_pfn <= curr_pfn)
- continue;
-
- size = last_pfn - curr_pfn;
- free_bootmem(PFN_PHYS(curr_pfn), PFN_PHYS(size));
- }
-}
-
-/*
* workaround for Dell systems that neglect to reserve EBDA
*/
static void __init reserve_ebda_region(void)
@@ -1021,7 +328,7 @@
reserve_bootmem(addr, PAGE_SIZE);
}
-#ifndef CONFIG_DISCONTIGMEM
+#ifndef CONFIG_NEED_MULTIPLE_NODES
void __init setup_bootmem_allocator(void);
static unsigned long __init setup_memory(void)
{
@@ -1042,7 +349,15 @@
}
printk(KERN_NOTICE "%ldMB HIGHMEM available.\n",
pages_to_mb(highend_pfn - highstart_pfn));
+ num_physpages = highend_pfn;
+ high_memory = (void *) __va(highstart_pfn * PAGE_SIZE - 1) + 1;
+#else
+ num_physpages = max_low_pfn;
+ high_memory = (void *) __va(max_low_pfn * PAGE_SIZE - 1) + 1;
#endif
+#ifdef CONFIG_FLATMEM
+ max_mapnr = num_physpages;
+#endif
printk(KERN_NOTICE "%ldMB LOWMEM available.\n",
pages_to_mb(max_low_pfn));
@@ -1053,27 +368,24 @@
void __init zone_sizes_init(void)
{
- unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0};
- unsigned int max_dma, low;
-
- max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
- low = max_low_pfn;
-
- if (low < max_dma)
- zones_size[ZONE_DMA] = low;
- else {
- zones_size[ZONE_DMA] = max_dma;
- zones_size[ZONE_NORMAL] = low - max_dma;
+ unsigned long max_zone_pfns[MAX_NR_ZONES];
+ memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
+ max_zone_pfns[ZONE_DMA] =
+ virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
+ max_zone_pfns[ZONE_NORMAL] = max_low_pfn;
#ifdef CONFIG_HIGHMEM
- zones_size[ZONE_HIGHMEM] = highend_pfn - low;
+ max_zone_pfns[ZONE_HIGHMEM] = highend_pfn;
+ add_active_range(0, 0, highend_pfn);
+#else
+ add_active_range(0, 0, max_low_pfn);
#endif
- }
- free_area_init(zones_size);
+
+ free_area_init_nodes(max_zone_pfns);
}
#else
-extern unsigned long setup_memory(void);
+extern unsigned long __init setup_memory(void);
extern void zone_sizes_init(void);
-#endif /* !CONFIG_DISCONTIGMEM */
+#endif /* !CONFIG_NEED_MULTIPLE_NODES */
void __init setup_bootmem_allocator(void)
{
@@ -1091,8 +403,8 @@
* the (very unlikely) case of us accidentally initializing the
* bootmem allocator with an invalid RAM area.
*/
- reserve_bootmem(HIGH_MEMORY, (PFN_PHYS(min_low_pfn) +
- bootmap_size + PAGE_SIZE-1) - (HIGH_MEMORY));
+ reserve_bootmem(__pa_symbol(_text), (PFN_PHYS(min_low_pfn) +
+ bootmap_size + PAGE_SIZE-1) - __pa_symbol(_text));
/*
* reserve physical page 0 - it's a special BIOS page on many boxes,
@@ -1130,13 +442,12 @@
*/
find_smp_config();
#endif
-
+ numa_kva_reserve();
#ifdef CONFIG_BLK_DEV_INITRD
if (LOADER_TYPE && INITRD_START) {
if (INITRD_START + INITRD_SIZE <= (max_low_pfn << PAGE_SHIFT)) {
reserve_bootmem(INITRD_START, INITRD_SIZE);
- initrd_start =
- INITRD_START ? INITRD_START + PAGE_OFFSET : 0;
+ initrd_start = INITRD_START + PAGE_OFFSET;
initrd_end = initrd_start+INITRD_SIZE;
}
else {
@@ -1148,6 +459,11 @@
}
}
#endif
+#ifdef CONFIG_KEXEC
+ if (crashk_res.start != crashk_res.end)
+ reserve_bootmem(crashk_res.start,
+ crashk_res.end - crashk_res.start + 1);
+#endif
}
/*
@@ -1168,215 +484,6 @@
}
}
-/*
- * Request address space for all standard RAM and ROM resources
- * and also for regions reported as reserved by the e820.
- */
-static void __init
-legacy_init_iomem_resources(struct resource *code_resource, struct resource *data_resource)
-{
- int i;
-
- probe_roms();
- for (i = 0; i < e820.nr_map; i++) {
- struct resource *res;
- if (e820.map[i].addr + e820.map[i].size > 0x100000000ULL)
- continue;
- res = alloc_bootmem_low(sizeof(struct resource));
- switch (e820.map[i].type) {
- case E820_RAM: res->name = "System RAM"; break;
- case E820_ACPI: res->name = "ACPI Tables"; break;
- case E820_NVS: res->name = "ACPI Non-volatile Storage"; break;
- default: res->name = "reserved";
- }
- res->start = e820.map[i].addr;
- res->end = res->start + e820.map[i].size - 1;
- res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
- request_resource(&iomem_resource, res);
- if (e820.map[i].type == E820_RAM) {
- /*
- * We don't know which RAM region contains kernel data,
- * so we try it repeatedly and let the resource manager
- * test it.
- */
- request_resource(res, code_resource);
- request_resource(res, data_resource);
- }
- }
-}
-
-/*
- * Request address space for all standard resources
- */
-static void __init register_memory(void)
-{
- unsigned long gapstart, gapsize;
- unsigned long long last;
- int i;
-
- if (efi_enabled)
- efi_initialize_iomem_resources(&code_resource, &data_resource);
- else
- legacy_init_iomem_resources(&code_resource, &data_resource);
-
- /* EFI systems may still have VGA */
- request_resource(&iomem_resource, &video_ram_resource);
-
- /* request I/O space for devices used on all i[345]86 PCs */
- for (i = 0; i < STANDARD_IO_RESOURCES; i++)
- request_resource(&ioport_resource, &standard_io_resources[i]);
-
- /*
- * Search for the bigest gap in the low 32 bits of the e820
- * memory space.
- */
- last = 0x100000000ull;
- gapstart = 0x10000000;
- gapsize = 0x400000;
- i = e820.nr_map;
- while (--i >= 0) {
- unsigned long long start = e820.map[i].addr;
- unsigned long long end = start + e820.map[i].size;
-
- /*
- * Since "last" is at most 4GB, we know we'll
- * fit in 32 bits if this condition is true
- */
- if (last > end) {
- unsigned long gap = last - end;
-
- if (gap > gapsize) {
- gapsize = gap;
- gapstart = end;
- }
- }
- if (start < last)
- last = start;
- }
-
- /*
- * Start allocating dynamic PCI memory a bit into the gap,
- * aligned up to the nearest megabyte.
- *
- * Question: should we try to pad it up a bit (do something
- * like " + (gapsize >> 3)" in there too?). We now have the
- * technology.
- */
- pci_mem_start = (gapstart + 0xfffff) & ~0xfffff;
-
- printk("Allocating PCI resources starting at %08lx (gap: %08lx:%08lx)\n",
- pci_mem_start, gapstart, gapsize);
-}
-
-/* Use inline assembly to define this because the nops are defined
- as inline assembly strings in the include files and we cannot
- get them easily into strings. */
-asm("\t.data\nintelnops: "
- GENERIC_NOP1 GENERIC_NOP2 GENERIC_NOP3 GENERIC_NOP4 GENERIC_NOP5 GENERIC_NOP6
- GENERIC_NOP7 GENERIC_NOP8);
-asm("\t.data\nk8nops: "
- K8_NOP1 K8_NOP2 K8_NOP3 K8_NOP4 K8_NOP5 K8_NOP6
- K8_NOP7 K8_NOP8);
-asm("\t.data\nk7nops: "
- K7_NOP1 K7_NOP2 K7_NOP3 K7_NOP4 K7_NOP5 K7_NOP6
- K7_NOP7 K7_NOP8);
-
-extern unsigned char intelnops[], k8nops[], k7nops[];
-static unsigned char *intel_nops[ASM_NOP_MAX+1] = {
- NULL,
- intelnops,
- intelnops + 1,
- intelnops + 1 + 2,
- intelnops + 1 + 2 + 3,
- intelnops + 1 + 2 + 3 + 4,
- intelnops + 1 + 2 + 3 + 4 + 5,
- intelnops + 1 + 2 + 3 + 4 + 5 + 6,
- intelnops + 1 + 2 + 3 + 4 + 5 + 6 + 7,
-};
-static unsigned char *k8_nops[ASM_NOP_MAX+1] = {
- NULL,
- k8nops,
- k8nops + 1,
- k8nops + 1 + 2,
- k8nops + 1 + 2 + 3,
- k8nops + 1 + 2 + 3 + 4,
- k8nops + 1 + 2 + 3 + 4 + 5,
- k8nops + 1 + 2 + 3 + 4 + 5 + 6,
- k8nops + 1 + 2 + 3 + 4 + 5 + 6 + 7,
-};
-static unsigned char *k7_nops[ASM_NOP_MAX+1] = {
- NULL,
- k7nops,
- k7nops + 1,
- k7nops + 1 + 2,
- k7nops + 1 + 2 + 3,
- k7nops + 1 + 2 + 3 + 4,
- k7nops + 1 + 2 + 3 + 4 + 5,
- k7nops + 1 + 2 + 3 + 4 + 5 + 6,
- k7nops + 1 + 2 + 3 + 4 + 5 + 6 + 7,
-};
-static struct nop {
- int cpuid;
- unsigned char **noptable;
-} noptypes[] = {
- { X86_FEATURE_K8, k8_nops },
- { X86_FEATURE_K7, k7_nops },
- { -1, NULL }
-};
-
-/* Replace instructions with better alternatives for this CPU type.
-
- This runs before SMP is initialized to avoid SMP problems with
- self modifying code. This implies that assymetric systems where
- APs have less capabilities than the boot processor are not handled.
- In this case boot with "noreplacement". */
-void apply_alternatives(void *start, void *end)
-{
- struct alt_instr *a;
- int diff, i, k;
- unsigned char **noptable = intel_nops;
- for (i = 0; noptypes[i].cpuid >= 0; i++) {
- if (boot_cpu_has(noptypes[i].cpuid)) {
- noptable = noptypes[i].noptable;
- break;
- }
- }
- for (a = start; (void *)a < end; a++) {
- if (!boot_cpu_has(a->cpuid))
- continue;
- BUG_ON(a->replacementlen > a->instrlen);
- memcpy(a->instr, a->replacement, a->replacementlen);
- diff = a->instrlen - a->replacementlen;
- /* Pad the rest with nops */
- for (i = a->replacementlen; diff > 0; diff -= k, i += k) {
- k = diff;
- if (k > ASM_NOP_MAX)
- k = ASM_NOP_MAX;
- memcpy(a->instr + i, noptable[k], k);
- }
- }
-}
-
-static int no_replacement __initdata = 0;
-
-void __init alternative_instructions(void)
-{
- extern struct alt_instr __alt_instructions[], __alt_instructions_end[];
- if (no_replacement)
- return;
- apply_alternatives(__alt_instructions, __alt_instructions_end);
-}
-
-static int __init noreplacement_setup(char *s)
-{
- no_replacement = 1;
- return 0;
-}
-
-__setup("noreplacement", noreplacement_setup);
-
-static char * __init machine_specific_memory_setup(void);
-
#ifdef CONFIG_MCA
static void set_mca_bus(int x)
{
@@ -1386,6 +493,12 @@
static void set_mca_bus(int x) { }
#endif
+/* Overridden in paravirt.c if CONFIG_PARAVIRT */
+char * __init __attribute__((weak)) memory_setup(void)
+{
+ return machine_specific_memory_setup();
+}
+
/*
* Determine if we were loaded by an EFI loader. If so, then we have also been
* passed the efi memmap, systab, etc., so we should use these data structures
@@ -1438,7 +551,7 @@
efi_init();
else {
printk(KERN_INFO "BIOS-provided physical RAM map:\n");
- print_memory_map(machine_specific_memory_setup());
+ print_memory_map(memory_setup());
}
copy_edd();
@@ -1455,11 +568,27 @@
data_resource.start = virt_to_phys(_etext);
data_resource.end = virt_to_phys(_edata)-1;
- parse_cmdline_early(cmdline_p);
+ parse_early_param();
+ if (user_defined_memmap) {
+ printk(KERN_INFO "user-defined physical RAM map:\n");
+ print_memory_map("user");
+ }
+
+ strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE);
+ *cmdline_p = command_line;
+
max_low_pfn = setup_memory();
+#ifdef CONFIG_VMI
/*
+ * Must be after max_low_pfn is determined, and before kernel
+ * pagetables are setup.
+ */
+ vmi_init();
+#endif
+
+ /*
* NOTE: before this point _nobody_ is allowed to allocate
* any memory using the bootmem allocator. Although the
* alloctor is now initialised only the first 8Mb of the kernel
@@ -1474,54 +603,48 @@
#endif
paging_init();
remapped_pgdat_init();
+ sparse_init();
zone_sizes_init();
/*
* NOTE: at this point the bootmem allocator is fully available.
*/
-#ifdef CONFIG_EARLY_PRINTK
- {
- char *s = strstr(*cmdline_p, "earlyprintk=");
- if (s) {
- extern void setup_early_printk(char *);
-
- setup_early_printk(s);
- printk("early console enabled\n");
- }
- }
-#endif
-
-
dmi_scan_machine();
#ifdef CONFIG_X86_GENERICARCH
- generic_apic_probe(*cmdline_p);
+ generic_apic_probe();
#endif
if (efi_enabled)
efi_map_memmap();
-#ifdef CONFIG_ACPI_BOOT
+#ifdef CONFIG_ACPI
/*
* Parse the ACPI tables for possible boot-time SMP configuration.
*/
acpi_boot_table_init();
- acpi_boot_init();
#endif
+#ifdef CONFIG_PCI
+#ifdef CONFIG_X86_IO_APIC
+ check_acpi_pci(); /* Checks more than just ACPI actually */
+#endif
+#endif
+
+#ifdef CONFIG_ACPI
+ acpi_boot_init();
+
+#if defined(CONFIG_SMP) && defined(CONFIG_X86_PC)
+ if (def_to_bigsmp)
+ printk(KERN_WARNING "More than 8 CPUs detected and "
+ "CONFIG_X86_PC cannot handle it.\nUse "
+ "CONFIG_X86_GENERICARCH or CONFIG_X86_BIGSMP.\n");
+#endif
+#endif
#ifdef CONFIG_X86_LOCAL_APIC
if (smp_found_config)
get_smp_config();
#endif
- register_memory();
+ e820_register_memory();
}
-
-#include "setup_arch_post.h"
-/*
- * Local Variables:
- * mode:c
- * c-file-style:"k&r"
- * c-basic-offset:8
- * End:
- */
Modified: branches/ruby-2.6.21/ruby-2.6/arch/x86_64/kernel/setup.c
===================================================================
--- branches/ruby-2.6.21/ruby-2.6/arch/x86_64/kernel/setup.c 2007-04-10 01:57:48 UTC (rev 2361)
+++ branches/ruby-2.6.21/ruby-2.6/arch/x86_64/kernel/setup.c 2007-04-10 02:01:16 UTC (rev 2362)
@@ -5,8 +5,6 @@
*
* Nov 2001 Dave Jones <da...@su...>
* Forked from i386 setup code.
- *
- * $Id$
*/
/*
@@ -23,10 +21,9 @@
#include <linux/slab.h>
#include <linux/user.h>
#include <linux/a.out.h>
-#include <linux/tty.h>
+#include <linux/screen_info.h>
#include <linux/ioport.h>
#include <linux/delay.h>
-#include <linux/config.h>
#include <linux/init.h>
#include <linux/initrd.h>
#include <linux/highmem.h>
@@ -34,11 +31,19 @@
#include <linux/module.h>
#include <asm/processor.h>
#include <linux/seq_file.h>
+#include <linux/crash_dump.h>
#include <linux/root_dev.h>
#include <linux/pci.h>
#include <linux/acpi.h>
#include <linux/kallsyms.h>
#include <linux/edd.h>
+#include <linux/mmzone.h>
+#include <linux/kexec.h>
+#include <linux/cpufreq.h>
+#include <linux/dmi.h>
+#include <linux/dma-mapping.h>
+#include <linux/ctype.h>
+
#include <asm/mtrr.h>
#include <asm/uaccess.h>
#include <asm/system.h>
@@ -56,52 +61,45 @@
#include <asm/setup.h>
#include <asm/mach_apic.h>
#include <asm/numa.h>
+#include <asm/sections.h>
+#include <asm/dmi.h>
/*
* Machine setup..
*/
-struct cpuinfo_x86 boot_cpu_data;
+struct cpuinfo_x86 boot_cpu_data __read_mostly;
+EXPORT_SYMBOL(boot_cpu_data);
unsigned long mmu_cr4_features;
-int acpi_disabled;
-EXPORT_SYMBOL(acpi_disabled);
-#ifdef CONFIG_ACPI_BOOT
-extern int __initdata acpi_ht;
-extern acpi_interrupt_flags acpi_sci_flags;
-int __initdata acpi_force = 0;
-#endif
-
-int acpi_numa __initdata;
-
/* Boot loader ID as an integer, for the benefit of proc_dointvec */
int bootloader_type;
unsigned long saved_video_mode;
-#ifdef CONFIG_SWIOTLB
-int swiotlb;
-EXPORT_SYMBOL(swiotlb);
-#endif
+/*
+ * Early DMI memory
+ */
+int dmi_alloc_index;
+char dmi_alloc_data[DMI_MAX_DATA];
/*
* Setup options
*/
-struct drive_info_struct { char dummy[32]; } drive_info;
struct screen_info screen_info;
+EXPORT_SYMBOL(screen_info);
struct sys_desc_table_struct {
unsigned short length;
unsigned char table[0];
};
struct edid_info edid_info;
-struct e820map e820;
+EXPORT_SYMBOL_GPL(edid_info);
extern int root_mountflags;
-extern char _text, _etext, _edata, _end;
-char command_line[COMMAND_LINE_SIZE];
+char __initdata command_line[COMMAND_LINE_SIZE];
struct resource standard_io_resources[] = {
{ .name = "dma1", .start = 0x00, .end = 0x1f,
@@ -124,9 +122,6 @@
.flags = IORESOURCE_BUSY | IORESOURCE_IO }
};
-#define STANDARD_IO_RESOURCES \
- (sizeof standard_io_resources / sizeof standard_io_resources[0])
-
#define IORESOURCE_RAM (IORESOURCE_BUSY | IORESOURCE_MEM)
struct resource data_resource = {
@@ -142,320 +137,39 @@
.flags = IORESOURCE_RAM,
};
-#define IORESOURCE_ROM (IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM)
-
-static struct resource system_rom_resource = {
- .name = "System ROM",
- .start = 0xf0000,
- .end = 0xfffff,
- .flags = IORESOURCE_ROM,
-};
-
-static struct resource extension_rom_resource = {
- .name = "Extension ROM",
- .start = 0xe0000,
- .end = 0xeffff,
- .flags = IORESOURCE_ROM,
-};
-
-static struct resource adapter_rom_resources[] = {
- { .name = "Adapter ROM", .start = 0xc8000, .end = 0,
- .flags = IORESOURCE_ROM },
- { .name = "Adapter ROM", .start = 0, .end = 0,
- .flags = IORESOURCE_ROM },
- { .name = "Adapter ROM", .start = 0, .end = 0,
- .flags = IORESOURCE_ROM },
- { .name = "Adapter ROM", .start = 0, .end = 0,
- .flags = IORESOURCE_ROM },
- { .name = "Adapter ROM", .start = 0, .end = 0,
- .flags = IORESOURCE_ROM },
- { .name = "Adapter ROM", .start = 0, .end = 0,
- .flags = IORESOURCE_ROM }
-};
-
-#define ADAPTER_ROM_RESOURCES \
- (sizeof adapter_rom_resources / sizeof adapter_rom_resources[0])
-
-static struct resource video_rom_resource = {
- .name = "Video ROM",
- .start = 0xc0000,
- .end = 0xc7fff,
- .flags = IORESOURCE_ROM,
-};
-
-static struct resource video_ram_resource = {
- .name = "Video RAM area",
- .start = 0xa0000,
- .end = 0xbffff,
- .flags = IORESOURCE_RAM,
-};
-
-#define romsignature(x) (*(unsigned short *)(x) == 0xaa55)
-
-static int __init romchecksum(unsigned char *rom, unsigned long length)
+#ifdef CONFIG_PROC_VMCORE
+/* elfcorehdr= specifies the location of elf core header
+ * stored by the crashed kernel. This option will be passed
+ * by kexec loader to the capture kernel.
+ */
+static int __init setup_elfcorehdr(char *arg)
{
- unsigned char *p, sum = 0;
-
- for (p = rom; p < rom + length; p++)
- sum += *p;
- return sum == 0;
+ char *end;
+ if (!arg)
+ return -EINVAL;
+ elfcorehdr_addr = memparse(arg, &end);
+ return end > arg ? 0 : -EINVAL;
}
-
-static void __init probe_roms(void)
-{
- unsigned long start, length, upper;
- unsigned char *rom;
- int i;
-
- /* video rom */
- upper = adapter_rom_resources[0].start;
- for (start = video_rom_resource.start; start < upper; start += 2048) {
- rom = isa_bus_to_virt(start);
- if (!romsignature(rom))
- continue;
-
- video_rom_resource.start = start;
-
- /* 0 < length <= 0x7f * 512, historically */
- length = rom[2] * 512;
-
- /* if checksum okay, trust length byte */
- if (length && romchecksum(rom, length))
- video_rom_resource.end = start + length - 1;
-
- request_resource(&iomem_resource, &video_rom_resource);
- break;
- }
-
- start = (video_rom_resource.end + 1 + 2047) & ~2047UL;
- if (start < upper)
- start = upper;
-
- /* system rom */
- request_resource(&iomem_resource, &system_rom_resource);
- upper = system_rom_resource.start;
-
- /* check for extension rom (ignore length byte!) */
- rom = isa_bus_to_virt(extension_rom_resource.start);
- if (romsignature(rom)) {
- length = extension_rom_resource.end - extension_rom_resource.start + 1;
- if (romchecksum(rom, length)) {
- request_resource(&iomem_resource, &extension_rom_resource);
- upper = extension_rom_resource.start;
- }
- }
-
- /* check for adapter roms on 2k boundaries */
- for (i = 0; i < ADAPTER_ROM_RESOURCES && start < upper; start += 2048) {
- rom = isa_bus_to_virt(start);
- if (!romsignature(rom))
- continue;
-
- /* 0 < length <= 0x7f * 512, historically */
- length = rom[2] * 512;
-
- /* but accept any length that fits if checksum okay */
- if (!length || start + length > upper || !romchecksum(rom, length))
- continue;
-
- adapter_rom_resources[i].start = start;
- adapter_rom_resources[i].end = start + length - 1;
- request_resource(&iomem_resource, &adapter_rom_resources[i]);
-
- start = adapter_rom_resources[i++].end & ~2047UL;
- }
-}
-
-static __init void parse_cmdline_early (char ** cmdline_p)
-{
- char c = ' ', *to = command_line, *from = COMMAND_LINE;
- int len = 0;
-
- /* Save unparsed command line copy for /proc/cmdline */
- memcpy(saved_command_line, COMMAND_LINE, COMMAND_LINE_SIZE);
- saved_command_line[COMMAND_LINE_SIZE-1] = '\0';
-
- for (;;) {
- if (c != ' ')
- goto next_char;
-
-#ifdef CONFIG_SMP
- /*
- * If the BIOS enumerates physical processors before logical,
- * maxcpus=N at enumeration-time can be used to disable HT.
- */
- else if (!memcmp(from, "maxcpus=", 8)) {
- extern unsigned int maxcpus;
-
- maxcpus = simple_strtoul(from + 8, NULL, 0);
- }
+early_param("elfcorehdr", setup_elfcorehdr);
#endif
-#ifdef CONFIG_ACPI_BOOT
- /* "acpi=off" disables both ACPI table parsing and interpreter init */
- if (!memcmp(from, "acpi=off", 8))
- disable_acpi();
- if (!memcmp(from, "acpi=force", 10)) {
- /* add later when we do DMI horrors: */
- acpi_force = 1;
- acpi_disabled = 0;
- }
-
- /* acpi=ht just means: do ACPI MADT parsing
- at bootup, but don't enable the full ACPI interpreter */
- if (!memcmp(from, "acpi=ht", 7)) {
- if (!acpi_force)
- disable_acpi();
- acpi_ht = 1;
- }
- else if (!memcmp(from, "pci=noacpi", 10))
- acpi_disable_pci();
- else if (!memcmp(from, "acpi=noirq", 10))
- acpi_noirq_set();
-
- else if (!memcmp(from, "acpi_sci=edge", 13))
- acpi_sci_flags.trigger = 1;
- else if (!memcmp(from, "acpi_sci=level", 14))
- acpi_sci_flags.trigger = 3;
- else if (!memcmp(from, "acpi_sci=high", 13))
- acpi_sci_flags.polarity = 1;
- else if (!memcmp(from, "acpi_sci=low", 12))
- acpi_sci_flags.polarity = 3;
-
- /* acpi=strict disables out-of-spec workarounds */
- else if (!memcmp(from, "acpi=strict", 11)) {
- acpi_strict = 1;
- }
-#ifdef CONFIG_X86_IO_APIC
- else if (!memcmp(from, "acpi_skip_timer_override", 24))
- acpi_skip_timer_override = 1;
-#endif
-#endif
-
- if (!memcmp(from, "nolapic", 7) ||
- !memcmp(from, "disableapic", 11))
- disable_apic = 1;
-
- if (!memcmp(from, "noapic", 6))
- skip_ioapic_setup = 1;
-
- if (!memcmp(from, "apic", 4)) {
- skip_ioapic_setup = 0;
- ioapic_force = 1;
- }
-
- if (!memcmp(from, "mem=", 4))
- parse_memopt(from+4, &from);
-
-#ifdef CONFIG_DISCONTIGMEM
- if (!memcmp(from, "numa=", 5))
- numa_setup(from+5);
-#endif
-
-#ifdef CONFIG_GART_IOMMU
- if (!memcmp(from,"iommu=",6)) {
- iommu_setup(from+6);
- }
-#endif
-
- if (!memcmp(from,"oops=panic", 10))
- panic_on_oops = 1;
-
- if (!memcmp(from, "noexec=", 7))
- nonx_setup(from + 7);
-
- next_char:
- c = *(from++);
- if (!c)
- break;
- if (COMMAND_LINE_SIZE <= ++len)
- break;
- *(to++) = c;
- }
- *to = '\0';
- *cmdline_p = command_line;
-}
-
-#ifndef CONFIG_DISCONTIGMEM
-static void __init contig_initmem_init(void)
+#ifndef CONFIG_NUMA
+static void __init
+contig_initmem_init(unsigned long start_pfn, unsigned long end_pfn)
{
- unsigned long bootmap_size, bootmap;
- bootmap_size = bootmem_bootmap_pages(end_pfn)<<PAGE_SHIFT;
- bootmap = find_e820_area(0, end_pfn<<PAGE_SHIFT, bootmap_size);
- if (bootmap == -1L)
- panic("Cannot find bootmem map of size %ld\n",bootmap_size);
- bootmap_size = init_bootmem(bootmap >> PAGE_SHIFT, end_pfn);
- e820_bootmem_free(&contig_page_data, 0, end_pfn << PAGE_SHIFT);
- reserve_bootmem(bootmap, bootmap_size);
+ unsigned long bootmap_size, bootmap;
+
+ bootmap_size = bootmem_bootmap_pages(end_pfn)<<PAGE_SHIFT;
+ bootmap = find_e820_area(0, end_pfn<<PAGE_SHIFT, bootmap_size);
+ if (bootmap == -1L)
+ panic("Cannot find bootmem map of size %ld\n",bootmap_size);
+ bootmap_size = init_bootmem(bootmap >> PAGE_SHIFT, end_pfn);
+ e820_register_active_regions(0, start_pfn, end_pfn);
+ free_bootmem_with_active_regions(0, end_pfn);
+ reserve_bootmem(bootmap, bootmap_size);
}
#endif
-/* Use inline assembly to define this because the nops are defined
- as inline assembly strings in the include files and we cannot
- get them easily into strings. */
-asm("\t.data\nk8nops: "
- K8_NOP1 K8_NOP2 K8_NOP3 K8_NOP4 K8_NOP5 K8_NOP6
- K8_NOP7 K8_NOP8);
-
-extern unsigned char k8nops[];
-static unsigned char *k8_nops[ASM_NOP_MAX+1] = {
- NULL,
- k8nops,
- k8nops + 1,
- k8nops + 1 + 2,
- k8nops + 1 + 2 + 3,
- k8nops + 1 + 2 + 3 + 4,
- k8nops + 1 + 2 + 3 + 4 + 5,
- k8nops + 1 + 2 + 3 + 4 + 5 + 6,
- k8nops + 1 + 2 + 3 + 4 + 5 + 6 + 7,
-};
-
-/* Replace instructions with better alternatives for this CPU type.
-
- This runs before SMP is initialized to avoid SMP problems with
- self modifying code. This implies that assymetric systems where
- APs have less capabilities than the boot processor are not handled.
- In this case boot with "noreplacement". */
-void apply_alternatives(void *start, void *end)
-{
- struct alt_instr *a;
- int diff, i, k;
- for (a = start; (void *)a < end; a++) {
- if (!boot_cpu_has(a->cpuid))
- continue;
-
- BUG_ON(a->replacementlen > a->instrlen);
- __inline_memcpy(a->instr, a->replacement, a->replacementlen);
- diff = a->instrlen - a->replacementlen;
-
- /* Pad the rest with nops */
- for (i = a->replacementlen; diff > 0; diff -= k, i += k) {
- k = diff;
- if (k > ASM_NOP_MAX)
- k = ASM_NOP_MAX;
- __inline_memcpy(a->instr + i, k8_nops[k], k);
- }
- }
-}
-
-static int no_replacement __initdata = 0;
-
-void __init alternative_instructions(void)
-{
- extern struct alt_instr __alt_instructions[], __alt_instructions_end[];
- if (no_replacement)
- return;
- apply_alternatives(__alt_instructions, __alt_instructions_end);
-}
-
-static int __init noreplacement_setup(char *s)
-{
- no_replacement = 1;
- return 0;
-}
-
-__setup("noreplacement", noreplacement_setup);
-
#if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)
struct edd edd;
#ifdef CONFIG_EDD_MODULE
@@ -480,25 +194,35 @@
#endif
#define EBDA_ADDR_POINTER 0x40E
-static void __init reserve_ebda_region(void)
+
+unsigned __initdata ebda_addr;
+unsigned __initdata ebda_size;
+
+static void discover_ebda(void)
{
- unsigned int addr;
- /**
+ /*
* there is a real-mode segmented pointer pointing to the
* 4K EBDA area at 0x40E
*/
- addr = *(unsigned short *)phys_to_virt(EBDA_ADDR_POINTER);
- addr <<= 4;
- if (addr)
- reserve_bootmem_generic(addr, PAGE_SIZE);
+ ebda_addr = *(unsigned short *)EBDA_ADDR_POINTER;
+ ebda_addr <<= 4;
+
+ ebda_size = *(unsigned short *)(unsigned long)ebda_addr;
+
+ /* Round EBDA up to pages */
+ if (ebda_size == 0)
+ ebda_size = 1;
+ ebda_size <<= 10;
+ ebda_size = round_up(ebda_size + (ebda_addr & ~PAGE_MASK), PAGE_SIZE);
+ if (ebda_size > 64*1024)
+ ebda_size = 64*1024;
}
void __init setup_arch(char **cmdline_p)
{
- unsigned long kernel_end;
+ printk(KERN_INFO "Command line: %s\n", boot_command_line);
ROOT_DEV = old_decode_dev(ORIG_ROOT_DEV);
- drive_info = DRIVE_INFO;
screen_info = SCREEN_INFO;
edid_info = EDID_INFO;
saved_video_mode = SAVED_VIDEO_MODE;
@@ -524,21 +248,34 @@
data_resource.start = virt_to_phys(&_etext);
data_resource.end = virt_to_phys(&_edata)-1;
- parse_cmdline_early(cmdline_p);
-
early_identify_cpu(&boot_cpu_data);
+ strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE);
+ *cmdline_p = command_line;
+
+ parse_early_param();
+
+ finish_e820_parsing();
+
+ e820_register_active_regions(0, 0, -1UL);
/*
* partially used pages are not usable - thus
* we are rounding upwards:
*/
end_pfn = e820_end_of_ram();
+ num_physpages = end_pfn;
check_efer();
+ discover_ebda();
+
init_memory_mapping(0, (end_pfn_map << PAGE_SHIFT));
-#ifdef CONFIG_ACPI_BOOT
+ dmi_scan_machine();
+
+ zap_low_mappings(0);
+
+#ifdef CONFIG_ACPI
/*
* Initialize the ACPI boot-time table parser (gets the RSDP and SDT).
* Call this early for SRAT node setup.
@@ -546,6 +283,14 @@
acpi_boot_table_init();
#endif
+ /* How many end-of-memory variables you have, grandma! */
+ max_low_pfn = end_pfn;
+ max_pfn = end_pfn;
+ high_memory = (void *)__va(end_pfn * PAGE_SIZE - 1) + 1;
+
+ /* Remove active ranges so rediscovery with NUMA-awareness happens */
+ remove_all_active_ranges();
+
#ifdef CONFIG_ACPI_NUMA
/*
* Parse SRAT to discover nodes.
@@ -553,10 +298,10 @@
acpi_numa_init();
#endif
-#ifdef CONFIG_DISCONTIGMEM
+#ifdef CONFIG_NUMA
numa_initmem_init(0, end_pfn);
#else
- contig_initmem_init();
+ contig_initmem_init(0, end_pfn);
#endif
/* Reserve direct mapping */
@@ -564,8 +309,8 @@
(table_end - table_start) << PAGE_SHIFT);
/* reserve kernel */
- kernel_end = round_up(__pa_symbol(&_end),PAGE_SIZE);
- reserve_bootmem_generic(HIGH_MEMORY, kernel_end - HIGH_MEMORY);
+ reserve_bootmem_generic(__pa_symbol(&_text),
+ __pa_symbol(&_end) - __pa_symbol(&_text));
/*
* reserve physical page 0 - it's a special BIOS page on many boxes,
@@ -574,7 +319,13 @@
reserve_bootmem_generic(0, PAGE_SIZE);
/* reserve ebda region */
- reserve_ebda_region();
+ if (ebda_addr)
+ reserve_bootmem_generic(ebda_addr, ebda_size);
+#ifdef CONFIG_NUMA
+ /* reserve nodemap region */
+ if (nodemap_addr)
+ reserve_bootmem_generic(nodemap_addr, nodemap_size);
+#endif
#ifdef CONFIG_SMP
/*
@@ -594,18 +345,15 @@
*/
acpi_reserve_bootmem();
#endif
-#ifdef CONFIG_X86_LOCAL_APIC
/*
* Find and reserve possible boot-time SMP configuration:
*/
find_smp_config();
-#endif
#ifdef CONFIG_BLK_DEV_INITRD
if (LOADER_TYPE && INITRD_START) {
if (INITRD_START + INITRD_SIZE <= (end_pfn << PAGE_SHIFT)) {
reserve_bootmem_generic(INITRD_START, INITRD_SIZE);
- initrd_start =
- INITRD_START ? INITRD_START + PAGE_OFFSET : 0;
+ initrd_start = INITRD_START + PAGE_OFFSET;
initrd_end = initrd_start+INITRD_SIZE;
}
else {
@@ -617,50 +365,58 @@
}
}
#endif
+#ifdef CONFIG_KEXEC
+ if (crashk_res.start != crashk_res.end) {
+ reserve_bootmem_generic(crashk_res.start,
+ crashk_res.end - crashk_res.start + 1);
+ }
+#endif
+
paging_init();
- check_ioapic();
+#ifdef CONFIG_PCI
+ early_quirks();
+#endif
-#ifdef CONFIG_ACPI_BOOT
/*
+ * set this early, so we dont allocate cpu0
+ * if MADT list doesnt list BSP first
+ * mpparse.c/MP_processor_info() allocates logical cpu numbers.
+ */
+ cpu_set(0, cpu_present_map);
+#ifdef CONFIG_ACPI
+ /*
* Read APIC and some other early information from ACPI tables.
*/
acpi_boot_init();
#endif
-#ifdef CONFIG_X86_LOCAL_APIC
+ init_cpu_to_node();
+
/*
* get boot-time SMP configuration:
*/
if (smp_found_config)
get_smp_config();
init_apic_mappings();
-#endif
/*
- * Request address space for all standard RAM and ROM resources
- * and also for regions reported as reserved by the e820.
- */
- probe_roms();
+ * We trust e820 completely. No explicit ROM probing in memory.
+ */
e820_reserve_resources();
+ e820_mark_nosave_regions();
- request_resource(&iomem_resource, &video_ram_resource);
-
{
unsigned i;
/* request I/O space for devices used on all i[345]86 PCs */
- for (i = 0; i < STANDARD_IO_RESOURCES; i++)
+ for (i = 0; i < ARRAY_SIZE(standard_io_resources); i++)
request_resource(&ioport_resource, &standard_io_resources[i]);
}
e820_setup_gap();
-
-#ifdef CONFIG_GART_IOMMU
- iommu_hole_init();
-#endif
}
-static int __init get_model_name(struct cpuinfo_x86 *c)
+static int __cpuinit get_model_name(struct cpuinfo_x86 *c)
{
unsigned int *v;
@@ -676,7 +432,7 @@
}
-static void __init display_cacheinfo(struct cpuinfo_x86 *c)
+static void __cpuinit display_cacheinfo(struct cpuinfo_x86 *c)
{
unsigned int n, dummy, eax, ebx, ecx, edx;
@@ -710,6 +466,24 @@
}
}
+#ifdef CONFIG_NUMA
+static int nearby_node(int apicid)
+{
+ int i;
+ for (i = apicid - 1; i >= 0; i--) {
+ int node = apicid_to_node[i];
+ if (node != NUMA_NO_NODE && node_online(node))
+ return node;
+ }
+ for (i = apicid + 1; i < MAX_LOCAL_APIC; i++) {
+ int node = apicid_to_node[i];
+ if (node != NUMA_NO_NODE && node_online(node))
+ return node;
+ }
+ return first_node(node_online_map); /* Shouldn't happen */
+}
+#endif
+
/*
* On a AMD dual core setup the lower bits of the APIC id distingush the cores.
* Assumes number of cores is a power of two.
@@ -717,55 +491,95 @@
static void __init amd_detect_cmp(struct cpuinfo_x86 *c)
{
#ifdef CONFIG_SMP
+ unsigned bits;
+#ifdef CONFIG_NUMA
int cpu = smp_processor_id();
int node = 0;
- unsigned bits;
- if (c->x86_num_cores == 1)
- return;
+ unsigned apicid = hard_smp_processor_id();
+#endif
+ unsigned ecx = cpuid_ecx(0x80000008);
- bits = 0;
- while ((1 << bits) < c->x86_num_cores)
- bits++;
+ c->x86_max_cores = (ecx & 0xff) + ...
[truncated message content] |
|
From: <jsi...@us...> - 2007-04-10 01:57:49
|
Revision: 2361
http://linuxconsole.svn.sourceforge.net/linuxconsole/?rev=2361&view=rev
Author: jsimmons
Date: 2007-04-09 18:57:48 -0700 (Mon, 09 Apr 2007)
Log Message:
-----------
Don't mess with it yet
Removed Paths:
-------------
branches/ruby-2.6.21/ruby-2.6/kernel/power/
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|