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. |