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: James S. <jsi...@us...> - 2001-10-08 04:36:36
|
Update of /cvsroot/linuxconsole/ruby/linux/drivers/video
In directory usw-pr-cvs1:/tmp/cvs-serv26231
Modified Files:
Config.in
Log Message:
If marked experimental it should be only configurable when experimental code is set.
Index: Config.in
===================================================================
RCS file: /cvsroot/linuxconsole/ruby/linux/drivers/video/Config.in,v
retrieving revision 1.50
retrieving revision 1.51
diff -u -d -r1.50 -r1.51
--- Config.in 2001/10/08 02:23:57 1.50
+++ Config.in 2001/10/08 04:36:34 1.51
@@ -168,7 +168,7 @@
bool ' 3Dfx Banshee/Voodoo3 display support (EXPERIMENTAL)' CONFIG_FB_3DFX
bool ' 3Dfx Voodoo Graphics (sst1) support (EXPERIMENTAL)' CONFIG_FB_VOODOO1
fi
- tristate ' SIS acceleration (EXPERIMENTAL)' CONFIG_FB_SIS
+ tristate ' SIS acceleration (EXPERIMENTAL)' CONFIG_FB_SIS $CONFIG_EXPERIMENTAL
if [ "$CONFIG_FB_SIS" != "n" ]; then
bool ' SIS 630/540/730 support' CONFIG_FB_SIS_300
bool ' SIS 315H/315 support' CONFIG_FB_SIS_315
|
|
From: James S. <jsi...@us...> - 2001-10-08 04:33:48
|
Update of /cvsroot/linuxconsole/ruby/linux/drivers/serial
In directory usw-pr-cvs1:/tmp/cvs-serv25653
Modified Files:
serial_21285.c serial_8250.c serial_8250.h serial_8250_pci.c
serial_8250_pnp.c serial_amba.c serial_clps711x.c
serial_core.c serial_sa1100.c
Log Message:
More syncing to Russel King's serial work. I really need to get to reworking it so the serial layer behaves more like the parallel port layer.
Index: serial_21285.c
===================================================================
RCS file: /cvsroot/linuxconsole/ruby/linux/drivers/serial/serial_21285.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- serial_21285.c 2001/07/29 18:24:12 1.3
+++ serial_21285.c 2001/10/08 04:33:45 1.4
@@ -563,3 +563,8 @@
}
#endif /* CONFIG_SERIAL_21285_CONSOLE */
+
+EXPORT_NO_SYMBOLS;
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Intel Footbridge (21285) serial driver");
Index: serial_8250.c
===================================================================
RCS file: /cvsroot/linuxconsole/ruby/linux/drivers/serial/serial_8250.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- serial_8250.c 2001/08/23 02:46:17 1.7
+++ serial_8250.c 2001/10/08 04:33:45 1.8
@@ -76,8 +76,9 @@
static struct tty_driver normal, callout;
static struct tty_struct *serial8250_table[UART_NR];
static struct termios *serial8250_termios[UART_NR], *serial8250_termios_locked[UART_NR];
-#ifdef SUPPORT_SYSRQ
+#ifdef CONFIG_SERIAL_8250_CONSOLE
static struct console serial8250_console;
+static unsigned int lsr_break_flag;
#endif
static struct uart_info *IRQ_ports[NR_IRQS];
@@ -692,7 +693,7 @@
* may get masked by ignore_status_mask
* or read_status_mask.
*/
- uart_handle_break(info, &sercons);
+ uart_handle_break(info, &serial8250_console);
} else if (*status & UART_LSR_PE)
port->icount.parity++;
else if (*status & UART_LSR_FE)
@@ -706,7 +707,7 @@
*status &= port->read_status_mask;
#ifdef CONFIG_SERIAL_8250_CONSOLE
- if (port->line == sercons.index) {
+ if (port->line == serial8250_console.index) {
/* Recover the break flag from console xmit */
*status |= lsr_break_flag;
lsr_break_flag = 0;
@@ -1651,6 +1652,8 @@
}
#endif
+#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
+
/*
* Wait for transmitter & holding register to empty
*/
@@ -1880,3 +1883,7 @@
EXPORT_SYMBOL(register_serial);
EXPORT_SYMBOL(unregister_serial);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Generic 8250/16x50 serial driver");
+
Index: serial_8250.h
===================================================================
RCS file: /cvsroot/linuxconsole/ruby/linux/drivers/serial/serial_8250.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
Index: serial_8250_pci.c
===================================================================
RCS file: /cvsroot/linuxconsole/ruby/linux/drivers/serial/serial_8250_pci.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- serial_8250_pci.c 2001/09/02 23:41:27 1.7
+++ serial_8250_pci.c 2001/10/08 04:33:45 1.8
@@ -1071,3 +1071,9 @@
module_init(serial8250_pci_init);
module_exit(serial8250_pci_exit);
+
+EXPORT_NO_SYMBOLS;
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Generic 8250/16x50 PCI serial probe module");
+MODULE_GENERIC_TABLE(pci, serial_pci_tbl);
Index: serial_8250_pnp.c
===================================================================
RCS file: /cvsroot/linuxconsole/ruby/linux/drivers/serial/serial_8250_pnp.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- serial_8250_pnp.c 2001/07/29 18:24:12 1.3
+++ serial_8250_pnp.c 2001/10/08 04:33:45 1.4
@@ -544,3 +544,10 @@
module_init(serial8250_pnp_init);
module_exit(serial8250_pnp_exit);
+
+EXPORT_NO_SYMBOLS;
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Generic 8250/16x50 PNPBIOS serial probe module");
+MODULE_GENERIC_TABLE(pnp, pnp_dev_table);
+
Index: serial_amba.c
===================================================================
RCS file: /cvsroot/linuxconsole/ruby/linux/drivers/serial/serial_amba.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- serial_amba.c 2001/08/23 02:46:18 1.6
+++ serial_amba.c 2001/10/08 04:33:45 1.7
@@ -487,7 +487,7 @@
/* first, disable everything */
save_flags(flags); cli();
- old_cr = UART_GET_CR(port) &= ~AMBA_UARTCR_MSIE;
+ old_cr = UART_GET_CR(port) & ~AMBA_UARTCR_MSIE;
if ((port->flags & ASYNC_HARDPPS_CD) ||
(cflag & CRTSCTS) || !(cflag & CLOCAL))
@@ -496,6 +496,7 @@
UART_PUT_CR(port, 0);
/* Set baud rate */
+ quot -= 1;
UART_PUT_LCRM(port, ((quot & 0xf00) >> 8));
UART_PUT_LCRL(port, (quot & 0xff));
@@ -725,6 +726,7 @@
}
static struct console amba_console = {
+ name: "ttyAM",
write: ambauart_console_write,
#ifdef used_and_not_const_char_pointer
read: ambauart_console_read,
@@ -780,3 +782,9 @@
module_init(ambauart_init);
module_exit(ambauart_exit);
+
+EXPORT_NO_SYMBOLS;
+
+MODULE_AUTHOR("ARM Ltd/Deep Blue Solutions Ltd");
+MODULE_DESCRIPTION("ARM AMBA serial port driver");
+MODULE_LICENSE("GPL");
Index: serial_clps711x.c
===================================================================
RCS file: /cvsroot/linuxconsole/ruby/linux/drivers/serial/serial_clps711x.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- serial_clps711x.c 2001/08/18 22:23:04 1.6
+++ serial_clps711x.c 2001/10/08 04:33:45 1.7
@@ -676,3 +676,9 @@
module_init(clps711xuart_init);
module_exit(clps711xuart_exit);
+
+EXPORT_NO_SYMBOLS;
+
+MODULE_AUTHOR("Deep Blue Solutions Ltd");
+MODULE_DESCRIPTION("CLPS-711x generic serial driver");
+MODULE_LICENSE("GPL");
Index: serial_core.c
===================================================================
RCS file: /cvsroot/linuxconsole/ruby/linux/drivers/serial/serial_core.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -d -r1.12 -r1.13
--- serial_core.c 2001/08/18 22:23:04 1.12
+++ serial_core.c 2001/10/08 04:33:45 1.13
@@ -273,7 +273,7 @@
((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST))
quot = info->state->custom_divisor;
else
- quot = (info->port->uartclk / (16 * baud)) - 1;
+ quot = info->port->uartclk / (16 * baud);
return quot;
}
@@ -1689,11 +1689,43 @@
}
co->cflag = cflag;
- quot = (port->uartclk / (16 * baud)) - 1;
+ quot = (port->uartclk / (16 * baud));
port->ops->change_speed(port, cflag, 0, quot);
return 0;
}
+
+extern void ambauart_console_init(void);
+extern void anakin_console_init(void);
+extern void clps711xuart_console_init(void);
+extern void rs285_console_init(void);
+extern void sa1100_rs_console_init(void);
+extern void serial8250_console_init(void);
+
+/*
+ * Central "initialise all serial consoles" container. Needs to be killed.
+ */
+void __init uart_console_init(void)
+{
+#ifdef CONFIG_SERIAL_AMBA_CONSOLE
+ ambauart_console_init();
+#endif
+#ifdef CONFIG_SERIAL_ANAKIN_CONSOLE
+ anakin_console_init();
+#endif
+#ifdef CONFIG_SERIAL_CLPS711X_CONSOLE
+ clps711xuart_console_init();
+#endif
+#ifdef CONFIG_SERIAL_21285_CONSOLE
+ rs285_console_init();
+#endif
+#ifdef CONFIG_SERIAL_SA1100_CONSOLE
+ sa1100_rs_console_init();
+#endif
+#ifdef CONFIG_SERIAL_8250_CONSOLE
+ serial8250_console_init();
+#endif
+}
#endif /* CONFIG_SERIAL_CORE_CONSOLE */
#ifdef CONFIG_PM
@@ -2147,3 +2179,6 @@
module_init(uart_init);
module_exit(uart_exit);
+
+MODULE_DESCRIPTION("Serial driver core");
+MODULE_LICENSE("GPL");
Index: serial_sa1100.c
===================================================================
RCS file: /cvsroot/linuxconsole/ruby/linux/drivers/serial/serial_sa1100.c,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -d -r1.11 -r1.12
--- serial_sa1100.c 2001/08/23 02:46:18 1.11
+++ serial_sa1100.c 2001/10/08 04:33:45 1.12
@@ -434,6 +434,7 @@
UART_PUT_UTCR0(port, utcr0);
/* set the baud rate */
+ quot -= 1;
UART_PUT_UTCR1(port, ((quot & 0xf00) >> 8));
UART_PUT_UTCR2(port, (quot & 0xff));
@@ -792,4 +793,10 @@
module_init(sa1100_serial_init);
module_exit(sa1100_serial_exit);
+
+EXPORT_NO_SYMBOLS;
+
+MODULE_AUTHOR("Deep Blue Solutions Ltd");
+MODULE_DESCRIPTION("SA1100 generic serial port driver");
+MODULE_LICENSE("GPL");
|
|
From: James S. <jsi...@us...> - 2001-10-08 04:30:41
|
Update of /cvsroot/linuxconsole/ruby/linux/kernel
In directory usw-pr-cvs1:/tmp/cvs-serv25361
Modified Files:
printk.c
Log Message:
After looking at Andrew Morton's patch and my work I merged them more together. The design I have is far more fine grain locking. I also did alot of proper inlining of code to minimize the diff. I replaced the console_sem with a console_lock again. But this time I don't do IRQ blocking with it (only spin_lock and spin_unlock) and I have the proper locking down for the console driver list now.
Index: printk.c
===================================================================
RCS file: /cvsroot/linuxconsole/ruby/linux/kernel/printk.c,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -d -r1.16 -r1.17
--- printk.c 2001/08/05 22:58:18 1.16
+++ printk.c 2001/10/08 04:30:38 1.17
@@ -13,7 +13,7 @@
* Fixed SMP synchronization, 08/08/99, Manfred Spraul
* man...@co...
* Rewrote bits to get rid of console_lock
- * 01Mar01 Andrew Morton <an...@uo...>
+ * 01Mar01 Andrew Morton <an...@uo...>
*/
#include <linux/mm.h>
@@ -27,7 +27,7 @@
#include <asm/uaccess.h>
-#define LOG_BUF_LEN (16384) /* This must be a power of two */
+#define LOG_BUF_LEN (16384) /* This must be a power of two */
#define LOG_BUF_MASK (LOG_BUF_LEN-1)
/* printk's without a loglevel use this.. */
@@ -44,14 +44,13 @@
int default_message_loglevel = DEFAULT_MESSAGE_LOGLEVEL;
int minimum_console_loglevel = MINIMUM_CONSOLE_LOGLEVEL;
int default_console_loglevel = DEFAULT_CONSOLE_LOGLEVEL;
+
int oops_in_progress;
/*
- * console_sem protects the console_drivers list, and also
- * provides serialisation for access to the entire console
- * driver system.
+ * console_lock protects the console_drivers list
*/
-static DECLARE_MUTEX(console_sem);
+static spinlock_t console_lock = SPIN_LOCK_UNLOCKED;
struct console *console_drivers;
/*
@@ -68,14 +67,10 @@
* The indices into log_buf are not constrained to LOG_BUF_LEN - they
* must be masked before subscripting
*/
-static unsigned long log_start; /* Index into log_buf: next char to be read
- syslog() */
-static unsigned long con_start; /* Index into log_buf: next char to be sent
- to consoles */
-static unsigned long log_end; /* Index into log_buf: most recently written
- char + 1 */
-static unsigned long logged_chars; /* Number of chars produced since last
- read+clear operation */
+static unsigned long log_start; /* Index into log_buf: next char to be read by syslog() */
+static unsigned long con_start; /* Index into log_buf: next char to be sent to consoles */
+static unsigned long log_end; /* Index into log_buf: most-recently-written-char + 1 */
+static unsigned long logged_chars; /* Number of chars produced since last read+clear operation */
struct console_cmdline console_cmdline[MAX_CMDLINECONSOLES];
static int preferred_console = -1;
@@ -147,7 +142,7 @@
* 6 -- Disable printk's to console
* 7 -- Enable printk's to console
* 8 -- Set level of messages printed to console
- * 9 -- Return the number of unread characters in the log buffer
+ * 9 -- Return number of unread characters in the log buffer
*/
int do_syslog(int type, char * buf, int len)
{
@@ -171,7 +166,7 @@
error = verify_area(VERIFY_WRITE,buf,len);
if (error)
goto out;
- error = wait_event_interruptible(log_wait,(log_start-log_end));
+ error = wait_event_interruptible(log_wait, (log_start - log_end));
if (error)
goto out;
i = 0;
@@ -267,7 +262,7 @@
spin_lock_irq(&logbuf_lock);
error = log_end - log_start;
spin_unlock_irq(&logbuf_lock);
- break;
+ break;
default:
error = -EINVAL;
break;
@@ -302,18 +297,17 @@
/*
* Write out chars from start to end - 1 inclusive
*/
-static void _call_console_drivers(struct console *con, unsigned long start,
- unsigned long end, int msg_log_level)
+static void _call_console_drivers(struct console *con, unsigned long start, unsigned long end, int msg_log_level)
{
- if (msg_log_level<console_loglevel && con && start != end){
+ if (msg_log_level < console_loglevel && con && start != end) {
if ((start & LOG_BUF_MASK) > (end & LOG_BUF_MASK)) {
- /* wrapped write */
- __call_console_drivers(con, start & LOG_BUF_MASK, LOG_BUF_LEN);
- __call_console_drivers(con, 0, end & LOG_BUF_MASK);
- } else {
- __call_console_drivers(con, start, end);
- }
- }
+ /* wrapped write */
+ __call_console_drivers(con, start & LOG_BUF_MASK, LOG_BUF_LEN);
+ __call_console_drivers(con, 0, end & LOG_BUF_MASK);
+ } else {
+ __call_console_drivers(con, start, end);
+ }
+ }
}
/*
@@ -321,50 +315,47 @@
* log_buf[start] to log_buf[end - 1].
* The console_sem must be held.
*/
-static void call_console_drivers(struct console *con, unsigned long start,
- unsigned long end)
+static void call_console_drivers(struct console *con, unsigned long start, unsigned long end)
{
unsigned long cur_index, start_print;
- static int msg_level = -1;
+ static int msg_level = -1;
- if (((long)(start - end)) > 0)
- BUG();
+ if (((long)(start - end)) > 0)
+ BUG();
cur_index = start;
- start_print = start;
- while (cur_index != end) {
- if (msg_level < 0 &&
- ((end - cur_index) >= 3) &&
- LOG_BUF(cur_index + 0) == '<' &&
- LOG_BUF(cur_index + 1) >= '0' &&
- LOG_BUF(cur_index + 1) <= '7' &&
- LOG_BUF(cur_index + 2) == '>') {
- msg_level = LOG_BUF(cur_index + 1) - '0';
- cur_index += 3;
- start_print = cur_index;
- }
- while (cur_index != end) {
- char c = LOG_BUF(cur_index);
- cur_index++;
+ start_print = start;
+ while (cur_index != end) {
+ if ( msg_level < 0 &&
+ ((end - cur_index) > 2) &&
+ LOG_BUF(cur_index + 0) == '<' &&
+ LOG_BUF(cur_index + 1) >= '0' &&
+ LOG_BUF(cur_index + 1) <= '7' &&
+ LOG_BUF(cur_index + 2) == '>')
+ {
+ msg_level = LOG_BUF(cur_index + 1) - '0';
+ cur_index += 3;
+ start_print = cur_index;
+ }
+ while (cur_index != end) {
+ char c = LOG_BUF(cur_index);
+ cur_index++;
- if (c == '\n') {
+ if (c == '\n') {
if (msg_level < 0) {
- /*
- * printk() has already given us
- * loglevel tages in the buffer.
- * This code is here in case the
- * log buffer has wrapped right
- * around and scribbled on those
- * tags.
- */
- msg_level = default_message_loglevel;
- }
- _call_console_drivers(con, start_print,
- cur_index, msg_level);
- msg_level = -1;
- start_print = cur_index;
- break;
- }
+ /*
+ * printk() has already given us loglevel tags in
+ * the buffer. This code is here in case the
+ * log buffer has wrapped right round and scribbled
+ * on those tags
+ */
+ msg_level = default_message_loglevel;
+ }
+ _call_console_drivers(con, start_print, cur_index, msg_level);
+ msg_level = -1;
+ start_print = cur_index;
+ break;
+ }
}
}
_call_console_drivers(con, start_print, end, msg_level);
@@ -373,100 +364,116 @@
static void emit_log_char(char c)
{
LOG_BUF(log_end) = c;
- log_end++;
- if (log_end - log_start > LOG_BUF_LEN)
- log_start = log_end - LOG_BUF_LEN;
+ log_end++;
+ if (log_end - log_start > LOG_BUF_LEN)
+ log_start = log_end - LOG_BUF_LEN;
if (log_end - con_start > LOG_BUF_LEN)
- con_start = log_end - LOG_BUF_LEN;
- if (logged_chars < LOG_BUF_LEN)
- logged_chars++;
+ con_start = log_end - LOG_BUF_LEN;
+ if (logged_chars < LOG_BUF_LEN)
+ logged_chars++;
}
+/*
+ * This is printk. It can be called from any context. We want it to work.
+ *
+ * We try to grab the console_sem. If we succeed, it's easy - we log the output and
+ * call the console drivers. If we fail to get the semaphore we place the output
+ * into the log buffer and return. The current holder of the console_sem will
+ * notice the new output in release_console_sem() and will send it to the
+ * consoles before releasing the semaphore.
+ *
+ * One effect of this deferred printing is that code which calls printk() and
+ * then changes console_loglevel may break. This is because console_loglevel
+ * is inspected when the actual printing occurs.
+ */
asmlinkage int printk(const char *fmt, ...)
{
static struct {
- char buf[1024];
- unsigned long semi_random;
+ char buf[1024];
+ unsigned long semi_random;
} printk_buf;
- static int log_level_unknown = 1;
- struct tty_driver *driver;
- unsigned long sr_copy;
- unsigned long flags;
- struct console *con;
- int printed_len;
- va_list args;
+ static int log_level_unknown = 1;
+ struct tty_driver *driver;
+ unsigned long sr_copy;
+ unsigned long flags;
+ struct console *con;
+ int printed_len;
+ va_list args;
char *p;
if (oops_in_progress) {
/* If a crash is occurring, make sure we can't deadlock */
spin_lock_init(&logbuf_lock);
- /* And make sure that we print immediately */
+ spin_lock_init(&console_lock);
}
/* This stops the holder of console_sem just where we want him */
spin_lock_irqsave(&logbuf_lock, flags);
+
/* Emit the output into the temporary buffer */
printk_buf.semi_random += jiffies;
sr_copy = printk_buf.semi_random;
va_start(args, fmt);
- printed_len = vsprintf(printk_buf.buf, fmt, args);
+ printed_len = vsnprintf(printk_buf.buf, sizeof(printk_buf.buf), fmt, args);
va_end(args);
-
- if (sr_copy != printk_buf.semi_random)
+
+ if (sr_copy != printk_buf.semi_random)
panic("buffer overrun in printk()");
- /*
- * Copy the output into log_buf. If the caller didn't provide
- * appropriate log level tags, we insert them here
- */
+ /*
+ * Copy the output into log_buf. If the caller didn't provide
+ * appropriate log level tags, we insert them here
+ */
for (p = printk_buf.buf; *p; p++) {
- if (log_level_unknown) {
- if (p[0] != '<' || p[1] < '0' || p[1] > '7' || p[2] != '>') {
+ if (log_level_unknown) {
+ if (p[0] != '<' || p[1] < '0' || p[1] > '7' || p[2] != '>') {
emit_log_char('<');
- emit_log_char(default_message_loglevel + '0');
- emit_log_char('>');
- }
- log_level_unknown = 0;
- }
- emit_log_char(*p);
- if (*p == '\n')
+ emit_log_char(default_message_loglevel + '0');
+ emit_log_char('>');
+ }
+ log_level_unknown = 0;
+ }
+ emit_log_char(*p);
+ if (*p == '\n')
log_level_unknown = 1;
}
spin_unlock_irqrestore(&logbuf_lock, flags);
- for (con = console_drivers; con; con = con->next) {
- if ((con->flags & CON_ENABLED) && con->write) {
+ spin_lock(&console_lock);
+ for (con = console_drivers; con; con = con->next) {
+ /*
+ * We own the drivers list. We can drop the lock and
+ * let release_console_sem() print the text
+ */
+ if ((con->flags & CON_ENABLED) && con->write) {
driver = get_tty_driver(con->device(con));
- if (driver && !down_trylock(&driver->tty_lock))
+ if (driver && !down_trylock(&driver->tty_lock)) {
+ driver->may_schedule = 0;
release_console_sem(con->device(con));
+ }
}
}
+ spin_unlock(&console_lock);
return printed_len;
}
EXPORT_SYMBOL(printk);
-void console_print(const char *s)
-{
- printk(KERN_EMERG "%s", s);
-}
-EXPORT_SYMBOL(console_print);
-
/**
* acquire_console_sem - lock the console system for exclusive use.
*
* Acquires a semaphore which guarantees that the caller has
- * exclusive access to the console display being drawn to.
+ * exclusive access to a console system.
*
* Can sleep, returns nothing.
*/
void acquire_console_sem(kdev_t device)
{
struct tty_driver *driver = get_tty_driver(device);
-
+
if (in_interrupt())
- BUG();
- down(&driver->tty_lock);
- //console_may_schedule = 1;
+ BUG();
+ down(&driver->tty_lock);
+ driver->may_schedule = 1;
}
EXPORT_SYMBOL(acquire_console_sem);
@@ -488,42 +495,67 @@
{
struct tty_driver *driver = get_tty_driver(device);
unsigned long _con_start, _log_end;
- unsigned long must_wake_klogd = 0;
+ unsigned long must_wake_klogd = 0;
unsigned long flags;
struct console *con;
if (driver->flags & TTY_DRIVER_CONSOLE) {
- /* Look for new messages */
+ spin_lock(&console_lock);
+ /* Look for new messages */
for (con = console_drivers; con; con = con->next) {
if (con->device(con) == device)
break;
- }
-
+ }
+ spin_unlock(&console_lock);
+
for ( ; ; ) {
- spin_lock_irqsave(&logbuf_lock, flags);
- must_wake_klogd |= log_start - log_end;
- if (con_start == log_end)
- break; /* Nothing to print */
- _con_start = con_start;
- _log_end = log_end;
- con_start = log_end; /* Flush */
- spin_unlock_irqrestore(&logbuf_lock, flags);
- call_console_drivers(con, _con_start, _log_end);
+ spin_lock_irqsave(&logbuf_lock, flags);
+ must_wake_klogd |= log_start - log_end;
+ if (con_start == log_end)
+ break; /* Nothing to print */
+ _con_start = con_start;
+ _log_end = log_end;
+ con_start = log_end; /* Flush */
+ spin_unlock_irqrestore(&logbuf_lock, flags);
+ call_console_drivers(con, _con_start, _log_end);
}
- spin_unlock_irqrestore(&logbuf_lock, flags);
- if (must_wake_klogd && !oops_in_progress)
- wake_up_interruptible(&log_wait);
+ spin_unlock_irqrestore(&logbuf_lock, flags);
+ if (must_wake_klogd && !oops_in_progress)
+ wake_up_interruptible(&log_wait);
}
- up(&driver->tty_lock);
+ driver->may_schedule = 0;
+ up(&driver->tty_lock);
}
+/** console_conditional_schedule - yield the CPU if required
+ *
+ * If the console code is currently allowed to sleep, and
+ * if this CPU should yield the CPU to another task, do
+ * so here.
+ *
+ * Must be called within acquire_console_sem().
+ */
+void console_conditional_schedule(struct tty_driver *driver)
+{
+ if (driver->may_schedule && current->need_resched) {
+ set_current_state(TASK_RUNNING);
+ schedule();
+ }
+}
+
+void console_print(const char *s)
+{
+ printk(KERN_EMERG "%s", s);
+}
+EXPORT_SYMBOL(console_print);
+
/*
* The console driver calls this routine during kernel initialization
* to register the console printing procedure with printk() and to
* print any messages that were printed by the kernel before the
* console driver was initialized.
*/
-void register_console(struct console *console)
+void register_console(struct console * console)
{
struct tty_driver *driver;
unsigned long flags;
@@ -573,25 +605,26 @@
* Put this console in the list - keep the
* preferred driver at the head of the list.
*/
- down(&console_sem);
+ spin_lock(&console_lock);
if ((console->flags & CON_CONSDEV) || console_drivers == NULL) {
console->next = console_drivers;
console_drivers = console;
} else {
console->next = console_drivers->next;
console_drivers->next = console;
- }
- driver = get_tty_driver(console->device(console));
- if (driver) {
- init_MUTEX(&driver->tty_lock);
- driver->flags |= TTY_DRIVER_CONSOLE;
}
- up(&console_sem);
- if (console->flags & CON_PRINTBUFFER) {
+ spin_unlock(&console_lock);
+
+ driver = get_tty_driver(console->device(console));
+ if (driver) {
+ init_MUTEX(&driver->tty_lock);
+ driver->flags |= TTY_DRIVER_CONSOLE;
+ }
+
+ if (console->flags & CON_PRINTBUFFER) {
/*
- * release_cosole_sem() will print out the buffered
- * messages for us.
- */
+ * release_console_sem() will print out the buffered messages for us.
+ */
spin_lock_irqsave(&logbuf_lock, flags);
con_start = log_start;
spin_unlock_irqrestore(&logbuf_lock, flags);
@@ -600,15 +633,16 @@
}
EXPORT_SYMBOL(register_console);
-int unregister_console(struct console *console)
+int unregister_console(struct console * console)
{
struct tty_driver *driver = get_tty_driver(console->device(console));
struct console *a,*b;
int res = 1;
- down(&console_sem);
if (driver)
release_console_sem(console->device(console));
+
+ spin_lock(&console_lock);
if (console_drivers == console) {
console_drivers=console->next;
res = 0;
@@ -629,14 +663,16 @@
*/
if (console_drivers == NULL)
preferred_console = -1;
- up(&console_sem);
+
+ spin_unlock(&console_lock);
return res;
}
EXPORT_SYMBOL(unregister_console);
-/*
- * Write a message to a certain tty, not just the console. This is used for
- * messages that need to be redirected to a specific tty.
+/**
+ * tty_write_message - write a message to a certain tty, not just the console.
+ *
+ * This is used for messages that need to be redirected to a specific tty.
* We don't put it into the syslog queue right now maybe in the future if
* really needed.
*/
|
|
From: James S. <jsi...@us...> - 2001-10-08 04:27:17
|
Update of /cvsroot/linuxconsole/ruby/linux/include/linux In directory usw-pr-cvs1:/tmp/cvs-serv24972 Modified Files: tty_driver.h Log Message: Added may_schedule field. From Andrew Morton's console sem patch. I feel it is much better to allow any TTY device the ability to conditional schedule. Especially some serial devices can be just as slow as VESA fb. Index: tty_driver.h =================================================================== RCS file: /cvsroot/linuxconsole/ruby/linux/include/linux/tty_driver.h,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- tty_driver.h 2001/06/02 16:40:03 1.2 +++ tty_driver.h 2001/10/08 04:27:13 1.3 @@ -129,6 +129,7 @@ short subtype; /* subtype of tty driver */ struct termios init_termios; /* Initial termios */ int flags; /* tty driver flags */ + int may_schedule; /* when we can schedule */ int *refcount; /* for loadable tty drivers */ struct semaphore tty_lock;/* access control for printk and tty layer */ struct proc_dir_entry *proc_entry; /* /proc fs entry */ |
|
From: James S. <jsi...@us...> - 2001-10-08 02:27:12
|
Update of /cvsroot/linuxconsole/ruby/linux/drivers/video
In directory usw-pr-cvs1:/tmp/cvs-serv5943
Modified Files:
vesafb.c
Log Message:
Removed a compile warning.
Index: vesafb.c
===================================================================
RCS file: /cvsroot/linuxconsole/ruby/linux/drivers/video/vesafb.c,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -d -r1.16 -r1.17
--- vesafb.c 2001/05/06 00:05:28 1.16
+++ vesafb.c 2001/10/08 02:27:09 1.17
@@ -203,7 +203,7 @@
if (!options || !*options)
return 0;
- while (this_opt = strsep(&options, ",")) {
+ while ((this_opt = strsep(&options, ","))) {
if (!*this_opt) continue;
if (! strcmp(this_opt, "inverse"))
|
|
From: James S. <jsi...@us...> - 2001-10-08 02:26:22
|
Update of /cvsroot/linuxconsole/ruby/linux/drivers/video/tdfx In directory usw-pr-cvs1:/tmp/cvs-serv5728 Modified Files: 3dfxfb.c Log Message: Synced up to the standard tree by adding in the pci_register code. Index: 3dfxfb.c =================================================================== RCS file: /cvsroot/linuxconsole/ruby/linux/drivers/video/tdfx/3dfxfb.c,v retrieving revision 1.12 retrieving revision 1.13 diff -u -d -r1.12 -r1.13 --- 3dfxfb.c 2001/06/07 06:18:11 1.12 +++ 3dfxfb.c 2001/10/08 02:26:20 1.13 @@ -18,6 +18,11 @@ * Voodoo3 support was contributed Harold Oga. Lots of additions * (proper acceleration, 24 bpp, hardware cursor) and bug fixes by Attila * Kesmarki. Thanks guys! + * + * Voodoo1 and Voodoo2 support aren't relevant to this driver as they + * behave very differently from the Voodoo3/4/5. For anyone wanting to + * use frame buffer on the Voodoo1/2, see the sstfb driver (which is + * located at http://www.sourceforge.net/projects/sstfb). * * While I _am_ grateful to 3Dfx for releasing the specs for Banshee, * I do wish the next version is a bit more complete. Without the XF86 @@ -32,9 +37,6 @@ * TODO: * - support for 16/32 bpp needs fixing (funky bootup penguin) * - multihead support (basically need to support an array of fb_infos) - * - banshee and voodoo3 now supported -- any others? afaik, the original - * voodoo was a 3d-only card, so we won't consider that. what about - * voodoo2? * - support other architectures (PPC, Alpha); does the fact that the VGA * core can be accessed only thru I/O (not memory mapped) complicate * things? @@ -105,6 +107,34 @@ }; /* + * PCI driver prototypes + */ +static int tdfxfb_probe(struct pci_dev *pdev, const struct pci_device_id *id); +static void tdfxfb_remove(struct pci_dev *pdev); + +static struct pci_device_id tdfxfb_id_table[] __devinitdata = { + { PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_BANSHEE, + PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16, + 0xff0000, 0 }, + { PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO3, + PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16, + 0xff0000, 0 }, + { PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO5, + PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16, + 0xff0000, 0 }, + { 0, } +}; + +static struct pci_driver tdfxfb_driver = { + name: "tdfxfb", + id_table: tdfxfb_id_table, + probe: tdfxfb_probe, + remove: tdfxfb_remove, +}; + +MODULE_DEVICE_TABLE(pci, tdfxfb_id_table); + +/* * Frame buffer device API */ int tdfxfb_init(void); @@ -124,8 +154,6 @@ unsigned int width, unsigned int height, int dx, int dy); static void tdfxfb_imageblit(struct fb_info *info, struct fb_image *image); -static int tdfxfb_ioctl(struct inode* inode, struct file *file, u_int cmd, - u_long arg, struct fb_info *info); static struct fb_ops tdfxfb_ops = { owner: THIS_MODULE, @@ -138,7 +166,6 @@ fb_fillrect: tdfxfb_fillrect, fb_copyarea: tdfxfb_copyarea, fb_imageblit: tdfxfb_imageblit, - fb_ioctl: tdfxfb_ioctl, }; /* @@ -161,7 +188,7 @@ static int nowrap = 1; // not implemented (yet) static int inverse = 0; static int nohwcursor = 0; -static const char *mode_option __initdata = NULL; +static char *mode_option __initdata = NULL; /* ------------------------------------------------------------------------- * Hardware-specific funcions @@ -1077,21 +1104,6 @@ banshee_wait_idle(); } -static int tdfxfb_ioctl(struct inode *inode, struct file *file, u_int cmd, - u_long arg, struct fb_info *info) -{ -/* These IOCTLs ar just for testing only... - switch (cmd) { - case 0x4680: - nowrap=nopan=0; - return 0; - case 0x4681: - nowrap=nopan=1; - return 0; - }*/ - return -EINVAL; -} - static void tdfxfb_hwcursor_init(struct fb_info *info) { unsigned int start; @@ -1103,15 +1115,18 @@ info->cursor.image); } -int __init tdfxfb_init(void) +/** + * tdfxfb_probe - Device Initializiation + * + * @pdev: PCI Device to initialize + * @id: PCI Device ID + * + * Initializes and allocates resources for PCI device @pdev. + * + */ +static int __devinit tdfxfb_probe(struct pci_dev *pdev, + const struct pci_device_id *id) { - struct pci_dev *pdev = NULL; - - while ((pdev = pci_find_device(PCI_VENDOR_ID_3DFX, PCI_ANY_ID, pdev))) { - if(((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY) && - ((pdev->device == PCI_DEVICE_ID_3DFX_BANSHEE) || - (pdev->device == PCI_DEVICE_ID_3DFX_VOODOO3) || - (pdev->device == PCI_DEVICE_ID_3DFX_VOODOO5))) { /* Configure the default fb_fix_screeninfo first */ memset(&fb_info, 0, sizeof(fb_info)); fb_info.par = &default_par; @@ -1189,27 +1204,36 @@ printk("fb%d: %s frame buffer device\n", GET_FB_IDX(fb_info.node), fb_info.fix.id); - } - } - return 0; + return 0; } /** - * tdfxfb_exit - Driver cleanup + * tdfxfb_remove - Device removal * - * Releases all resources allocated during the - * course of the driver's lifetime. + * @pdev: PCI Device to cleanup * - * FIXME - do results of fb_alloc_cmap need disposal? + * Releases all resources allocated during the course of the driver's + * lifetime for the PCI device @pdev. + * */ -static void __exit tdfxfb_exit (void) +static void __devexit tdfxfb_remove(struct pci_dev *pdev) { struct tdfx_par *par = (struct tdfx_par *) fb_info.par; unregister_framebuffer(&fb_info); - del_timer_sync(&par->hwcursor.timer); + //del_timer_sync(&par->hwcursor.timer); iounmap(par->regbase_virt); iounmap(fb_info.screen_base); +} + +int __init tdfxfb_init(void) +{ + return pci_module_init(&tdfxfb_driver); +} + +static void __exit tdfxfb_exit(void) +{ + pci_unregister_driver(&tdfxfb_driver); } MODULE_AUTHOR("Hannu Mallat <hm...@cc...>"); |
|
From: James S. <jsi...@us...> - 2001-10-08 02:25:19
|
Update of /cvsroot/linuxconsole/ruby/linux/drivers/video
In directory usw-pr-cvs1:/tmp/cvs-serv5592
Modified Files:
fbmem.c
Log Message:
Made the penguin logo come back. It works even for stand alone fbdev systems. Hey this way you know if it worked.
Index: fbmem.c
===================================================================
RCS file: /cvsroot/linuxconsole/ruby/linux/drivers/video/fbmem.c,v
retrieving revision 1.50
retrieving revision 1.51
diff -u -d -r1.50 -r1.51
--- fbmem.c 2001/10/06 16:11:13 1.50
+++ fbmem.c 2001/10/08 02:25:16 1.51
@@ -775,7 +775,7 @@
}
#endif
-static void __init fbcon_show_logo(struct fb_info *info)
+static void fbcon_show_logo(struct fb_info *info)
{
u16 palette_red[16], palette_green[16], palette_blue[16];
int depth = info->var.bits_per_pixel;
@@ -885,7 +885,7 @@
printk("%s: MTRR turned on\n", fb_info->fix.id);
}
#endif
-
+ fbcon_show_logo(fb_info);
return 0;
}
|
|
From: James S. <jsi...@us...> - 2001-10-08 02:24:01
|
Update of /cvsroot/linuxconsole/ruby/linux/drivers/video
In directory usw-pr-cvs1:/tmp/cvs-serv5311
Modified Files:
Config.in
Log Message:
Oops. Small config error with SiS.
Index: Config.in
===================================================================
RCS file: /cvsroot/linuxconsole/ruby/linux/drivers/video/Config.in,v
retrieving revision 1.49
retrieving revision 1.50
diff -u -d -r1.49 -r1.50
--- Config.in 2001/10/06 16:11:13 1.49
+++ Config.in 2001/10/08 02:23:57 1.50
@@ -168,6 +168,7 @@
bool ' 3Dfx Banshee/Voodoo3 display support (EXPERIMENTAL)' CONFIG_FB_3DFX
bool ' 3Dfx Voodoo Graphics (sst1) support (EXPERIMENTAL)' CONFIG_FB_VOODOO1
fi
+ tristate ' SIS acceleration (EXPERIMENTAL)' CONFIG_FB_SIS
if [ "$CONFIG_FB_SIS" != "n" ]; then
bool ' SIS 630/540/730 support' CONFIG_FB_SIS_300
bool ' SIS 315H/315 support' CONFIG_FB_SIS_315
|
|
From: johann d. <jd...@us...> - 2001-10-07 19:29:11
|
Update of /cvsroot/linuxconsole/ruby/utils
In directory usw-pr-cvs1:/tmp/cvs-serv30954
Modified Files:
Tag: iforce-split
Makefile ffcfstress.c ffmvforce.c fftest.c
Log Message:
Reflected the change of the ff_effect structure (the "direction" member was
moved out of the union, as every effect type used it).
Index: Makefile
===================================================================
RCS file: /cvsroot/linuxconsole/ruby/utils/Makefile,v
retrieving revision 1.10
retrieving revision 1.10.2.1
diff -u -d -r1.10 -r1.10.2.1
--- Makefile 2001/10/03 08:35:19 1.10
+++ Makefile 2001/10/07 19:29:08 1.10.2.1
@@ -41,7 +41,7 @@
$(RM) *.o *.swp $(PROGRAMS) *.orig *.rej map *~
ffcfstress: ffcfstress.c
- $(CC) -O2 -mcpu=pentiumpro -fno-implement-inlines -funsigned-char \
+ $(CC) -O2 -fno-implement-inlines -funsigned-char \
-lm ffcfstress.c -o ffcfstress
ffmvforce.o: ffmvforce.c
Index: ffcfstress.c
===================================================================
RCS file: /cvsroot/linuxconsole/ruby/utils/ffcfstress.c,v
retrieving revision 1.1
retrieving revision 1.1.2.1
diff -u -d -r1.1 -r1.1.2.1
--- ffcfstress.c 2001/10/02 17:47:28 1.1
+++ ffcfstress.c 2001/10/07 19:29:08 1.1.2.1
@@ -20,7 +20,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include <linux/input.h>
+#include "../linux/include/linux/input.h"
#include <sys/ioctl.h>
#include <stdio.h>
#include <stdlib.h>
@@ -186,7 +186,7 @@
effect.replay.length=0xffff;
effect.replay.delay=0;
effect.u.constant.level=0;
- effect.u.constant.direction=0xC000;
+ effect.direction=0xC000;
effect.u.constant.shape.attack_length=0;
effect.u.constant.shape.attack_level=0;
effect.u.constant.shape.fade_length=0;
@@ -231,7 +231,7 @@
if (force>1.0) force=1.0;
if (force<-1.0) force=1.0;
effect.u.constant.level=(short)(force*32767.0); /* only to be safe */
- effect.u.constant.direction=0xC000;
+ effect.direction=0xC000;
effect.u.constant.shape.attack_level=(short)(force*32767.0); /* this one counts! */
effect.u.constant.shape.fade_level=(short)(force*32767.0); /* only to be safe */
Index: ffmvforce.c
===================================================================
RCS file: /cvsroot/linuxconsole/ruby/utils/ffmvforce.c,v
retrieving revision 1.8
retrieving revision 1.8.2.1
diff -u -d -r1.8 -r1.8.2.1
--- ffmvforce.c 2001/10/02 18:27:59 1.8
+++ ffmvforce.c 2001/10/07 19:29:08 1.8.2.1
@@ -77,8 +77,8 @@
printf("mouse: %d %d n: %4.2f %4.2f angle: %4.2f\n", x, y, nx, ny, angle);
effect.type = FF_CONSTANT;
effect.u.constant.level = 0x7fff * max(fabs(nx), fabs(ny));
- effect.u.constant.direction = 0x8000 * (angle + M_PI)/M_PI;
-printf("level: %04x direction: %04x\n", (unsigned int)effect.u.constant.level, (unsigned int)effect.u.constant.direction);
+ effect.direction = 0x8000 * (angle + M_PI)/M_PI;
+printf("level: %04x direction: %04x\n", (unsigned int)effect.u.constant.level, (unsigned int)effect.direction);
effect.u.constant.shape.attack_length = 0;
effect.u.constant.shape.attack_level = 0;
effect.u.constant.shape.fade_length = 0;
Index: fftest.c
===================================================================
RCS file: /cvsroot/linuxconsole/ruby/utils/fftest.c,v
retrieving revision 1.11
retrieving revision 1.11.2.1
diff -u -d -r1.11 -r1.11.2.1
--- fftest.c 2001/10/02 18:27:59 1.11
+++ fftest.c 2001/10/07 19:29:08 1.11.2.1
@@ -105,7 +105,7 @@
effects[1].type = FF_CONSTANT;
effects[1].id = -1;
effects[1].u.constant.level = 0x2000; /* Strength : 25 % */
- effects[1].u.constant.direction = 0x6000; /* 135 degrees */
+ effects[1].direction = 0x6000; /* 135 degrees */
effects[1].u.constant.shape.attack_length = 0x100;
effects[1].u.constant.shape.attack_level = 0;
effects[1].u.constant.shape.fade_length = 0x100;
@@ -128,7 +128,7 @@
effects[0].u.periodic.magnitude = 0x4000; /* 0.5 * Maximum magnitude */
effects[0].u.periodic.offset = 0;
effects[0].u.periodic.phase = 0;
- effects[0].u.periodic.direction = 0x4000; /* Along X axis */
+ effects[0].direction = 0x4000; /* Along X axis */
effects[0].u.periodic.shape.attack_length = 0x100;
effects[0].u.periodic.shape.attack_level = 0;
effects[0].u.periodic.shape.fade_length = 0x100;
|
|
From: johann d. <jd...@us...> - 2001-10-07 19:25:45
|
Update of /cvsroot/linuxconsole/ruby/linux/drivers/input
In directory usw-pr-cvs1:/tmp/cvs-serv30438
Modified Files:
Tag: iforce-split
iforce-ff.c
Log Message:
iforce_upload_* now return the correct value.
Index: iforce-ff.c
===================================================================
RCS file: /cvsroot/linuxconsole/ruby/linux/drivers/input/Attic/iforce-ff.c,v
retrieving revision 1.1.2.1
retrieving revision 1.1.2.2
diff -u -d -r1.1.2.1 -r1.1.2.2
--- iforce-ff.c 2001/10/07 17:06:49 1.1.2.1
+++ iforce-ff.c 2001/10/07 19:25:43 1.1.2.2
@@ -41,6 +41,8 @@
{
unsigned char data[3];
+ printk(KERN_DEBUG "iforce: in make_magnitude_modifier\n");
+
if (!no_alloc) {
down(&iforce->mem_mutex);
if (allocate_resource(&(iforce->device_memory), mod_chunk, 2,
@@ -350,25 +352,27 @@
struct iforce_core_effect* core_effect = iforce->core_effects + core_id;
struct resource* mod1_chunk = &(iforce->core_effects[core_id].mod1_chunk);
struct resource* mod2_chunk = &(iforce->core_effects[core_id].mod2_chunk);
- int err = 1;
+ int param1_err = 1;
+ int param2_err = 1;
+ int core_err = 0;
if (!is_update || need_period_modifier(iforce, effect)) {
- err = make_period_modifier(iforce, mod1_chunk,
+ param1_err = make_period_modifier(iforce, mod1_chunk,
is_update,
effect->u.periodic.magnitude, effect->u.periodic.offset,
effect->u.periodic.period, effect->u.periodic.phase);
- if (err) return err;
+ if (param1_err) return param1_err;
set_bit(FF_MOD1_IS_USED, core_effect->flags);
}
if (!is_update || need_shape_modifier(iforce, effect)) {
- err = make_shape_modifier(iforce, mod2_chunk,
+ param2_err = make_shape_modifier(iforce, mod2_chunk,
is_update,
effect->u.periodic.shape.attack_length,
effect->u.periodic.shape.attack_level,
effect->u.periodic.shape.fade_length,
effect->u.periodic.shape.fade_level);
- if (err) return err;
+ if (param2_err) return param2_err;
set_bit(FF_MOD2_IS_USED, core_effect->flags);
}
@@ -382,7 +386,7 @@
}
if (!is_update || need_core(iforce, effect)) {
- err = make_core(iforce, effect->id,
+ core_err = make_core(iforce, effect->id,
mod1_chunk->start,
mod2_chunk->start,
wave_code,
@@ -397,7 +401,13 @@
printk(KERN_DEBUG "iforce.c: no effect packet was needed\n");
}
- return err;
+ /* If one of the parameter creation failed, we already returned an
+ * error code.
+ * If the core creation failed, we return its error code.
+ * Else: if one parameter at least was created, we return 0
+ * else we return 1;
+ */
+ return core_err < 0 ? core_err : (param1_err && param2_err);
}
/*
@@ -413,31 +423,33 @@
struct iforce_core_effect* core_effect = iforce->core_effects + core_id;
struct resource* mod1_chunk = &(iforce->core_effects[core_id].mod1_chunk);
struct resource* mod2_chunk = &(iforce->core_effects[core_id].mod2_chunk);
- int ret = 1;
+ int param1_err = 1;
+ int param2_err = 1;
+ int core_err = 0;
printk(KERN_DEBUG "iforce.c: make constant effect\n");
if (!is_update || need_magnitude_modifier(iforce, effect)) {
- ret = make_magnitude_modifier(iforce, mod1_chunk,
+ param1_err = make_magnitude_modifier(iforce, mod1_chunk,
is_update,
effect->u.constant.level);
- if (ret) return ret;
+ if (param1_err) return param1_err;
set_bit(FF_MOD1_IS_USED, core_effect->flags);
}
if (!is_update || need_shape_modifier(iforce, effect)) {
- ret = make_shape_modifier(iforce, mod2_chunk,
+ param2_err = make_shape_modifier(iforce, mod2_chunk,
is_update,
effect->u.constant.shape.attack_length,
effect->u.constant.shape.attack_level,
effect->u.constant.shape.fade_length,
effect->u.constant.shape.fade_level);
- if (ret) return ret;
+ if (param2_err) return param2_err;
set_bit(FF_MOD2_IS_USED, core_effect->flags);
}
if (!is_update || need_core(iforce, effect)) {
- ret = make_core(iforce, effect->id,
+ core_err = make_core(iforce, effect->id,
mod1_chunk->start,
mod2_chunk->start,
0x00,
@@ -452,7 +464,13 @@
printk(KERN_DEBUG "iforce.c: no effect packet was needed\n");
}
- return ret;
+ /* If one of the parameter creation failed, we already returned an
+ * error code.
+ * If the core creation failed, we return its error code.
+ * Else: if one parameter at least was created, we return 0
+ * else we return 1;
+ */
+ return core_err < 0 ? core_err : (param1_err && param2_err);
}
/*
@@ -465,7 +483,8 @@
struct resource* mod_chunk = &(core_effect->mod1_chunk);
u8 type, axes;
u16 mod1, mod2, direction;
- int err = 1;
+ int param_err = 1;
+ int core_err = 0;
printk(KERN_DEBUG "iforce.c: make interactive effect\n");
@@ -476,7 +495,7 @@
}
if (!is_update || need_interactive_modifier(iforce, effect)) {
- err = make_interactive_modifier(iforce, mod_chunk,
+ param_err = make_interactive_modifier(iforce, mod_chunk,
is_update,
effect->u.interactive.right_saturation,
effect->u.interactive.left_saturation,
@@ -484,7 +503,7 @@
effect->u.interactive.left_coeff,
effect->u.interactive.deadband,
effect->u.interactive.center);
- if (err) return err;
+ if (param_err) return param_err;
set_bit(FF_MOD1_IS_USED, core_effect->flags);
}
@@ -526,7 +545,7 @@
}
if (!is_update || need_core(iforce, effect)) {
- err = make_core(iforce, effect->id,
+ core_err = make_core(iforce, effect->id,
mod1, mod2,
type, axes,
effect->replay.length, effect->replay.delay,
@@ -534,5 +553,11 @@
direction);
}
- return err;
+ /* If the parameter creation failed, we already returned an
+ * error code.
+ * If the core creation failed, we return its error code.
+ * Else: if a parameter was created, we return 0
+ * else we return 1;
+ */
+ return core_err < 0 ? core_err : param_err;
}
|
|
From: johann d. <jd...@us...> - 2001-10-07 19:25:05
|
Update of /cvsroot/linuxconsole/ruby/linux/drivers/input
In directory usw-pr-cvs1:/tmp/cvs-serv30231
Modified Files:
Tag: iforce-split
iforce-packets.c
Log Message:
Restart an effect that stopped early. This happens when we send core effect
parameters for updated effects.
Index: iforce-packets.c
===================================================================
RCS file: /cvsroot/linuxconsole/ruby/linux/drivers/input/Attic/iforce-packets.c,v
retrieving revision 1.1.2.1
retrieving revision 1.1.2.2
diff -u -d -r1.1.2.1 -r1.1.2.2
--- iforce-packets.c 2001/10/07 17:06:49 1.1.2.1
+++ iforce-packets.c 2001/10/07 19:25:03 1.1.2.2
@@ -209,6 +209,7 @@
}
else {
printk(KERN_WARNING "iforce.c: effect %d stopped, while it should not\nStarting again\n", i);
+ input_report_ff(dev, i, 1);
}
}
if (LO(cmd) > 3) {
|
|
From: James S. <jsi...@us...> - 2001-10-07 17:16:08
|
Update of /cvsroot/linuxconsole/ruby/linux/drivers/video In directory usw-pr-cvs1:/tmp/cvs-serv8534 Modified Files: vgacon.c Log Message: Added sched.h to vgacon to deal with issues compiling on some machines. Index: vgacon.c =================================================================== RCS file: /cvsroot/linuxconsole/ruby/linux/drivers/video/vgacon.c,v retrieving revision 1.55 retrieving revision 1.56 diff -u -d -r1.55 -r1.56 --- vgacon.c 2001/10/04 02:45:52 1.55 +++ vgacon.c 2001/10/07 17:16:06 1.56 @@ -37,6 +37,7 @@ #include <linux/module.h> #include <linux/types.h> #include <linux/kernel.h> +#include <linux/sched.h> #include <linux/tty.h> #include <linux/string.h> #include <linux/kd.h> |
|
From: johann d. <jd...@us...> - 2001-10-07 17:06:52
|
Update of /cvsroot/linuxconsole/ruby/linux/drivers/input
In directory usw-pr-cvs1:/tmp/cvs-serv6680
Modified Files:
Tag: iforce-split
Makefile
Added Files:
Tag: iforce-split
iforce-ff.c iforce-main.c iforce-packets.c iforce-serio.c
iforce-usb.c iforce.h
Removed Files:
Tag: iforce-split
iforce.c
Log Message:
Split iforce.c into several smaller files.
--- NEW FILE: iforce-ff.c ---
/*
* $Id: iforce-ff.c,v 1.1.2.1 2001/10/07 17:06:49 jdeneux Exp $
*
* Copyright (c) 2000-2001 Vojtech Pavlik <vo...@uc...>
* Copyright (c) 2001 Johann Deneux <de...@if...>
*
* USB/RS232 I-Force joysticks and wheels.
*/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* 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
*/
#include "iforce.h"
/*
* Set the magnitude of a constant force effect
* Return error code
*
* Note: caller must ensure exclusive access to device
*/
static int make_magnitude_modifier(struct iforce* iforce,
struct resource* mod_chunk, int no_alloc, __s16 level)
{
unsigned char data[3];
if (!no_alloc) {
down(&iforce->mem_mutex);
if (allocate_resource(&(iforce->device_memory), mod_chunk, 2,
iforce->device_memory.start, iforce->device_memory.end, 2L,
NULL, NULL)) {
up(&iforce->mem_mutex);
return -ENOMEM;
}
up(&iforce->mem_mutex);
}
data[0] = LO(mod_chunk->start);
data[1] = HI(mod_chunk->start);
data[2] = HIFIX80(level);
iforce_send_packet(iforce, FF_CMD_MAGNITUDE, data);
iforce_dump_packet("magnitude: ", FF_CMD_MAGNITUDE, data);
return 0;
}
/*
* Upload the component of an effect dealing with the period, phase and magnitude
*/
static int make_period_modifier(struct iforce* iforce,
struct resource* mod_chunk, int no_alloc,
__s16 magnitude, __s16 offset, u16 period, u16 phase)
{
unsigned char data[7];
period = TIME_SCALE(period);
if (!no_alloc) {
down(&iforce->mem_mutex);
if (allocate_resource(&(iforce->device_memory), mod_chunk, 0x0c,
iforce->device_memory.start, iforce->device_memory.end, 2L,
NULL, NULL)) {
up(&iforce->mem_mutex);
return -ENOMEM;
}
up(&iforce->mem_mutex);
}
data[0] = LO(mod_chunk->start);
data[1] = HI(mod_chunk->start);
data[2] = HIFIX80(magnitude);
data[3] = HIFIX80(offset);
data[4] = HI(phase);
data[5] = LO(period);
data[6] = HI(period);
iforce_send_packet(iforce, FF_CMD_PERIOD, data);
return 0;
}
/*
* Uploads the part of an effect setting the shape of the force
*/
static int make_shape_modifier(struct iforce* iforce,
struct resource* mod_chunk, int no_alloc,
u16 attack_duration, __s16 initial_level,
u16 fade_duration, __s16 final_level)
{
unsigned char data[8];
attack_duration = TIME_SCALE(attack_duration);
fade_duration = TIME_SCALE(fade_duration);
if (!no_alloc) {
down(&iforce->mem_mutex);
if (allocate_resource(&(iforce->device_memory), mod_chunk, 0x0e,
iforce->device_memory.start, iforce->device_memory.end, 2L,
NULL, NULL)) {
up(&iforce->mem_mutex);
return -ENOMEM;
}
up(&iforce->mem_mutex);
}
data[0] = LO(mod_chunk->start);
data[1] = HI(mod_chunk->start);
data[2] = LO(attack_duration);
data[3] = HI(attack_duration);
data[4] = HIFIX80(initial_level);
data[5] = LO(fade_duration);
data[6] = HI(fade_duration);
data[7] = HIFIX80(final_level);
iforce_send_packet(iforce, FF_CMD_SHAPE, data);
return 0;
}
/*
* Component of spring, friction, inertia... effects
*/
static int make_interactive_modifier(struct iforce* iforce,
struct resource* mod_chunk, int no_alloc,
__s16 rsat, __s16 lsat, __s16 rk, __s16 lk, u16 db, __s16 center)
{
unsigned char data[10];
if (!no_alloc) {
down(&iforce->mem_mutex);
if (allocate_resource(&(iforce->device_memory), mod_chunk, 8,
iforce->device_memory.start, iforce->device_memory.end, 2L,
NULL, NULL)) {
up(&iforce->mem_mutex);
return -ENOMEM;
}
up(&iforce->mem_mutex);
}
data[0] = LO(mod_chunk->start);
data[1] = HI(mod_chunk->start);
data[2] = HIFIX80(rk);
data[3] = HIFIX80(lk);
data[4] = LO(center);
data[5] = HI(center);
data[6] = LO(db);
data[7] = HI(db);
data[8] = HIFIX80(rsat);
data[9] = HIFIX80(lsat);
iforce_send_packet(iforce, FF_CMD_INTERACT, data);
return 0;
}
static unsigned char find_button(struct iforce *iforce, signed short button)
{
int i;
for (i = 1; iforce->type->btn[i] >= 0; i++)
if (iforce->type->btn[i] == button)
return i + 1;
return 0;
}
/*
* Analyse the changes in an effect, and tell if we need to send an interactive
* parameter packet
*/
static int need_interactive_modifier(struct iforce* iforce, struct ff_effect* new)
{
int id = new->id;
struct ff_effect* old = &iforce->core_effects[id].effect;
if (new->type != FF_SPRING && new->type != FF_FRICTION) {
printk(KERN_WARNING "iforce.c: bad effect type in need_interactive_modifier\n");
return FALSE;
}
return (old->u.interactive.right_saturation != new->u.interactive.right_saturation
|| old->u.interactive.left_saturation != new->u.interactive.left_saturation
|| old->u.interactive.right_coeff != new->u.interactive.right_coeff
|| old->u.interactive.left_coeff != new->u.interactive.left_coeff
|| old->u.interactive.deadband != new->u.interactive.deadband
|| old->u.interactive.center != new->u.interactive.center);
}
/*
* Analyse the changes in an effect, and tell if we need to send a magnitude
* parameter packet
*/
static int need_magnitude_modifier(struct iforce* iforce, struct ff_effect* effect)
{
int id = effect->id;
struct ff_effect* old = &iforce->core_effects[id].effect;
if (effect->type != FF_CONSTANT) {
printk(KERN_WARNING "iforce.c: bad effect type in need_shape_modifier\n");
return FALSE;
}
return (old->u.constant.level != effect->u.constant.level);
}
/*
* Analyse the changes in an effect, and tell if we need to send a shape
* parameter packet
*/
static int need_shape_modifier(struct iforce* iforce, struct ff_effect* effect)
{
int id = effect->id;
struct ff_effect* old = &iforce->core_effects[id].effect;
switch (effect->type) {
case FF_CONSTANT:
if (old->u.constant.shape.attack_length != effect->u.constant.shape.attack_length
|| old->u.constant.shape.attack_level != effect->u.constant.shape.attack_level
|| old->u.constant.shape.fade_length != effect->u.constant.shape.fade_length
|| old->u.constant.shape.fade_level != effect->u.constant.shape.fade_level)
return TRUE;
break;
case FF_PERIODIC:
if (old->u.periodic.shape.attack_length != effect->u.periodic.shape.attack_length
|| old->u.periodic.shape.attack_level != effect->u.periodic.shape.attack_level
|| old->u.periodic.shape.fade_length != effect->u.periodic.shape.fade_length
|| old->u.periodic.shape.fade_level != effect->u.periodic.shape.fade_level)
return TRUE;
break;
default:
printk(KERN_WARNING "iforce.c: bad effect type in need_shape_modifier\n");
}
return FALSE;
}
/*
* Analyse the changes in an effect, and tell if we need to send a periodic
* parameter effect
*/
static int need_period_modifier(struct iforce* iforce, struct ff_effect* new)
{
int id = new->id;
struct ff_effect* old = &iforce->core_effects[id].effect;
if (new->type != FF_PERIODIC) {
printk(KERN_WARNING "iforce.c: bad effect type in need_periodic_modifier\n");
return FALSE;
}
return (old->u.periodic.period != new->u.periodic.period
|| old->u.periodic.magnitude != new->u.periodic.magnitude
|| old->u.periodic.offset != new->u.periodic.offset
|| old->u.periodic.phase != new->u.periodic.phase);
}
/*
* Analyse the changes in an effect, and tell if we need to send an effect
* packet
*/
static int need_core(struct iforce* iforce, struct ff_effect* new)
{
int id = new->id;
struct ff_effect* old = &iforce->core_effects[id].effect;
if (old->direction != new->direction
|| old->trigger.button != new->trigger.button
|| old->trigger.interval != new->trigger.interval
|| old->replay.length != new->replay.length
|| old->replay.delay != new->replay.delay)
return TRUE;
return FALSE;
}
/*
* Send the part common to all effects to the device
*/
static int make_core(struct iforce* iforce, u16 id, u16 mod_id1, u16 mod_id2,
u8 effect_type, u8 axes, u16 duration, u16 delay, u16 button,
u16 interval, u16 direction)
{
unsigned char data[14];
duration = TIME_SCALE(duration);
delay = TIME_SCALE(delay);
interval = TIME_SCALE(interval);
data[0] = LO(id);
data[1] = effect_type;
data[2] = LO(axes) | find_button(iforce, button);
data[3] = LO(duration);
data[4] = HI(duration);
data[5] = HI(direction);
data[6] = LO(interval);
data[7] = HI(interval);
data[8] = LO(mod_id1);
data[9] = HI(mod_id1);
data[10] = LO(mod_id2);
data[11] = HI(mod_id2);
data[12] = LO(delay);
data[13] = HI(delay);
iforce_send_packet(iforce, FF_CMD_EFFECT, data);
return 0;
}
/*
* Upload a periodic effect to the device
* See also iforce_upload_constant.
*/
int iforce_upload_periodic(struct iforce* iforce, struct ff_effect* effect, int is_update)
{
u8 wave_code;
int core_id = effect->id;
struct iforce_core_effect* core_effect = iforce->core_effects + core_id;
struct resource* mod1_chunk = &(iforce->core_effects[core_id].mod1_chunk);
struct resource* mod2_chunk = &(iforce->core_effects[core_id].mod2_chunk);
int err = 1;
if (!is_update || need_period_modifier(iforce, effect)) {
err = make_period_modifier(iforce, mod1_chunk,
is_update,
effect->u.periodic.magnitude, effect->u.periodic.offset,
effect->u.periodic.period, effect->u.periodic.phase);
if (err) return err;
set_bit(FF_MOD1_IS_USED, core_effect->flags);
}
if (!is_update || need_shape_modifier(iforce, effect)) {
err = make_shape_modifier(iforce, mod2_chunk,
is_update,
effect->u.periodic.shape.attack_length,
effect->u.periodic.shape.attack_level,
effect->u.periodic.shape.fade_length,
effect->u.periodic.shape.fade_level);
if (err) return err;
set_bit(FF_MOD2_IS_USED, core_effect->flags);
}
switch (effect->u.periodic.waveform) {
case FF_SQUARE: wave_code = 0x20; break;
case FF_TRIANGLE: wave_code = 0x21; break;
case FF_SINE: wave_code = 0x22; break;
case FF_SAW_UP: wave_code = 0x23; break;
case FF_SAW_DOWN: wave_code = 0x24; break;
default: wave_code = 0x20; break;
}
if (!is_update || need_core(iforce, effect)) {
err = make_core(iforce, effect->id,
mod1_chunk->start,
mod2_chunk->start,
wave_code,
0x20,
effect->replay.length,
effect->replay.delay,
effect->trigger.button,
effect->trigger.interval,
effect->direction);
}
else {
printk(KERN_DEBUG "iforce.c: no effect packet was needed\n");
}
return err;
}
/*
* Upload a constant force effect
* Return value:
* <0 Error code
* 0 Ok, effect created or updated
* 1 effect did not change since last upload, and no packet was therefore sent
*/
int iforce_upload_constant(struct iforce* iforce, struct ff_effect* effect, int is_update)
{
int core_id = effect->id;
struct iforce_core_effect* core_effect = iforce->core_effects + core_id;
struct resource* mod1_chunk = &(iforce->core_effects[core_id].mod1_chunk);
struct resource* mod2_chunk = &(iforce->core_effects[core_id].mod2_chunk);
int ret = 1;
printk(KERN_DEBUG "iforce.c: make constant effect\n");
if (!is_update || need_magnitude_modifier(iforce, effect)) {
ret = make_magnitude_modifier(iforce, mod1_chunk,
is_update,
effect->u.constant.level);
if (ret) return ret;
set_bit(FF_MOD1_IS_USED, core_effect->flags);
}
if (!is_update || need_shape_modifier(iforce, effect)) {
ret = make_shape_modifier(iforce, mod2_chunk,
is_update,
effect->u.constant.shape.attack_length,
effect->u.constant.shape.attack_level,
effect->u.constant.shape.fade_length,
effect->u.constant.shape.fade_level);
if (ret) return ret;
set_bit(FF_MOD2_IS_USED, core_effect->flags);
}
if (!is_update || need_core(iforce, effect)) {
ret = make_core(iforce, effect->id,
mod1_chunk->start,
mod2_chunk->start,
0x00,
0x20,
effect->replay.length,
effect->replay.delay,
effect->trigger.button,
effect->trigger.interval,
effect->direction);
}
else {
printk(KERN_DEBUG "iforce.c: no effect packet was needed\n");
}
return ret;
}
/*
* Upload an interactive effect. Those are for example friction, inertia, springs...
*/
int iforce_upload_interactive(struct iforce* iforce, struct ff_effect* effect, int is_update)
{
int core_id = effect->id;
struct iforce_core_effect* core_effect = iforce->core_effects + core_id;
struct resource* mod_chunk = &(core_effect->mod1_chunk);
u8 type, axes;
u16 mod1, mod2, direction;
int err = 1;
printk(KERN_DEBUG "iforce.c: make interactive effect\n");
switch (effect->type) {
case FF_SPRING: type = 0x40; break;
case FF_FRICTION: type = 0x41; break;
default: return -1;
}
if (!is_update || need_interactive_modifier(iforce, effect)) {
err = make_interactive_modifier(iforce, mod_chunk,
is_update,
effect->u.interactive.right_saturation,
effect->u.interactive.left_saturation,
effect->u.interactive.right_coeff,
effect->u.interactive.left_coeff,
effect->u.interactive.deadband,
effect->u.interactive.center);
if (err) return err;
set_bit(FF_MOD1_IS_USED, core_effect->flags);
}
switch ((test_bit(ABS_X, &effect->u.interactive.axis) ||
test_bit(ABS_WHEEL, &effect->u.interactive.axis)) |
(!!test_bit(ABS_Y, &effect->u.interactive.axis) << 1)) {
case 0: /* Only one axis, choose orientation */
mod1 = mod_chunk->start;
mod2 = 0xffff;
direction = effect->direction;
axes = 0x20;
break;
case 1: /* Only X axis */
mod1 = mod_chunk->start;
mod2 = 0xffff;
direction = 0x5a00;
axes = 0x40;
break;
case 2: /* Only Y axis */
mod1 = 0xffff;
mod2 = mod_chunk->start;
direction = 0xb400;
axes = 0x80;
break;
case 3: /* Both X and Y axes */
/* TODO: same setting for both axes is not mandatory */
mod1 = mod_chunk->start;
mod2 = mod_chunk->start;
direction = 0x6000;
axes = 0xc0;
break;
default:
return -1;
}
if (!is_update || need_core(iforce, effect)) {
err = make_core(iforce, effect->id,
mod1, mod2,
type, axes,
effect->replay.length, effect->replay.delay,
effect->trigger.button, effect->trigger.interval,
direction);
}
return err;
}
--- NEW FILE: iforce-main.c ---
/*
* $Id: iforce-main.c,v 1.1.2.1 2001/10/07 17:06:49 jdeneux Exp $
*
* Copyright (c) 2000-2001 Vojtech Pavlik <vo...@uc...>
* Copyright (c) 2001 Johann Deneux <de...@if...>
*
* USB/RS232 I-Force joysticks and wheels.
*/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* 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
*/
#include "iforce.h"
#include "usbpath.h"
MODULE_AUTHOR("Vojtech Pavlik <vo...@uc...>, Johann Deneux <de...@if...>");
MODULE_DESCRIPTION("USB/RS232 I-Force joysticks and wheels driver");
MODULE_LICENSE("GPL");
static signed short btn_joystick[] = { BTN_TRIGGER, BTN_TOP, BTN_THUMB, BTN_TOP2, BTN_BASE,
BTN_BASE2, BTN_BASE3, BTN_BASE4, BTN_BASE5, BTN_A, BTN_B, BTN_C, BTN_DEAD, -1 };
static signed short btn_wheel[] = { BTN_TRIGGER, BTN_TOP, BTN_THUMB, BTN_TOP2, BTN_BASE,
BTN_BASE2, BTN_BASE3, BTN_BASE4, BTN_BASE5, BTN_A, BTN_B, BTN_C, -1 };
static signed short btn_avb_tw[] = { BTN_TRIGGER, BTN_THUMB, BTN_TOP, BTN_TOP2, BTN_BASE,
BTN_BASE2, BTN_BASE3, BTN_BASE4, -1 };
static signed short abs_joystick[] = { ABS_X, ABS_Y, ABS_THROTTLE, ABS_HAT0X, ABS_HAT0Y, -1 };
static signed short abs_joystick2[] = { ABS_X, ABS_Y, ABS_THROTTLE, ABS_RUDDER, ABS_HAT0X, ABS_HAT0Y, -1 };
static signed short abs_wheel[] = { ABS_WHEEL, ABS_GAS, ABS_BRAKE, ABS_HAT0X, ABS_HAT0Y, -1 };
static signed short ff_iforce[] = { FF_PERIODIC, FF_CONSTANT, FF_SPRING, FF_FRICTION,
FF_SQUARE, FF_TRIANGLE, FF_SINE, FF_SAW_UP, FF_SAW_DOWN, FF_GAIN, FF_AUTOCENTER, -1 };
static struct iforce_device iforce_device[] = {
{ 0x044f, 0xa01c, "Thrustmaster Motor Sport GT", btn_wheel, abs_wheel, ff_iforce },
{ 0x046d, 0xc281, "Logitech WingMan Force", btn_joystick, abs_joystick, ff_iforce },
{ 0x046d, 0xc291, "Logitech WingMan Formula Force", btn_wheel, abs_wheel, ff_iforce },
{ 0x05ef, 0x020a, "AVB Top Shot Pegasus", btn_joystick, abs_joystick2, ff_iforce },
{ 0x05ef, 0x8884, "AVB Mag Turbo Force", btn_wheel, abs_wheel, ff_iforce },
{ 0x05ef, 0x8888, "AVB Top Shot Force Feedback Racing Wheel", btn_avb_tw, abs_wheel, ff_iforce },
{ 0x06f8, 0x0001, "Guillemot Race Leader Force Feedback", btn_wheel, abs_wheel, ff_iforce },
{ 0x0000, 0x0000, "Unknown I-Force Device [%04x:%04x]", btn_joystick, abs_joystick, ff_iforce }
};
static int iforce_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
{
struct iforce* iforce = (struct iforce*)(dev->private);
unsigned char data[3];
printk(KERN_DEBUG "iforce.c: input_event(type = %d, code = %d, value = %d)\n", type, code, value);
if (type != EV_FF)
return -1;
switch (code) {
case FF_GAIN:
data[0] = value >> 9;
iforce_send_packet(iforce, FF_CMD_GAIN, data);
return 0;
case FF_AUTOCENTER:
data[0] = 0x03;
data[1] = value >> 9;
iforce_send_packet(iforce, FF_CMD_AUTOCENTER, data);
data[0] = 0x04;
data[1] = 0x01;
iforce_send_packet(iforce, FF_CMD_AUTOCENTER, data);
return 0;
default: /* Play or stop an effect */
if (!CHECK_OWNERSHIP(code, iforce)) {
return -1;
}
if (value > 0) {
set_bit(FF_CORE_SHOULD_PLAY, iforce->core_effects[code].flags);
}
else {
clear_bit(FF_CORE_SHOULD_PLAY, iforce->core_effects[code].flags);
}
data[0] = LO(code);
data[1] = (value > 0) ? ((value > 1) ? 0x41 : 0x01) : 0;
data[2] = LO(value);
iforce_send_packet(iforce, FF_CMD_PLAY, data);
return 0;
}
return -1;
}
/*
* Function called when an ioctl is performed on the event dev entry.
* It uploads an effect to the device
*/
static int iforce_upload_effect(struct input_dev *dev, struct ff_effect *effect)
{
struct iforce* iforce = (struct iforce*)(dev->private);
int id;
int ret;
int is_update;
printk(KERN_DEBUG "iforce.c: upload effect\n");
/*
* If we want to create a new effect, get a free id
*/
if (effect->id == -1) {
for (id=0; id < FF_EFFECTS_MAX; ++id)
if (!test_and_set_bit(FF_CORE_IS_USED, iforce->core_effects[id].flags)) break;
if ( id == FF_EFFECTS_MAX || id >= iforce->dev.ff_effects_max)
return -ENOMEM;
effect->id = id;
iforce->core_effects[id].owner = current->pid;
iforce->core_effects[id].flags[0] = (1<<FF_CORE_IS_USED); /* Only IS_USED bit must be set */
is_update = FALSE;
}
else {
/* We want to update an effect */
if (!CHECK_OWNERSHIP(effect->id, iforce)) return -EACCES;
/* Parameter type cannot be updated */
if (effect->type != iforce->core_effects[effect->id].effect.type)
return -EINVAL;
/* Check the effect is not already being updated */
if (test_bit(FF_CORE_UPDATE, iforce->core_effects[effect->id].flags)) {
printk(KERN_DEBUG "iforce.c: update too frequent refused\n");
return -EAGAIN;
}
is_update = TRUE;
}
/*
* Upload the effect
*/
switch (effect->type) {
case FF_PERIODIC:
ret = iforce_upload_periodic(iforce, effect, is_update);
break;
case FF_CONSTANT:
ret = iforce_upload_constant(iforce, effect, is_update);
break;
case FF_SPRING:
case FF_FRICTION:
ret = iforce_upload_interactive(iforce, effect, is_update);
break;
default:
return -EINVAL;
}
if (ret == 0) {
/* A packet was sent, forbid new updates until we are notified
* that the packet was updated
*/
set_bit(FF_CORE_UPDATE, iforce->core_effects[effect->id].flags);
}
iforce->core_effects[effect->id].effect = *effect;
return ret;
}
/*
* Erases an effect: it frees the effect id and mark as unused the memory
* allocated for the parameters
*/
static int iforce_erase_effect(struct input_dev *dev, int effect_id)
{
struct iforce* iforce = (struct iforce*)(dev->private);
int err = 0;
struct iforce_core_effect* core_effect;
/* Check who is trying to erase this effect */
if (iforce->core_effects[effect_id].owner != current->pid) {
printk(KERN_WARNING "iforce.c: %d tried to erase an effect belonging to %d\n", current->pid, iforce->core_effects[effect_id].owner);
return -EACCES;
}
printk(KERN_DEBUG "iforce.c: erase effect %d\n", effect_id);
if (effect_id < 0 || effect_id >= FF_EFFECTS_MAX)
return -EINVAL;
core_effect = iforce->core_effects + effect_id;
if (test_bit(FF_MOD1_IS_USED, core_effect->flags))
err = release_resource(&(iforce->core_effects[effect_id].mod1_chunk));
if (!err && test_bit(FF_MOD2_IS_USED, core_effect->flags))
err = release_resource(&(iforce->core_effects[effect_id].mod2_chunk));
/*TODO: remember to change that if more FF_MOD* bits are added */
core_effect->flags[0] = 0;
return err;
}
static int iforce_open(struct input_dev *dev)
{
struct iforce *iforce = dev->private;
switch (iforce->bus) {
#ifdef IFORCE_USB
case IFORCE_USB:
if (iforce->open++)
break;
iforce->irq.dev = iforce->usbdev;
if (usb_submit_urb(&iforce->irq))
return -EIO;
break;
#endif
}
/* Reset device */
iforce_send_packet(iforce, FF_CMD_ENABLE, "\004");
return 0;
}
static int iforce_flush(struct input_dev *dev, struct file *file)
{
struct iforce *iforce = dev->private;
int i;
/* Erase all effects this process owns */
for (i=0; i<dev->ff_effects_max; ++i) {
if (test_bit(FF_CORE_IS_USED, iforce->core_effects[i].flags) &&
current->pid == iforce->core_effects[i].owner) {
/* Stop effect */
iforce_input_event(dev, EV_FF, i, 0);
/* Free ressources assigned to effect */
if (iforce_erase_effect(dev, i)) {
printk(KERN_WARNING "iforce_flush: (%s) erase effect %d failed\n", dev->phys, i);
}
}
}
return 0;
}
static void iforce_close(struct input_dev *dev)
{
struct iforce *iforce = dev->private;
printk(KERN_DEBUG "iforce.c: in iforce_close\n");
/* Disable force feedback playback */
iforce_send_packet(iforce, FF_CMD_ENABLE, "\001");
switch (iforce->bus) {
#ifdef IFORCE_USB
case IFORCE_USB:
if (!--iforce->open)
usb_unlink_urb(&iforce->irq);
break;
#endif
}
}
int iforce_init_device(struct iforce *iforce)
{
unsigned char c[] = "CEOV";
char path[64];
int i;
init_waitqueue_head(&iforce->wait);
spin_lock_init(&iforce->xmit_lock);
init_MUTEX(&iforce->mem_mutex);
iforce->xmit.buf = iforce->xmit_data;
iforce->dev.ff_effects_max = 10;
switch (iforce->bus) {
#ifdef IFORCE_232
case IFORCE_232:
strcpy(path, iforce->serio->phys);
break;
#endif
#ifdef IFORCE_USB
case IFORCE_USB:
usb_make_path(iforce->usbdev, path, 64);
break;
#endif
}
sprintf(iforce->phys, "%s/input0", path);
/*
* Input device fields.
*/
iforce->dev.idbus = BUS_USB;
iforce->dev.private = iforce;
iforce->dev.name = iforce->name;
iforce->dev.name = iforce->phys;
iforce->dev.open = iforce_open;
iforce->dev.close = iforce_close;
iforce->dev.flush = iforce_flush;
iforce->dev.event = iforce_input_event;
iforce->dev.upload_effect = iforce_upload_effect;
iforce->dev.erase_effect = iforce_erase_effect;
/*
* On-device memory allocation.
*/
iforce->device_memory.name = "I-Force device effect memory";
iforce->device_memory.start = 0;
iforce->device_memory.end = 200;
iforce->device_memory.flags = IORESOURCE_MEM;
iforce->device_memory.parent = NULL;
iforce->device_memory.child = NULL;
iforce->device_memory.sibling = NULL;
/*
* Wait until device ready - until it sends its first response.
*/
for (i = 0; i < 20; i++)
if (!iforce_get_id_packet(iforce, "O"))
break;
if (i == 20) { /* 5 seconds */
printk(KERN_ERR "iforce.c: Timeout waiting for response from device.\n");
iforce_close(&iforce->dev);
return -1;
}
/*
* Get device info.
*/
if (!iforce_get_id_packet(iforce, "M"))
iforce->dev.idvendor = (iforce->edata[2] << 8) | iforce->edata[1];
if (!iforce_get_id_packet(iforce, "P"))
iforce->dev.idproduct = (iforce->edata[2] << 8) | iforce->edata[1];
if (!iforce_get_id_packet(iforce, "B"))
iforce->device_memory.end = (iforce->edata[2] << 8) | iforce->edata[1];
if (!iforce_get_id_packet(iforce, "N"))
iforce->dev.ff_effects_max = iforce->edata[1];
/* Check if the device can store more effects than the driver can really handle */
if (iforce->dev.ff_effects_max > FF_EFFECTS_MAX) {
printk(KERN_WARNING "input??: Device can handle %d effects, but N_EFFECTS_MAX is set to %d in iforce.c\n",
iforce->dev.ff_effects_max, FF_EFFECTS_MAX);
iforce->dev.ff_effects_max = FF_EFFECTS_MAX;
}
/*
* Display additional info.
*/
for (i = 0; c[i]; i++)
if (!iforce_get_id_packet(iforce, c + i))
iforce_dump_packet("info", iforce->ecmd, iforce->edata);
/*
* Disable spring, enable force feedback.
* FIXME: We should use iforce_set_autocenter() et al here.
*/
iforce_send_packet(iforce, FF_CMD_AUTOCENTER, "\004\000");
/*
* Find appropriate device entry
*/
for (i = 0; iforce_device[i].idvendor; i++)
if (iforce_device[i].idvendor == iforce->dev.idvendor &&
iforce_device[i].idproduct == iforce->dev.idproduct)
break;
iforce->type = iforce_device + i;
sprintf(iforce->name, iforce->type->name,
iforce->dev.idproduct, iforce->dev.idvendor);
/*
* Set input device bitfields and ranges.
*/
iforce->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_FF) | BIT(EV_FF_STATUS);
for (i = 0; iforce->type->btn[i] >= 0; i++) {
signed short t = iforce->type->btn[i];
set_bit(t, iforce->dev.keybit);
if (t != BTN_DEAD)
set_bit(FF_BTN(t), iforce->dev.ffbit);
}
for (i = 0; iforce->type->abs[i] >= 0; i++) {
signed short t = iforce->type->abs[i];
set_bit(t, iforce->dev.absbit);
switch (t) {
case ABS_X:
case ABS_Y:
case ABS_WHEEL:
iforce->dev.absmax[t] = 1920;
iforce->dev.absmin[t] = -1920;
iforce->dev.absflat[t] = 128;
iforce->dev.absfuzz[t] = 16;
set_bit(FF_ABS(t), iforce->dev.ffbit);
break;
case ABS_THROTTLE:
case ABS_GAS:
case ABS_BRAKE:
iforce->dev.absmax[t] = 255;
iforce->dev.absmin[t] = 0;
break;
case ABS_RUDDER:
iforce->dev.absmax[t] = 127;
iforce->dev.absmin[t] = -128;
break;
case ABS_HAT0X:
case ABS_HAT0Y:
iforce->dev.absmax[t] = 1;
iforce->dev.absmin[t] = -1;
break;
}
}
for (i = 0; iforce->type->ff[i] >= 0; i++)
set_bit(iforce->type->ff[i], iforce->dev.ffbit);
/*
* Register input device.
*/
input_register_device(&iforce->dev);
printk(KERN_INFO "input: %s [%d effects, %ld bytes memory] on %s\n",
iforce->dev.name, iforce->dev.ff_effects_max,
iforce->device_memory.end, path);
return 0;
}
static int __init iforce_init(void)
{
#ifdef IFORCE_USB
usb_register(&iforce_usb_driver);
#endif
#ifdef IFORCE_232
serio_register_device(&iforce_serio_dev);
#endif
return 0;
}
static void __exit iforce_exit(void)
{
#ifdef IFORCE_USB
usb_deregister(&iforce_usb_driver);
#endif
#ifdef IFORCE_232
serio_unregister_device(&iforce_serio_dev);
#endif
}
module_init(iforce_init);
module_exit(iforce_exit);
--- NEW FILE: iforce-packets.c ---
/*
* $Id: iforce-packets.c,v 1.1.2.1 2001/10/07 17:06:49 jdeneux Exp $
*
* Copyright (c) 2000-2001 Vojtech Pavlik <vo...@uc...>
* Copyright (c) 2001 Johann Deneux <de...@if...>
*
* USB/RS232 I-Force joysticks and wheels.
*/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* 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
*/
#include "iforce.h"
static struct {
__s32 x;
__s32 y;
} iforce_hat_to_axis[16] = {{ 0,-1}, { 1,-1}, { 1, 0}, { 1, 1}, { 0, 1}, {-1, 1}, {-1, 0}, {-1,-1}};
void iforce_dump_packet(char *msg, u16 cmd, unsigned char *data)
{
int i;
printk(KERN_DEBUG "iforce.c: %s ( cmd = %04x, data = ", msg, cmd);
for (i = 0; i < LO(cmd); i++)
printk("%02x ", data[i]);
printk(")\n");
}
/*
* Send a packet of bytes to the device
*/
int iforce_send_packet(struct iforce *iforce, u16 cmd, unsigned char* data)
{
/* Copy data to buffer */
int n = LO(cmd);
int c;
int empty;
int head, tail;
unsigned long flags;
/*
* Update head and tail of xmit buffer
*/
spin_lock_irqsave(&iforce->xmit_lock, flags);
head = iforce->xmit.head;
tail = iforce->xmit.tail;
if (CIRC_SPACE(head, tail, XMIT_SIZE) < n+2) {
printk(KERN_WARNING "iforce.c: not enough space in xmit buffer to send new packet\n");
spin_unlock_irqrestore(&iforce->xmit_lock, flags);
return -1;
}
empty = head == tail;
XMIT_INC(iforce->xmit.head, n+2);
/*
* Store packet in xmit buffer
*/
iforce->xmit.buf[head] = HI(cmd);
XMIT_INC(head, 1);
iforce->xmit.buf[head] = LO(cmd);
XMIT_INC(head, 1);
c = CIRC_SPACE_TO_END(head, tail, XMIT_SIZE);
if (n < c) c=n;
memcpy(&iforce->xmit.buf[head],
data,
c);
if (n != c) {
memcpy(&iforce->xmit.buf[0],
data + c,
n - c);
}
XMIT_INC(head, n);
spin_unlock_irqrestore(&iforce->xmit_lock, flags);
/*
* If necessary, start the transmission
*/
switch (iforce->bus) {
#ifdef IFORCE_232
case IFORCE_232:
if (empty)
iforce_serial_xmit(iforce);
break;
#endif
#ifdef IFORCE_USB
case IFORCE_USB:
if (empty & !iforce->out.status) {
iforce_usb_xmit(iforce);
}
break;
#endif
}
return 0;
}
/* Mark an effect that was being updated as ready. That means it can be updated
* again */
static int mark_core_as_ready(struct iforce *iforce, unsigned short addr)
{
int i;
for (i=0; i<iforce->dev.ff_effects_max; ++i) {
if (test_bit(FF_CORE_IS_USED, iforce->core_effects[i].flags) &&
(iforce->core_effects[i].mod1_chunk.start == addr ||
iforce->core_effects[i].mod2_chunk.start == addr)) {
clear_bit(FF_CORE_UPDATE, iforce->core_effects[i].flags);
printk(KERN_DEBUG "iforce.c: marked effect %d as ready\n", i);
return 0;
}
}
printk(KERN_DEBUG "iforce.c: unused effect %04x updated !!!\n", addr);
return -1;
}
void iforce_process_packet(struct iforce *iforce, u16 cmd, unsigned char *data)
{
struct input_dev *dev = &iforce->dev;
int i;
static int being_used = 0;
if (being_used)
printk(KERN_WARNING "iforce.c: re-entrant call to iforce_process %d\n", being_used);
being_used++;
#ifdef IFORCE_232
if (HI(iforce->expect_packet) == HI(cmd)) {
iforce->expect_packet = 0;
iforce->ecmd = cmd;
memcpy(iforce->edata, data, IFORCE_MAX_LENGTH);
if (waitqueue_active(&iforce->wait))
wake_up(&iforce->wait);
}
#endif
if (!iforce->type) {
being_used--;
return;
}
switch (HI(cmd)) {
case 0x01: /* joystick position data */
case 0x03: /* wheel position data */
if (HI(cmd) == 1) {
input_report_abs(dev, ABS_X, (__s16) (((__s16)data[1] << 8) | data[0]));
input_report_abs(dev, ABS_Y, (__s16) (((__s16)data[3] << 8) | data[2]));
input_report_abs(dev, ABS_THROTTLE, 255 - data[4]);
if (LO(cmd) >= 8 && test_bit(ABS_RUDDER ,dev->absbit))
input_report_abs(dev, ABS_RUDDER, (__s8)data[7]);
} else {
input_report_abs(dev, ABS_WHEEL, (__s16) (((__s16)data[1] << 8) | data[0]));
input_report_abs(dev, ABS_GAS, 255 - data[2]);
input_report_abs(dev, ABS_BRAKE, 255 - data[3]);
}
input_report_abs(dev, ABS_HAT0X, iforce_hat_to_axis[data[6] >> 4].x);
input_report_abs(dev, ABS_HAT0Y, iforce_hat_to_axis[data[6] >> 4].y);
for (i = 0; iforce->type->btn[i] >= 0; i++)
input_report_key(dev, iforce->type->btn[i], data[(i >> 3) + 5] & (1 << (i & 7)));
break;
case 0x02: /* status report */
input_report_key(dev, BTN_DEAD, data[0] & 0x02);
/* Check if an effect was just started or stopped */
i = data[1] & 0x7f;
if (data[1] & 0x80) {
if (!test_and_set_bit(FF_CORE_IS_PLAYED, iforce->core_effects[i].flags)) {
/* Report play event */
input_report_ff_status(dev, i, FF_STATUS_PLAYING);
printk(KERN_DEBUG "iforce.c: effect %d started to play\n", i);
}
}
else {
if (!test_bit(FF_CORE_SHOULD_PLAY, iforce->core_effects[i].flags)) {
if (test_and_clear_bit(FF_CORE_IS_PLAYED, iforce->core_effects[i].flags)) {
/* Report stop event */
input_report_ff_status(dev, i, FF_STATUS_STOPPED);
printk(KERN_DEBUG "iforce.c: effect %d stopped to play\n", i);
}
}
else {
printk(KERN_WARNING "iforce.c: effect %d stopped, while it should not\nStarting again\n", i);
}
}
if (LO(cmd) > 3) {
int j;
for (j=3; j<LO(cmd); j+=2) {
if (mark_core_as_ready(iforce, data[j] | (data[j+1]<<8)))
iforce_dump_packet("ff status", cmd, data);
}
}
break;
}
being_used--;
}
int iforce_get_id_packet(struct iforce *iforce, char *packet)
{
DECLARE_WAITQUEUE(wait, current);
int timeout = HZ; /* 1 second */
switch (iforce->bus) {
#ifdef IFORCE_USB
case IFORCE_USB:
iforce->dr.request = packet[0];
iforce->ctrl.dev = iforce->usbdev;
set_current_state(TASK_INTERRUPTIBLE);
add_wait_queue(&iforce->wait, &wait);
if (usb_submit_urb(&iforce->ctrl)) {
set_current_state(TASK_RUNNING);
remove_wait_queue(&iforce->wait, &wait);
return -1;
}
while (timeout && iforce->ctrl.status == -EINPROGRESS)
timeout = schedule_timeout(timeout);
set_current_state(TASK_RUNNING);
remove_wait_queue(&iforce->wait, &wait);
if (!timeout) {
usb_unlink_urb(&iforce->ctrl);
return -1;
}
break;
#endif
#ifdef IFORCE_232
case IFORCE_232:
iforce->expect_packet = FF_CMD_QUERY;
iforce_send_packet(iforce, FF_CMD_QUERY, packet);
set_current_state(TASK_INTERRUPTIBLE);
add_wait_queue(&iforce->wait, &wait);
while (timeout && iforce->expect_packet)
timeout = schedule_timeout(timeout);
set_current_state(TASK_RUNNING);
remove_wait_queue(&iforce->wait, &wait);
if (!timeout) {
iforce->expect_packet = 0;
return -1;
}
break;
#endif
}
return -(iforce->edata[0] != packet[0]);
}
--- NEW FILE: iforce-serio.c ---
/*
* $Id: iforce-serio.c,v 1.1.2.1 2001/10/07 17:06:49 jdeneux Exp $
*
* Copyright (c) 2000-2001 Vojtech Pavlik <vo...@uc...>
* Copyright (c) 2001 Johann Deneux <de...@if...>
*
* USB/RS232 I-Force joysticks and wheels.
*/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* 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
*/
#include "iforce.h"
void iforce_serial_xmit(struct iforce *iforce)
{
unsigned char cs;
int i;
unsigned long flags;
if (test_and_set_bit(IFORCE_XMIT_RUNNING, iforce->xmit_flags)) {
set_bit(IFORCE_XMIT_AGAIN, iforce->xmit_flags);
return;
}
spin_lock_irqsave(&iforce->xmit_lock, flags);
again:
if (iforce->xmit.head == iforce->xmit.tail) {
clear_bit(IFORCE_XMIT_RUNNING, iforce->xmit_flags);
spin_unlock_irqrestore(&iforce->xmit_lock, flags);
return;
}
cs = 0x2b;
serio_write(iforce->serio, 0x2b);
serio_write(iforce->serio, iforce->xmit.buf[iforce->xmit.tail]);
cs ^= iforce->xmit.buf[iforce->xmit.tail];
XMIT_INC(iforce->xmit.tail, 1);
for (i=iforce->xmit.buf[iforce->xmit.tail]; i >= 0; --i) {
serio_write(iforce->serio, iforce->xmit.buf[iforce->xmit.tail]);
cs ^= iforce->xmit.buf[iforce->xmit.tail];
XMIT_INC(iforce->xmit.tail, 1);
}
serio_write(iforce->serio, cs);
if (test_and_clear_bit(IFORCE_XMIT_AGAIN, iforce->xmit_flags))
goto again;
clear_bit(IFORCE_XMIT_RUNNING, iforce->xmit_flags);
spin_unlock_irqrestore(&iforce->xmit_lock, flags);
}
static void iforce_serio_write_wakeup(struct serio *serio)
{
iforce_serial_xmit((struct iforce *)serio->private);
}
static void iforce_serio_irq(struct serio *serio, unsigned char data, unsigned int flags)
{
struct iforce* iforce = serio->private;
if (!iforce->pkt) {
if (data != 0x2b) {
return;
}
iforce->pkt = 1;
return;
}
if (!iforce->id) {
if (data > 3 && data != 0xff) {
iforce->pkt = 0;
return;
}
iforce->id = data;
return;
}
if (!iforce->len) {
if (data > IFORCE_MAX_LENGTH) {
iforce->pkt = 0;
iforce->id = 0;
return;
}
iforce->len = data;
return;
}
if (iforce->idx < iforce->len) {
iforce->csum += iforce->data[iforce->idx++] = data;
return;
}
if (iforce->idx == iforce->len) {
iforce_process_packet(iforce, (iforce->id << 8) | iforce->idx, iforce->data);
iforce->pkt = 0;
iforce->id = 0;
iforce->len = 0;
iforce->idx = 0;
iforce->csum = 0;
}
}
static void iforce_serio_connect(struct serio *serio, struct serio_dev *dev)
{
struct iforce *iforce;
if (serio->type != (SERIO_RS232 | SERIO_IFORCE))
return;
if (!(iforce = kmalloc(sizeof(struct iforce), GFP_KERNEL))) return;
memset(iforce, 0, sizeof(struct iforce));
iforce->bus = IFORCE_232;
iforce->serio = serio;
serio->private = iforce;
if (serio_open(serio, dev)) {
kfree(iforce);
return;
}
if (iforce_init_device(iforce)) {
serio_close(serio);
kfree(iforce);
return;
}
}
static void iforce_serio_disconnect(struct serio *serio)
{
struct iforce* iforce = serio->private;
input_unregister_device(&iforce->dev);
serio_close(serio);
kfree(iforce);
}
struct serio_dev iforce_serio_dev = {
write_wakeup: iforce_serio_write_wakeup,
interrupt: iforce_serio_irq,
connect: iforce_serio_connect,
disconnect: iforce_serio_disconnect,
};
--- NEW FILE: iforce-usb.c ---
/*
* $Id: iforce-usb.c,v 1.1.2.1 2001/10/07 17:06:49 jdeneux Exp $
*
* Copyright (c) 2000-2001 Vojtech Pavlik <vo...@uc...>
* Copyright (c) 2001 Johann Deneux <de...@if...>
*
* USB/RS232 I-Force joysticks and wheels.
*/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* 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
*/
#include "iforce.h"
void iforce_usb_xmit(struct iforce *iforce)
{
int n, c;
unsigned long flags;
spin_lock_irqsave(&iforce->xmit_lock, flags);
if (iforce->xmit.head == iforce->xmit.tail) {
spin_unlock_irqrestore(&iforce->xmit_lock, flags);
return;
}
((char *)iforce->out.transfer_buffer)[0] = iforce->xmit.buf[iforce->xmit.tail];
XMIT_INC(iforce->xmit.tail, 1);
n = iforce->xmit.buf[iforce->xmit.tail];
XMIT_INC(iforce->xmit.tail, 1);
iforce->out.transfer_buffer_length = n + 2;
iforce->out.dev = iforce->usbdev;
/* Copy rest of data then */
c = CIRC_CNT_TO_END(iforce->xmit.head, iforce->xmit.tail, XMIT_SIZE);
if (n < c) c=n;
memcpy(iforce->out.transfer_buffer + 1,
&iforce->xmit.buf[iforce->xmit.tail],
c);
if (n != c) {
memcpy(iforce->out.transfer_buffer + 1 + c,
&iforce->xmit.buf[0],
n-c);
}
XMIT_INC(iforce->xmit.tail, n);
if ( (n=usb_submit_urb(&iforce->out)) ) {
printk(KERN_WARNING "iforce.c: iforce_usb_xmit: usb_submit_urb failed %d\n", n);
}
spin_unlock_irqrestore(&iforce->xmit_lock, flags);
}
static void iforce_usb_irq(struct urb *urb)
{
struct iforce *iforce = urb->context;
if (urb->status) return;
iforce_process_packet(iforce,
(iforce->data[0] << 8) | (urb->actual_length - 1), iforce->data + 1);
}
static void iforce_usb_out(struct urb *urb)
{
struct iforce *iforce = urb->context;
if (urb->status) return;
iforce_usb_xmit(iforce);
if (waitqueue_active(&iforce->wait))
wake_up(&iforce->wait);
}
static void iforce_usb_ctrl(struct urb *urb)
{
struct iforce *iforce = urb->context;
if (urb->status) return;
iforce->ecmd = 0xff00 | urb->actual_length;
if (waitqueue_active(&iforce->wait))
wake_up(&iforce->wait);
}
static void *iforce_usb_probe(struct usb_device *dev, unsigned int ifnum,
const struct usb_device_id *id)
{
struct usb_endpoint_descriptor *epirq, *epout;
struct iforce *iforce;
epirq = dev->config[0].interface[ifnum].altsetting[0].endpoint + 0;
epout = dev->config[0].interface[ifnum].altsetting[0].endpoint + 1;
if (!(iforce = kmalloc(sizeof(struct iforce) + 32, GFP_KERNEL))) return NULL;
memset(iforce, 0, sizeof(struct iforce));
iforce->bus = IFORCE_USB;
iforce->usbdev = dev;
iforce->dr.requesttype = USB_TYPE_VENDOR | USB_DIR_IN | USB_RECIP_INTERFACE;
iforce->dr.index = 0;
iforce->dr.length = 16;
FILL_INT_URB(&iforce->irq, dev, usb_rcvintpipe(dev, epirq->bEndpointAddress),
iforce->data, 16, iforce_usb_irq, iforce, epirq->bInterval);
FILL_BULK_URB(&iforce->out, dev, usb_sndbulkpipe(dev, epout->bEndpointAddress),
iforce + 1, 32, iforce_usb_out, iforce);
FILL_CONTROL_URB(&iforce->ctrl, dev, usb_rcvctrlpipe(dev, 0),
(void*) &iforce->dr, iforce->edata, 16, iforce_usb_ctrl, iforce);
if (iforce_init_device(iforce)) {
kfree(iforce);
return NULL;
}
return iforce;
}
static void iforce_usb_disconnect(struct usb_device *dev, void *ptr)
{
struct iforce *iforce = ptr;
usb_unlink_urb(&iforce->irq);
input_unregister_device(&iforce->dev);
kfree(iforce);
}
static struct usb_device_id iforce_usb_ids [] = {
{ USB_DEVICE(0x044f, 0xa01c) }, /* Thrustmaster Motor Sport GT */
{ USB_DEVICE(0x046d, 0xc281) }, /* Logitech WingMan Force */
{ USB_DEVICE(0x046d, 0xc291) }, /* Logitech WingMan Formula Force */
{ USB_DEVICE(0x05ef, 0x020a) }, /* AVB Top Shot Pegasus */
{ USB_DEVICE(0x05ef, 0x8884) }, /* AVB Mag Turbo Force */
{ USB_DEVICE(0x05ef, 0x8888) }, /* AVB Top Shot FFB Racing Wheel */
{ USB_DEVICE(0x06f8, 0x0001) }, /* Guillemot Race Leader Force Feedback */
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE (usb, iforce_usb_ids);
struct usb_driver iforce_usb_driver = {
name: "iforce",
probe: iforce_usb_probe,
disconnect: iforce_usb_disconnect,
id_table: iforce_usb_ids,
};
--- NEW FILE: iforce.h ---
/*
* $Id: iforce.h,v 1.1.2.1 2001/10/07 17:06:49 jdeneux Exp $
*
* Copyright (c) 2000-2001 Vojtech Pavlik <vo...@uc...>
* Copyright (c) 2001 Johann Deneux <de...@if...>
*
* USB/RS232 I-Force joysticks and wheels.
*/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* 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
*/
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/input.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/spinlock.h>
#include <linux/usb.h>
#include <linux/serio.h>
#include <linux/config.h>
#include <linux/circ_buf.h>
#include <asm/semaphore.h>
/* FF: This module provides arbitrary resource management routines.
* I use it to manage the device's memory.
* Despite the name of this module, I am *not* going to access the ioports.
*/
#include <linux/ioport.h>
#define IFORCE_MAX_LENGTH 16
#if defined(CONFIG_INPUT_IFORCE_232) || defined(CONFIG_INPUT_IFORCE_232_MODULE)
#define IFORCE_232 1
#endif
#if defined(CONFIG_INPUT_IFORCE_USB) || defined(CONFIG_INPUT_IFORCE_USB_MODULE)
#define IFORCE_USB 2
#endif
#define FALSE 0
#define TRUE 1
#define FF_EFFECTS_MAX 32
/* Each force feedback effect is made of one core effect, which can be
* associated to at most to effect modifiers
*/
#define FF_MOD1_IS_USED 0
#define FF_MOD2_IS_USED 1
#define FF_CORE_IS_USED 2
#define FF_CORE_IS_PLAYED 3 /* Effect is actually being played */
#define FF_CORE_SHOULD_PLAY 4 /* User wants the effect to be played */
#define FF_CORE_UPDATE 5 /* Effect is being updated */
#define FF_MODCORE_MAX 5
#define CHECK_OWNERSHIP(i, iforce) \
((i) < FF_EFFECTS_MAX && i >= 0 && \
test_bit(FF_CORE_IS_USED, (iforce)->core_effects[(i)].flags) && \
(current->pid == 0 || \
(iforce)->core_effects[(i)].owner == current->pid))
struct iforce_core_effect {
/* Information about where modifiers are stored in the device's memory */
struct resource mod1_chunk;
struct resource mod2_chunk;
unsigned long flags[NBITS(FF_MODCORE_MAX)];
pid_t owner;
/* Used to keep track of parameters of an effect. They are needed
* to know what parts of an effect changed in an update operation.
* We try to send only parameter packets if possible, as sending
* effect parameter requires the effect to be stoped and restarted
*/
struct ff_effect effect;
};
#define FF_CMD_EFFECT 0x010e
#define FF_CMD_SHAPE 0x0208
#define FF_CMD_MAGNITUDE 0x0303
#define FF_CMD_PERIOD 0x0407
#define FF_CMD_INTERACT 0x050a
#define FF_CMD_AUTOCENTER 0x4002
#define FF_CMD_PLAY 0x4103
#define FF_CMD_ENABLE 0x4201
#define FF_CMD_GAIN 0x4301
#define FF_CMD_QUERY 0xff01
/* Buffer for async write */
#define XMIT_SIZE 256
#define XMIT_INC(var, n) (var)+=n; (var)&= XMIT_SIZE -1
/* iforce::xmit_flags */
#define IFORCE_XMIT_RUNNING 0
#define IFORCE_XMIT_AGAIN 1
struct iforce_device {
u16 idvendor;
u16 idproduct;
char *name;
signed short *btn;
signed short *abs;
signed short *ff;
};
struct iforce {
struct input_dev dev; /* Input device interface */
struct iforce_device *type;
char name[64];
char phys[64];
int open;
int bus;
unsigned char data[IFORCE_MAX_LENGTH];
unsigned char edata[IFORCE_MAX_LENGTH];
u16 ecmd;
u16 expect_packet;
#ifdef IFORCE_232
struct serio *serio; /* RS232 transfer */
int idx, pkt, len, id;
unsigned char csum;
#endif
#ifdef IFORCE_USB
struct usb_device *usbdev; /* USB transfer */
struct urb irq, out, ctrl;
devrequest dr;
#endif
spinlock_t xmit_lock;
/* Buffer used for asynchronous sending of bytes to the device */
struct circ_buf xmit;
unsigned char xmit_data[XMIT_SIZE];
long xmit_flags[1];
/* Force Feedback */
wait_queue_head_t wait;
struct resource device_memory;
struct iforce_core_effect core_effects[FF_EFFECTS_MAX];
struct semaphore mem_mutex;
};
/* Get hi and low bytes of a 16-bits int */
#define HI(a) ((unsigned char)((a) >> 8))
#define LO(a) ((unsigned char)((a) & 0xff))
/* For many parameters, it seems that 0x80 is a special value that should
* be avoided. Instead, we replace this value by 0x7f
*/
#define HIFIX80(a) ((unsigned char)(((a)<0? (a)+255 : (a))>>8))
/* Encode a time value */
#define TIME_SCALE(a) ((a) == 0xffff ? 0xffff : (a) * 1000 / 256)
/* Public functions */
/* iforce-serio.c */
void iforce_serial_xmit(struct iforce *iforce);
/* iforce-usb.c */
void iforce_usb_xmit(struct iforce *iforce);
/* iforce-main.c */
int iforce_init_device(struct iforce *iforce);
/* iforce-packets.c */
void iforce_process_packet(struct iforce *iforce, u16 cmd, unsigned char *data);
int iforce_send_packet(struct iforce *iforce, u16 cmd, unsigned char* data);
void iforce_dump_packet(char *msg, u16 cmd, unsigned char *data) ;
int iforce_get_id_packet(struct iforce *iforce, char *packet);
/* iforce-ff.c */
int iforce_upload_periodic(struct iforce*, struct ff_effect*, int is_update);
int iforce_upload_constant(struct iforce*, struct ff_effect*, int is_update);
int iforce_upload_interactive(struct iforce*, struct ff_effect*, int is_update);
/* Public variables */
struct serio_dev iforce_serio_dev;
struct usb_driver iforce_usb_driver;
Index: Makefile
===================================================================
RCS file: /cvsroot/linuxconsole/ruby/linux/drivers/input/Makefile,v
retrieving revision 1.42
retrieving revision 1.42.2.1
diff -u -d -r1.42 -r1.42.2.1
--- Makefile 2001/08/27 11:48:38 1.42
+++ Makefile 2001/10/07 17:06:49 1.42.2.1
@@ -28,6 +28,14 @@
hid-objs += hiddev.o
endif
+iforce-objs := iforce-packets.o iforce-ff.o iforce-main.o
+ifeq ($(CONFIG_IFORCE_SERIAL),y)
+ iforce-objs += iforce-serio.o
+endif
+ifeq ($(CONFIG_IFORCE_USB),y)
+ iforce-objs += iforce-usb.o
+endif
+
# Object file lists.
obj-y :=
@@ -147,3 +155,6 @@
hid.o: $(hid-objs)
$(LD) -r -o $@ $(hid-objs)
+
+iforce.o: $(iforce-objs)
+ $(LD) -r -o $@ $(iforce-objs)
--- iforce.c DELETED ---
|
|
From: Paul M. <le...@us...> - 2001-10-06 21:06:35
|
Update of /cvsroot/linuxconsole/ruby/linux/fs/gfxfs
In directory usw-pr-cvs1:/tmp/cvs-serv16175
Modified Files:
dir.c
Log Message:
Add support for the dcache provided readdir.
Index: dir.c
===================================================================
RCS file: /cvsroot/linuxconsole/ruby/linux/fs/gfxfs/dir.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- dir.c 2001/10/06 21:00:43 1.1
+++ dir.c 2001/10/06 21:06:32 1.2
@@ -9,10 +9,12 @@
*
*/
#include <linux/gfxfs_fs.h>
+#include <linux/dcache.h>
/* FIXME: Keep things happy for now, add our own later */
struct file_operations gfxfs_dir_ops = {
read: generic_read_dir,
+ readdir: dcache_readdir,
};
/* Ditto */
|
|
From: Paul M. <le...@us...> - 2001-10-06 21:01:17
|
Update of /cvsroot/linuxconsole/ruby/linux/include/linux
In directory usw-pr-cvs1:/tmp/cvs-serv15040
Modified Files:
gfxfs_fs.h
Log Message:
header updates too.
Index: gfxfs_fs.h
===================================================================
RCS file: /cvsroot/linuxconsole/ruby/linux/include/linux/gfxfs_fs.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- gfxfs_fs.h 2001/10/06 19:35:58 1.1
+++ gfxfs_fs.h 2001/10/06 21:01:15 1.2
@@ -5,14 +5,24 @@
*
* Copyright (C) 2001 Paul Mundt <pm...@mv...>
*
+ * Released under the terms of the GNU GPL v2.0.
+ *
*/
#ifndef __GFXFS_FS_H
#define __GFXFS_FS_H
#include <linux/fs.h>
+#include <linux/config.h>
#define GFXFS_SUPER_MAGIC 0x8048494 /* "gfxfs" */
+#ifdef CONFIG_GFXFS_FS_DEBUG
+ #define gfxfs_debug(x...) printk(KERN_DEBUG "gfxfs: " \
+ __FUNCTION__ "(): " ##x)
+#else
+ #define gfxfs_debug(x...) do { } while (0)
+#endif /* CONFIG_GFXFS_FS_DEBUG */
+
/*
* struct gfxfs_dentry - gfxfs dentry
*
@@ -32,6 +42,17 @@
struct dentry *f_dentry;
struct file_operations *f_ops;
};
+
+/* fs/gfxfs/inode.c */
+extern void gfxfs_read_inode(struct inode *inode);
+extern struct inode *gfxfs_get_inode(struct super_block *sb, int mode, int dev);
+
+/* fs/gfxfs/file.c */
+extern struct file_operations gfxfs_file_ops;
+
+/* fs/gfxfs/dir.c */
+extern struct file_operations gfxfs_dir_ops;
+extern struct inode_operations gfxfs_dir_inode_ops;
#endif /* __GFXFS_FS_H */
|
|
From: Paul M. <le...@us...> - 2001-10-06 21:00:46
|
Update of /cvsroot/linuxconsole/ruby/linux/fs In directory usw-pr-cvs1:/tmp/cvs-serv14922 Modified Files: Config.in Log Message: GfxFS updates. Index: Config.in =================================================================== RCS file: /cvsroot/linuxconsole/ruby/linux/fs/Config.in,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- Config.in 2001/10/06 17:47:04 1.1 +++ Config.in 2001/10/06 21:00:43 1.2 @@ -46,6 +46,7 @@ tristate 'OS/2 HPFS file system support' CONFIG_HPFS_FS dep_tristate 'Graphics file system support (EXPERIMENTAL)' CONFIG_GFXFS_FS $CONFIG_EXPERIMENTAL +dep_bool ' Debug gfxfs' CONFIG_GFXFS_FS_DEBUG $CONFIG_GFXFS_FS bool '/proc file system support' CONFIG_PROC_FS |
|
From: Paul M. <le...@us...> - 2001-10-06 21:00:46
|
Update of /cvsroot/linuxconsole/ruby/linux/fs/gfxfs
In directory usw-pr-cvs1:/tmp/cvs-serv14922/gfxfs
Added Files:
Makefile dir.c file.c inode.c super.c
Log Message:
GfxFS updates.
--- NEW FILE: Makefile ---
#
# Makefile for the Linux graphics filesystem routines.
#
# Note! Dependencies are done automagically by 'make dep', which also
# removes any old dependencies. DON'T put your own dependencies here
# unless it's something special (not a .c file).
#
# Note 2! The CFLAGS definitions are now in the main makefile.
O_TARGET := gfxfs.o
obj-y := super.o inode.o file.o dir.o
obj-m := $(O_TARGET)
include $(TOPDIR)/Rules.make
--- NEW FILE: dir.c ---
/*
* fs/gfxfs/dir.c
*
* gfxfs directory operations
*
* Copyright (C) 2001 Paul Mundt <pm...@mv...>
*
* Released under the terms of the GNU GPL v2.0.
*
*/
#include <linux/gfxfs_fs.h>
/* FIXME: Keep things happy for now, add our own later */
struct file_operations gfxfs_dir_ops = {
read: generic_read_dir,
};
/* Ditto */
struct inode_operations gfxfs_dir_inode_ops = {
/* Empty for now */
};
--- NEW FILE: file.c ---
/*
* fs/gfxfs/file.c
*
* gfxfs file operations
*
* Copyright (C) 2001 Paul Mundt <pm...@mv...>
*
* Released under the terms of the GNU GPL v2.0.
*
*/
#include <linux/gfxfs_fs.h>
/*
* FIXME: Use generic routines for now, add our own later.
*/
struct file_operations gfxfs_file_ops = {
mmap: generic_file_mmap,
llseek: generic_file_llseek,
};
--- NEW FILE: inode.c ---
/*
* fs/gfxfs/inode.c
*
* gfxfs inode operations
*
* Copyright (C) 2001 Paul Mundt <pm...@mv...>
*
* Released under the terms of the GNU GPL v2.0.
*
*/
#include <linux/locks.h>
#include <linux/gfxfs_fs.h>
#include <asm/uaccess.h>
void gfxfs_read_inode(struct inode *inode)
{
inode->i_atime = inode->i_ctime = inode->i_mtime = CURRENT_TIME;
}
struct inode *gfxfs_get_inode(struct super_block *sb, int mode, int dev)
{
struct inode *inode = new_inode(sb);
if (!inode) {
printk(KERN_WARNING "gfxfs: Unable to get new inode\n");
return NULL;
}
inode->i_mode = mode;
inode->i_uid = current->fsuid;
inode->i_gid = current->fsgid;
inode->i_blksize = PAGE_CACHE_SIZE;
inode->i_blocks = 0;
inode->i_rdev = NODEV;
gfxfs_read_inode(inode);
switch (mode & S_IFMT) {
case S_IFREG:
inode->i_fop = &gfxfs_file_ops;
break;
case S_IFDIR:
inode->i_op = &gfxfs_dir_inode_ops;
inode->i_fop = &gfxfs_dir_ops;
break;
default:
init_special_inode(inode, mode, dev);
break;
}
return inode;
}
--- NEW FILE: super.c ---
/*
* fs/gfxfs/super.c
*
* gfxfs superblock operations
*
* Copyright (C) 2001 Paul Mundt <pm...@mv...>
*
* Released under the terms of the GNU GPL v2.0.
*
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/gfxfs_fs.h>
#include <linux/pagemap.h>
#include <linux/dcache.h>
static struct vfsmount *gfxfs_mnt;
static int gfxfs_statfs(struct super_block *sb, struct statfs *buf)
{
buf->f_type = GFXFS_SUPER_MAGIC;
buf->f_bsize = PAGE_CACHE_SIZE;
buf->f_namelen = NAME_MAX;
return 0;
}
static struct super_operations gfxfs_super_ops = {
statfs: gfxfs_statfs,
};
static struct super_block *gfxfs_read_super(struct super_block *sb,
void *data, int silent)
{
struct inode *root_inode;
sb->s_blocksize = PAGE_CACHE_SIZE;
sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
sb->s_magic = GFXFS_SUPER_MAGIC;
sb->s_op = &gfxfs_super_ops;
root_inode = gfxfs_get_inode(sb, S_IFDIR | 0755, 0);
if (!root_inode) {
printk(KERN_WARNING "gfxfs: Unable to get root inode\n");
return NULL;
}
sb->s_root = d_alloc_root(root_inode);
if (!sb->s_root) {
printk(KERN_WARNING "gfxfs: Unable to get root dentry\n");
iput(root_inode);
return NULL;
}
return sb;
}
static DECLARE_FSTYPE(gfxfs_fs_type, "gfxfs", gfxfs_read_super, FS_SINGLE);
static int __init init_gfxfs_fs(void)
{
int ret = register_filesystem(&gfxfs_fs_type);
if (!ret) {
gfxfs_mnt = kern_mount(&gfxfs_fs_type);
ret = PTR_ERR(gfxfs_mnt);
if (!IS_ERR(gfxfs_mnt)) {
ret = 0;
}
}
return ret;
}
static void __exit exit_gfxfs_fs(void)
{
kern_umount(gfxfs_mnt);
unregister_filesystem(&gfxfs_fs_type);
}
EXPORT_NO_SYMBOLS;
MODULE_AUTHOR("Paul Mundt <pm...@mv...>");
MODULE_DESCRIPTION("graphics file system");
MODULE_LICENSE("GPL");
module_init(init_gfxfs_fs);
module_exit(exit_gfxfs_fs);
|
|
From: Paul M. <le...@us...> - 2001-10-06 19:36:00
|
Update of /cvsroot/linuxconsole/ruby/linux/include/linux
In directory usw-pr-cvs1:/tmp/cvs-serv31635
Added Files:
gfxfs_fs.h
Log Message:
Added preliminary header.
--- NEW FILE: gfxfs_fs.h ---
/*
* include/linux/gfxfs_fs.h
*
* Primary GfxFS header.
*
* Copyright (C) 2001 Paul Mundt <pm...@mv...>
*
*/
#ifndef __GFXFS_FS_H
#define __GFXFS_FS_H
#include <linux/fs.h>
#define GFXFS_SUPER_MAGIC 0x8048494 /* "gfxfs" */
/*
* struct gfxfs_dentry - gfxfs dentry
*
* @f_dentry: Pointer to underlying dentry.
* @f_ops: File operations associated with given dentry.
*
* Each gfxfs dentry has the ability for callbacks to be
* registered with it upon allocation. In the event a
* callback is registered, it gets executed in place of
* the generic dcache routines. For all other operations,
* we rely on generic routines provided by the dcache.
*
* Notably, the registered file operations callbacks
* only apply to regular (S_IFREG) files.
*/
struct gfxfs_dentry {
struct dentry *f_dentry;
struct file_operations *f_ops;
};
#endif /* __GFXFS_FS_H */
|
|
From: Paul M. <le...@us...> - 2001-10-06 17:47:07
|
Update of /cvsroot/linuxconsole/ruby/linux/fs
In directory usw-pr-cvs1:/tmp/cvs-serv11819
Added Files:
Config.in Makefile
Log Message:
Added GfxFS rules.
--- NEW FILE: Config.in ---
#
# File system configuration
#
mainmenu_option next_comment
comment 'File systems'
bool 'Quota support' CONFIG_QUOTA
tristate 'Kernel automounter support' CONFIG_AUTOFS_FS
tristate 'Kernel automounter version 4 support (also supports v3)' CONFIG_AUTOFS4_FS
dep_tristate 'Reiserfs support' CONFIG_REISERFS_FS $CONFIG_EXPERIMENTAL
dep_mbool ' Have reiserfs do extra internal checking' CONFIG_REISERFS_CHECK $CONFIG_REISERFS_FS $CONFIG_EXPERIMENTAL
dep_tristate 'ADFS file system support' CONFIG_ADFS_FS $CONFIG_EXPERIMENTAL
dep_mbool ' ADFS write support (DANGEROUS)' CONFIG_ADFS_FS_RW $CONFIG_ADFS_FS $CONFIG_EXPERIMENTAL
dep_tristate 'Amiga FFS file system support (EXPERIMENTAL)' CONFIG_AFFS_FS $CONFIG_EXPERIMENTAL
dep_tristate 'Apple Macintosh file system support (EXPERIMENTAL)' CONFIG_HFS_FS $CONFIG_EXPERIMENTAL
dep_tristate 'BFS file system support (EXPERIMENTAL)' CONFIG_BFS_FS $CONFIG_EXPERIMENTAL
# msdos file systems
tristate 'DOS FAT fs support' CONFIG_FAT_FS
dep_tristate ' MSDOS fs support' CONFIG_MSDOS_FS $CONFIG_FAT_FS
dep_tristate ' UMSDOS: Unix-like file system on top of standard MSDOS fs' CONFIG_UMSDOS_FS $CONFIG_MSDOS_FS
dep_tristate ' VFAT (Windows-95) fs support' CONFIG_VFAT_FS $CONFIG_FAT_FS
dep_tristate 'EFS file system support (read only) (EXPERIMENTAL)' CONFIG_EFS_FS $CONFIG_EXPERIMENTAL
dep_tristate 'Journalling Flash File System (JFFS) support (EXPERIMENTAL)' CONFIG_JFFS_FS $CONFIG_EXPERIMENTAL $CONFIG_MTD
if [ "$CONFIG_JFFS_FS" = "y" -o "$CONFIG_JFFS_FS" = "m" ] ; then
int 'JFFS debugging verbosity (0 = quiet, 3 = noisy)' CONFIG_JFFS_FS_VERBOSE 0
fi
tristate 'Compressed ROM file system support' CONFIG_CRAMFS
bool 'Virtual memory file system support (former shm fs)' CONFIG_TMPFS
tristate 'Simple RAM-based file system support' CONFIG_RAMFS
tristate 'ISO 9660 CDROM file system support' CONFIG_ISO9660_FS
dep_mbool ' Microsoft Joliet CDROM extensions' CONFIG_JOLIET $CONFIG_ISO9660_FS
tristate 'Minix fs support' CONFIG_MINIX_FS
tristate 'FreeVxFS file system support (VERITAS VxFS(TM) compatible)' CONFIG_VXFS_FS
tristate 'NTFS file system support (read only)' CONFIG_NTFS_FS
dep_mbool ' NTFS write support (DANGEROUS)' CONFIG_NTFS_RW $CONFIG_NTFS_FS $CONFIG_EXPERIMENTAL
tristate 'OS/2 HPFS file system support' CONFIG_HPFS_FS
dep_tristate 'Graphics file system support (EXPERIMENTAL)' CONFIG_GFXFS_FS $CONFIG_EXPERIMENTAL
bool '/proc file system support' CONFIG_PROC_FS
dep_bool '/dev file system support (EXPERIMENTAL)' CONFIG_DEVFS_FS $CONFIG_EXPERIMENTAL
dep_bool ' Automatically mount at boot' CONFIG_DEVFS_MOUNT $CONFIG_DEVFS_FS
dep_bool ' Debug devfs' CONFIG_DEVFS_DEBUG $CONFIG_DEVFS_FS
# It compiles as a module for testing only. It should not be used
# as a module in general. If we make this "tristate", a bunch of people
# who don't know what they are doing turn it on and complain when it
# breaks.
dep_bool '/dev/pts file system for Unix98 PTYs' CONFIG_DEVPTS_FS $CONFIG_UNIX98_PTYS
dep_tristate 'QNX4 file system support (read only) (EXPERIMENTAL)' CONFIG_QNX4FS_FS $CONFIG_EXPERIMENTAL
dep_mbool ' QNX4FS write support (DANGEROUS)' CONFIG_QNX4FS_RW $CONFIG_QNX4FS_FS $CONFIG_EXPERIMENTAL
tristate 'ROM file system support' CONFIG_ROMFS_FS
tristate 'Second extended fs support' CONFIG_EXT2_FS
tristate 'System V/Xenix/V7/Coherent file system support' CONFIG_SYSV_FS
tristate 'UDF file system support (read only)' CONFIG_UDF_FS
dep_mbool ' UDF write support (DANGEROUS)' CONFIG_UDF_RW $CONFIG_UDF_FS $CONFIG_EXPERIMENTAL
tristate 'UFS file system support (read only)' CONFIG_UFS_FS
dep_mbool ' UFS file system write support (DANGEROUS)' CONFIG_UFS_FS_WRITE $CONFIG_UFS_FS $CONFIG_EXPERIMENTAL
if [ "$CONFIG_NET" = "y" ]; then
mainmenu_option next_comment
comment 'Network File Systems'
dep_tristate 'Coda file system support (advanced network fs)' CONFIG_CODA_FS $CONFIG_INET
dep_tristate 'NFS file system support' CONFIG_NFS_FS $CONFIG_INET
dep_mbool ' Provide NFSv3 client support' CONFIG_NFS_V3 $CONFIG_NFS_FS
dep_bool ' Root file system on NFS' CONFIG_ROOT_NFS $CONFIG_NFS_FS $CONFIG_IP_PNP
dep_tristate 'NFS server support' CONFIG_NFSD $CONFIG_INET
dep_mbool ' Provide NFSv3 server support' CONFIG_NFSD_V3 $CONFIG_NFSD
if [ "$CONFIG_NFS_FS" = "y" -o "$CONFIG_NFSD" = "y" ]; then
define_tristate CONFIG_SUNRPC y
define_tristate CONFIG_LOCKD y
else
if [ "$CONFIG_NFS_FS" = "m" -o "$CONFIG_NFSD" = "m" ]; then
define_tristate CONFIG_SUNRPC m
define_tristate CONFIG_LOCKD m
else
define_tristate CONFIG_SUNRPC n
define_tristate CONFIG_LOCKD n
fi
fi
if [ "$CONFIG_NFSD_V3" = "y" -o "$CONFIG_NFS_V3" = "y" ]; then
define_bool CONFIG_LOCKD_V4 y
fi
dep_tristate 'SMB file system support (to mount Windows shares etc.)' CONFIG_SMB_FS $CONFIG_INET
if [ "$CONFIG_SMB_FS" != "n" ]; then
bool ' Use a default NLS' CONFIG_SMB_NLS_DEFAULT
if [ "$CONFIG_SMB_NLS_DEFAULT" = "y" ]; then
string ' Default Remote NLS Option' CONFIG_SMB_NLS_REMOTE "cp437"
fi
fi
if [ "$CONFIG_IPX" != "n" -o "$CONFIG_INET" != "n" ]; then
tristate 'NCP file system support (to mount NetWare volumes)' CONFIG_NCP_FS
source fs/ncpfs/Config.in
else
# for fs/nls/Config.in
define_bool CONFIG_NCPFS_NLS n
fi
endmenu
else
# for fs/nls/Config.in
define_bool CONFIG_NCPFS_NLS n
define_bool CONFIG_SMB_FS n
fi
mainmenu_option next_comment
comment 'Partition Types'
source fs/partitions/Config.in
endmenu
source fs/nls/Config.in
endmenu
--- NEW FILE: Makefile ---
#
# Makefile for the Linux filesystems.
#
# 14 Sep 2000, Christoph Hellwig <hc...@ca...>
# Rewritten to use lists instead of if-statements.
#
O_TARGET := fs.o
export-objs := filesystems.o open.o dcache.o
mod-subdirs := nls
obj-y := open.o read_write.o devices.o file_table.o buffer.o \
super.o block_dev.o char_dev.o stat.o exec.o pipe.o namei.o \
fcntl.o ioctl.o readdir.o select.o fifo.o locks.o \
dcache.o inode.o attr.o bad_inode.o file.o iobuf.o dnotify.o \
filesystems.o
ifeq ($(CONFIG_QUOTA),y)
obj-y += dquot.o
else
obj-y += noquot.o
endif
subdir-$(CONFIG_PROC_FS) += proc
subdir-y += partitions
# Do not add any filesystems before this line
subdir-$(CONFIG_EXT2_FS) += ext2
subdir-$(CONFIG_CRAMFS) += cramfs
subdir-$(CONFIG_RAMFS) += ramfs
subdir-$(CONFIG_CODA_FS) += coda
subdir-$(CONFIG_MINIX_FS) += minix
subdir-$(CONFIG_FAT_FS) += fat
subdir-$(CONFIG_UMSDOS_FS) += umsdos
subdir-$(CONFIG_MSDOS_FS) += msdos
subdir-$(CONFIG_VFAT_FS) += vfat
subdir-$(CONFIG_BFS_FS) += bfs
subdir-$(CONFIG_ISO9660_FS) += isofs
subdir-$(CONFIG_DEVFS_FS) += devfs
subdir-$(CONFIG_HFS_FS) += hfs
subdir-$(CONFIG_VXFS_FS) += freevxfs
subdir-$(CONFIG_NFS_FS) += nfs
subdir-$(CONFIG_NFSD) += nfsd
subdir-$(CONFIG_LOCKD) += lockd
subdir-$(CONFIG_NLS) += nls
subdir-$(CONFIG_SYSV_FS) += sysv
subdir-$(CONFIG_SMB_FS) += smbfs
subdir-$(CONFIG_NCP_FS) += ncpfs
subdir-$(CONFIG_HPFS_FS) += hpfs
subdir-$(CONFIG_NTFS_FS) += ntfs
subdir-$(CONFIG_UFS_FS) += ufs
subdir-$(CONFIG_EFS_FS) += efs
subdir-$(CONFIG_JFFS_FS) += jffs
subdir-$(CONFIG_AFFS_FS) += affs
subdir-$(CONFIG_ROMFS_FS) += romfs
subdir-$(CONFIG_QNX4FS_FS) += qnx4
subdir-$(CONFIG_UDF_FS) += udf
subdir-$(CONFIG_AUTOFS_FS) += autofs
subdir-$(CONFIG_AUTOFS4_FS) += autofs4
subdir-$(CONFIG_ADFS_FS) += adfs
subdir-$(CONFIG_REISERFS_FS) += reiserfs
subdir-$(CONFIG_DEVPTS_FS) += devpts
subdir-$(CONFIG_SUN_OPENPROMFS) += openpromfs
subdir-$(CONFIG_GFXFS_FS) += gfxfs
obj-$(CONFIG_BINFMT_AOUT) += binfmt_aout.o
obj-$(CONFIG_BINFMT_EM86) += binfmt_em86.o
obj-$(CONFIG_BINFMT_MISC) += binfmt_misc.o
# binfmt_script is always there
obj-y += binfmt_script.o
obj-$(CONFIG_BINFMT_ELF) += binfmt_elf.o
# persistent filesystems
obj-y += $(join $(subdir-y),$(subdir-y:%=/%.o))
include $(TOPDIR)/Rules.make
|
|
From: Paul M. <le...@us...> - 2001-10-06 17:46:44
|
Update of /cvsroot/linuxconsole/ruby/linux/fs/gfxfs In directory usw-pr-cvs1:/tmp/cvs-serv11793/gfxfs Log Message: Directory /cvsroot/linuxconsole/ruby/linux/fs/gfxfs added to the repository |
|
From: James S. <jsi...@us...> - 2001-10-06 16:31:00
|
Update of /cvsroot/linuxconsole/ruby In directory usw-pr-cvs1:/tmp/cvs-serv29635 Removed Files: AGAINST-2.4.9 Log Message: --- AGAINST-2.4.9 DELETED --- |
|
From: James S. <jsi...@us...> - 2001-10-06 16:30:22
|
Update of /cvsroot/linuxconsole/ruby In directory usw-pr-cvs1:/tmp/cvs-serv29561 Added Files: AGAINST-2.4.10 Log Message: --- NEW FILE: AGAINST-2.4.10 --- |
|
From: James S. <jsi...@us...> - 2001-10-06 16:27:55
|
Update of /cvsroot/linuxconsole/ruby/linux/arch/i386/kernel
In directory usw-pr-cvs1:/tmp/cvs-serv29140
Added Files:
dmi_scan.c
Log Message:
Hm. On DELL PS/2 and PM suspend don't get along. For now I just ignore the problem but we will have to think about handling PM on a input level.
--- NEW FILE: dmi_scan.c ---
#include <linux/config.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/init.h>
#include <linux/apm_bios.h>
#include <linux/slab.h>
#include <asm/io.h>
#include <linux/pm.h>
#include <linux/keyboard.h>
struct dmi_header
{
u8 type;
u8 length;
u16 handle;
};
#define dmi_printk(x)
//#define dmi_printk(x) printk x
static char * __init dmi_string(struct dmi_header *dm, u8 s)
{
u8 *bp=(u8 *)dm;
bp+=dm->length;
if(!s)
return "";
s--;
while(s>0)
{
bp+=strlen(bp);
bp++;
s--;
}
return bp;
}
/*
* We have to be cautious here. We have seen BIOSes with DMI pointers
* pointing to completely the wrong place for example
*/
static int __init dmi_table(u32 base, int len, int num, void (*decode)(struct dmi_header *))
{
u8 *buf;
struct dmi_header *dm;
u8 *data;
int i=1;
buf = ioremap(base, len);
if(buf==NULL)
return -1;
data = buf;
/*
* Stop when we see al the items the table claimed to have
* OR we run off the end of the table (also happens)
*/
while(i<num && (data - buf) < len)
{
dm=(struct dmi_header *)data;
/*
* Avoid misparsing crud if the length of the last
* record is crap
*/
if((data-buf+dm->length) >= len)
break;
decode(dm);
data+=dm->length;
/*
* Don't go off the end of the data if there is
* stuff looking like string fill past the end
*/
while((data-buf) < len && (*data || data[1]))
data++;
data+=2;
i++;
}
iounmap(buf);
return 0;
}
int __init dmi_iterate(void (*decode)(struct dmi_header *))
{
unsigned char buf[20];
long fp=0xE0000L;
fp -= 16;
#ifdef CONFIG_SIMNOW
/*
* Skip on x86/64 with simnow. Will eventually go away
* If you see this ifdef in 2.6pre mail me !
*/
return;
#endif
while( fp < 0xFFFFF)
{
fp+=16;
isa_memcpy_fromio(buf, fp, 20);
if(memcmp(buf, "_DMI_", 5)==0)
{
u16 num=buf[13]<<8|buf[12];
u16 len=buf[7]<<8|buf[6];
u32 base=buf[11]<<24|buf[10]<<16|buf[9]<<8|buf[8];
dmi_printk((KERN_INFO "DMI %d.%d present.\n",
buf[14]>>4, buf[14]&0x0F));
dmi_printk((KERN_INFO "%d structures occupying %d bytes.\n",
buf[13]<<8|buf[12],
buf[7]<<8|buf[6]));
dmi_printk((KERN_INFO "DMI table at 0x%08X.\n",
buf[11]<<24|buf[10]<<16|buf[9]<<8|buf[8]));
if(dmi_table(base,len, num, decode)==0)
return 0;
}
}
return -1;
}
enum
{
DMI_BIOS_VENDOR,
DMI_BIOS_VERSION,
DMI_BIOS_DATE,
DMI_SYS_VENDOR,
DMI_PRODUCT_NAME,
DMI_PRODUCT_VERSION,
DMI_BOARD_VENDOR,
DMI_BOARD_NAME,
DMI_BOARD_VERSION,
DMI_STRING_MAX
};
static char *dmi_ident[DMI_STRING_MAX];
/*
* Save a DMI string
*/
static void __init dmi_save_ident(struct dmi_header *dm, int slot, int string)
{
char *d = (char*)dm;
char *p = dmi_string(dm, d[string]);
if(p==NULL || *p == 0)
return;
if (dmi_ident[slot])
return;
dmi_ident[slot] = kmalloc(strlen(p)+1, GFP_KERNEL);
if(dmi_ident[slot])
strcpy(dmi_ident[slot], p);
else
printk(KERN_ERR "dmi_save_ident: out of memory.\n");
}
/*
* DMI callbacks for problem boards
*/
struct dmi_strmatch
{
u8 slot;
char *substr;
};
#define NONE 255
struct dmi_blacklist
{
int (*callback)(struct dmi_blacklist *);
char *ident;
struct dmi_strmatch matches[4];
};
#define NO_MATCH { NONE, NULL}
#define MATCH(a,b) { a, b }
/*
* We have problems with IDE DMA on some platforms. In paticular the
* KT7 series. On these it seems the newer BIOS has fixed them. The
* rule needs to be improved to match specific BIOS revisions with
* corruption problems
*/
static __init int disable_ide_dma(struct dmi_blacklist *d)
{
#ifdef CONFIG_BLK_DEV_IDE
extern int noautodma;
if(noautodma == 0)
{
noautodma = 1;
printk(KERN_INFO "%s series board detected. Disabling IDE DMA.\n", d->ident);
}
#endif
return 0;
}
/*
* Reboot options and system auto-detection code provided by
* Dell Computer Corporation so their systems "just work". :-)
*/
/*
* Some machines require the "reboot=b" commandline option, this quirk makes that automatic.
*/
static __init int set_bios_reboot(struct dmi_blacklist *d)
{
extern int reboot_thru_bios;
if (reboot_thru_bios == 0)
{
reboot_thru_bios = 1;
printk(KERN_INFO "%s series board detected. Selecting BIOS-method for reboots.\n", d->ident);
}
return 0;
}
/*
* Some machines require the "reboot=s" commandline option, this quirk makes that automatic.
*/
static __init int set_smp_reboot(struct dmi_blacklist *d)
{
#ifdef CONFIG_SMP
extern int reboot_smp;
if (reboot_smp == 0)
{
reboot_smp = 1;
printk(KERN_INFO "%s series board detected. Selecting SMP-method for reboots.\n", d->ident);
}
#endif
return 0;
}
/*
* Some machines require the "reboot=b,s" commandline option, this quirk makes that automatic.
*/
static __init int set_smp_bios_reboot(struct dmi_blacklist *d)
{
set_smp_reboot(d);
set_bios_reboot(d);
return 0;
}
/*
* Some bioses have a broken protected mode poweroff and need to use realmode
*/
static __init int set_realmode_power_off(struct dmi_blacklist *d)
{
if (apm_info.realmode_power_off == 0)
{
apm_info.realmode_power_off = 1;
printk(KERN_INFO "%s bios detected. Using realmode poweroff only.\n", d->ident);
}
return 0;
}
/*
* Some laptops require interrupts to be enabled during APM calls
*/
static __init int set_apm_ints(struct dmi_blacklist *d)
{
if (apm_info.allow_ints == 0)
{
apm_info.allow_ints = 1;
printk(KERN_INFO "%s machine detected. Enabling interrupts during APM calls.\n", d->ident);
}
return 0;
}
/*
* Some APM bioses corrupt memory or just plain do not work
*/
static __init int apm_is_horked(struct dmi_blacklist *d)
{
if (apm_info.disabled == 0)
{
apm_info.disabled = 1;
printk(KERN_INFO "%s machine detected. Disabling APM.\n", d->ident);
}
return 0;
}
/*
* Check for clue free BIOS implementations who use
* the following QA technique
*
* [ Write BIOS Code ]<------
* | ^
* < Does it Compile >----N--
* |Y ^
* < Does it Boot Win98 >-N--
* |Y
* [Ship It]
*
* Phoenix A04 08/24/2000 is known bad (Dell Inspiron 5000e)
* Phoenix A07 09/29/2000 is known good (Dell Inspiron 5000)
*/
static __init int broken_apm_power(struct dmi_blacklist *d)
{
apm_info.get_power_status_broken = 1;
printk(KERN_WARNING "BIOS strings suggest APM bugs, disabling power status reporting.\n");
return 0;
}
#if defined(CONFIG_SONYPI) || defined(CONFIG_SONYPI_MODULE)
/*
* Check for a Sony Vaio system in order to enable the use of
* the sonypi driver (we don't want this driver to be used on
* other systems, even if they have the good PCI IDs).
*
* This one isn't a bug detect for those who asked, we simply want to
* activate Sony specific goodies like the camera and jogdial..
*/
int is_sony_vaio_laptop;
static __init int sony_vaio_laptop(struct dmi_blacklist *d)
{
if (is_sony_vaio_laptop == 0)
{
is_sony_vaio_laptop = 1;
printk(KERN_INFO "%s laptop detected.\n", d->ident);
}
return 0;
}
#endif
/*
* This bios swaps the APM minute reporting bytes over (Many sony laptops
* have this problem).
*/
static __init int swab_apm_power_in_minutes(struct dmi_blacklist *d)
{
apm_info.get_power_status_swabinminutes = 1;
printk(KERN_WARNING "BIOS strings suggest APM reports battery life in minutes and wrong byte order.\n");
return 0;
}
/*
* The Intel 440GX hall of shame.
*
* On many (all we have checked) of these boxes the $PIRQ table is wrong.
* The MP1.4 table is right however and so SMP kernels tend to work.
*/
static __init int broken_pirq(struct dmi_blacklist *d)
{
printk(KERN_INFO " *** Possibly defective BIOS detected (irqtable)\n");
printk(KERN_INFO " *** Many BIOSes matching this signature have incorrect IRQ routing tables.\n");
printk(KERN_INFO " *** If you see IRQ problems, in paticular SCSI resets and hangs at boot\n");
printk(KERN_INFO " *** contact your vendor and ask about updates.\n");
printk(KERN_INFO " *** Building an SMP kernel may evade the bug some of the time.\n");
return 0;
}
/*
* Process the DMI blacklists
*/
/*
* This will be expanded over time to force things like the APM
* interrupt mask settings according to the laptop
*/
static __initdata struct dmi_blacklist dmi_blacklist[]={
#if 0
{ disable_ide_dma, "KT7", { /* Overbroad right now - kill DMA on problem KT7 boards */
MATCH(DMI_PRODUCT_NAME, "KT7-RAID"),
NO_MATCH, NO_MATCH, NO_MATCH
} },
#endif
{ broken_apm_power, "Dell Inspiron 5000e", { /* Handle problems with APM on Inspiron 5000e */
MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
MATCH(DMI_BIOS_VERSION, "A04"),
MATCH(DMI_BIOS_DATE, "08/24/2000"), NO_MATCH
} },
{ set_realmode_power_off, "Award Software v4.60 PGMA", { /* broken PM poweroff bios */
MATCH(DMI_BIOS_VENDOR, "Award Software International, Inc."),
MATCH(DMI_BIOS_VERSION, "4.60 PGMA"),
MATCH(DMI_BIOS_DATE, "134526184"), NO_MATCH
} },
{ set_smp_bios_reboot, "Dell PowerEdge 1300", { /* Handle problems with rebooting on Dell 1300's */
MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
MATCH(DMI_PRODUCT_NAME, "PowerEdge 1300/"),
NO_MATCH, NO_MATCH
} },
{ set_bios_reboot, "Dell PowerEdge 300", { /* Handle problems with rebooting on Dell 1300's */
MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
MATCH(DMI_PRODUCT_NAME, "PowerEdge 300/"),
NO_MATCH, NO_MATCH
} },
{ set_apm_ints, "IBM", { /* Allow interrupts during suspend on IBM laptops */
MATCH(DMI_SYS_VENDOR, "IBM"),
NO_MATCH, NO_MATCH, NO_MATCH
} },
{ set_apm_ints, "Dell Inspiron", { /* Allow interrupts during suspend on Dell Inspiron laptops*/
MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
MATCH(DMI_PRODUCT_NAME, "Inspiron 4000"),
NO_MATCH, NO_MATCH
} },
{ set_apm_ints, "Compaq 12XL125", { /* Allow interrupts during suspend on Compaq Laptops*/
MATCH(DMI_SYS_VENDOR, "Compaq"),
MATCH(DMI_PRODUCT_NAME, "Compaq PC"),
MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
MATCH(DMI_BIOS_VERSION,"4.06")
} },
{ set_apm_ints, "ASUSTeK", { /* Allow interrupts during APM or the clock goes slow */
MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
MATCH(DMI_PRODUCT_NAME, "L8400K series Notebook PC"),
NO_MATCH, NO_MATCH
} },
{ apm_is_horked, "Trigem Delhi3", { /* APM crashes */
MATCH(DMI_SYS_VENDOR, "TriGem Computer, Inc"),
MATCH(DMI_PRODUCT_NAME, "Delhi3"),
NO_MATCH, NO_MATCH,
} },
{ apm_is_horked, "Sharp PC-PJ/AX", { /* APM crashes */
MATCH(DMI_SYS_VENDOR, "SHARP"),
MATCH(DMI_PRODUCT_NAME, "PC-PJ/AX"),
MATCH(DMI_BIOS_VENDOR,"SystemSoft"),
MATCH(DMI_BIOS_VERSION,"Version R2.08")
} },
#if defined(CONFIG_SONYPI) || defined(CONFIG_SONYPI_MODULE)
{ sony_vaio_laptop, "Sony Vaio", { /* This is a Sony Vaio laptop */
MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
MATCH(DMI_PRODUCT_NAME, "PCG-"),
NO_MATCH, NO_MATCH,
} },
#endif
{ swab_apm_power_in_minutes, "Sony VAIO", { /* Handle problems with APM on Sony Vaio PCG-N505X(DE) */
MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
MATCH(DMI_BIOS_VERSION, "R0206H"),
MATCH(DMI_BIOS_DATE, "08/23/99"), NO_MATCH
} },
{ swab_apm_power_in_minutes, "Sony VAIO", { /* Handle problems with APM on Sony Vaio PCG-N505VX */
MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
MATCH(DMI_BIOS_VERSION, "W2K06H0"),
MATCH(DMI_BIOS_DATE, "02/03/00"), NO_MATCH
} },
{ swab_apm_power_in_minutes, "Sony VAIO", { /* Handle problems with APM on Sony Vaio PCG-XG29 */
MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
MATCH(DMI_BIOS_VERSION, "R0117A0"),
MATCH(DMI_BIOS_DATE, "04/25/00"), NO_MATCH
} },
{ swab_apm_power_in_minutes, "Sony VAIO", { /* Handle problems with APM on Sony Vaio PCG-Z600NE */
MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
MATCH(DMI_BIOS_VERSION, "R0121Z1"),
MATCH(DMI_BIOS_DATE, "05/11/00"), NO_MATCH
} },
{ swab_apm_power_in_minutes, "Sony VAIO", { /* Handle problems with APM on Sony Vaio PCG-Z505LS */
MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
MATCH(DMI_BIOS_VERSION, "R0203D0"),
MATCH(DMI_BIOS_DATE, "05/12/00"), NO_MATCH
} },
{ swab_apm_power_in_minutes, "Sony VAIO", { /* Handle problems with APM on Sony Vaio PCG-Z505LS */
MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
MATCH(DMI_BIOS_VERSION, "R0203Z3"),
MATCH(DMI_BIOS_DATE, "08/25/00"), NO_MATCH
} },
{ swab_apm_power_in_minutes, "Sony VAIO", { /* Handle problems with APM on Sony Vaio PCG-F104K */
MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
MATCH(DMI_BIOS_VERSION, "R0204K2"),
MATCH(DMI_BIOS_DATE, "08/28/00"), NO_MATCH
} },
{ swab_apm_power_in_minutes, "Sony VAIO", { /* Handle problems with APM on Sony Vaio PCG-C1VN/C1VE */
MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
MATCH(DMI_BIOS_VERSION, "R0208P1"),
MATCH(DMI_BIOS_DATE, "11/09/00"), NO_MATCH
} },
{ swab_apm_power_in_minutes, "Sony VAIO", { /* Handle problems with APM on Sony Vaio PCG-C1VE */
MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
MATCH(DMI_BIOS_VERSION, "R0204P1"),
MATCH(DMI_BIOS_DATE, "09/12/00"), NO_MATCH
} },
/* Problem Intel 440GX bioses */
{ broken_pirq, "SABR1 Bios", { /* Bad $PIR */
MATCH(DMI_BIOS_VENDOR, "Intel Corporation"),
MATCH(DMI_BIOS_VERSION,"SABR1"),
NO_MATCH, NO_MATCH
} },
{ broken_pirq, "l44GX Bios", { /* Bad $PIR */
MATCH(DMI_BIOS_VENDOR, "Intel Corporation"),
MATCH(DMI_BIOS_VERSION,"L440GX0.86B.0094.P10"),
NO_MATCH, NO_MATCH
} },
{ broken_pirq, "l44GX Bios", { /* Bad $PIR */
MATCH(DMI_BIOS_VENDOR, "Intel Corporation"),
MATCH(DMI_BIOS_VERSION,"L440GX0.86B.0125.P13"),
NO_MATCH, NO_MATCH
} },
/* Intel in disgiuse - In this case they can't hide and they don't run
too well either... */
{ broken_pirq, "Dell PowerEdge 8450", { /* Bad $PIR */
MATCH(DMI_PRODUCT_NAME, "Dell PowerEdge 8450"),
NO_MATCH, NO_MATCH, NO_MATCH
} },
{ NULL, }
};
/*
* Walk the blacklist table running matching functions until someone
* returns 1 or we hit the end.
*/
static __init void dmi_check_blacklist(void)
{
struct dmi_blacklist *d;
int i;
d=&dmi_blacklist[0];
while(d->callback)
{
for(i=0;i<4;i++)
{
int s = d->matches[i].slot;
if(s==NONE)
continue;
if(dmi_ident[s] && strstr(dmi_ident[s], d->matches[i].substr))
continue;
/* No match */
goto fail;
}
if(d->callback(d))
return;
fail:
d++;
}
}
/*
* Process a DMI table entry. Right now all we care about are the BIOS
* and machine entries. For 2.5 we should pull the smbus controller info
* out of here.
*/
static void __init dmi_decode(struct dmi_header *dm)
{
u8 *data = (u8 *)dm;
char *p;
switch(dm->type)
{
case 0:
p=dmi_string(dm,data[4]);
if(*p)
{
dmi_printk(("BIOS Vendor: %s\n", p));
dmi_save_ident(dm, DMI_BIOS_VENDOR, 4);
dmi_printk(("BIOS Version: %s\n",
dmi_string(dm, data[5])));
dmi_save_ident(dm, DMI_BIOS_VERSION, 5);
dmi_printk(("BIOS Release: %s\n",
dmi_string(dm, data[8])));
dmi_save_ident(dm, DMI_BIOS_DATE, 8);
}
break;
case 1:
p=dmi_string(dm,data[4]);
if(*p)
{
dmi_printk(("System Vendor: %s.\n",p));
dmi_save_ident(dm, DMI_SYS_VENDOR, 4);
dmi_printk(("Product Name: %s.\n",
dmi_string(dm, data[5])));
dmi_save_ident(dm, DMI_PRODUCT_NAME, 5);
dmi_printk(("Version %s.\n",
dmi_string(dm, data[6])));
dmi_save_ident(dm, DMI_PRODUCT_VERSION, 6);
dmi_printk(("Serial Number %s.\n",
dmi_string(dm, data[7])));
}
break;
case 2:
p=dmi_string(dm,data[4]);
if(*p)
{
dmi_printk(("Board Vendor: %s.\n",p));
dmi_save_ident(dm, DMI_BOARD_VENDOR, 4);
dmi_printk(("Board Name: %s.\n",
dmi_string(dm, data[5])));
dmi_save_ident(dm, DMI_BOARD_NAME, 5);
dmi_printk(("Board Version: %s.\n",
dmi_string(dm, data[6])));
dmi_save_ident(dm, DMI_BOARD_VERSION, 6);
}
break;
case 3:
p=dmi_string(dm,data[8]);
if(*p && *p!=' ')
dmi_printk(("Asset Tag: %s.\n", p));
break;
}
}
static int __init dmi_scan_machine(void)
{
int err = dmi_iterate(dmi_decode);
if(err == 0)
dmi_check_blacklist();
return err;
}
module_init(dmi_scan_machine);
|
|
From: James S. <jsi...@us...> - 2001-10-06 16:25:03
|
Update of /cvsroot/linuxconsole/ruby/linux/fs/proc In directory usw-pr-cvs1:/tmp/cvs-serv28674 Removed Files: kmsg.c Log Message: Changes in standard tree. --- kmsg.c DELETED --- |
|
From: James S. <jsi...@us...> - 2001-10-06 16:21:25
|
Update of /cvsroot/linuxconsole/ruby/linux/arch/sparc/lib In directory usw-pr-cvs1:/tmp/cvs-serv28089 Removed Files: debuglocks.c Log Message: Changes in standard tree. --- debuglocks.c DELETED --- |