All of lore.kernel.org
 help / color / mirror / Atom feed
* (no subject)
@ 2002-03-13 19:21 Romain Liévin
  2002-03-13 19:43 ` your mail Alan Cox
  2002-03-14  7:08 ` your mail Zwane Mwaikambo
  0 siblings, 2 replies; 14+ messages in thread
From: Romain Liévin @ 2002-03-13 19:21 UTC (permalink / raw)
  To: Kernel List; +Cc: Linus Torvalds, Alan Cox, Tim Waugh

This is a new driver which uses parport for handling a parallel link cable 
designed to connect a Texas Instruments graphing calculators to a 
computer/workstation.
It has been tested on x86 for almost 2 years and on Alpha & Sparc too with 
various calculators.

BTW, a such driver was requested on SlashDot in 1999.
I also have 2 similar drivers I will submit: one for the serial cable, the 
other for the USB cable.

==============================[ cut here ]==============================
--- linux.orig/MAINTAINERS      Wed Mar 13 18:30:35 2002
+++ linux/MAINTAINERS   Wed Mar 13 19:07:55 2002
@@ -1502,6 +1502,13 @@
 M:     hch@infradead.org
 S:     Maintained
 
+TI PARALLEL LINK CABLE DRIVER
+P:     Romain Lievin
+M:     roms@lpg.ticalc.org
+P:     Julien Blache
+M:     jb@technologeek.org
+S:     Maintained
+
 TLAN NETWORK DRIVER
 P:     Torben Mathiasen
 M:     torben.mathiasen@compaq.com
--- linux.orig/drivers/char/tipar.c     Wed Mar 13 19:19:10 2002
+++ linux/drivers/char/tipar.c  Wed Mar 13 20:12:37 2002
@@ -0,0 +1,541 @@
+/* Hey EMACS -*- linux-c -*-
+ *
+ * tipar - low level driver for handling a parallel link cable
+ * designed for Texas Instruments graphing calculators.
+ *
+ * Copyright (C) 2000-2002, Romain Lievin <roms@lpg.ticalc.org>
+ * under the terms of the GNU General Public License.
+ */
+
+#define VERSION "1.11"
+
+/* This driver should, in theory, work with any parallel port that has an
+ * appropriate low-level driver; all I/O is done through the parport
+ * abstraction layer.
+ *
+ * If this driver is built into the kernel, you can configure it using the
+ * kernel command-line.  For example:
+ *
+ *      tipar=timeout,delay       (set timeout and delay)
+ *
+ * If the driver is loaded as a module, similar functionality is available
+ * using module parameters.  The equivalent of the above commands would be:
+ *
+ *      # insmod tipar.o tipar=15,10
+ */
+
+/* COMPATIBILITY WITH OLD KERNELS
+ *
+ * Usually, parallel cables were bound to ports at
+ * particular I/O addresses, as follows:
+ *
+ *      tipar0             0x378
+ *      tipar1             0x278
+ *      tipar2             0x3bc
+ *
+ *
+ * This driver, by default, binds tipar devices according to parport and
+ * the minor number.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/config.h>
+#include <linux/version.h>
+#include <linux/init.h>
+#include <asm/uaccess.h>
+#include <linux/ioport.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <asm/io.h>
+#include <linux/poll.h>
+#include <linux/devfs_fs_kernel.h>
+#include <linux/parport.h> /* Our code depend on parport */
+
+/*
+ * TI definitions
+ */
+#include <linux/ticable.h>
+
+/*
+ * Deal with CONFIG_MODVERSIONS
+ */
+#if 0 /* Pb with MODVERSIONS */
+#if CONFIG_MODVERSIONS==1
+#define MODVERSIONS
+#include <linux/modversions.h>
+#endif
+#endif
+
+/* ----- global variables --------------------------------------------- */
+
+struct tipar_struct {
+       struct pardevice *dev;                  /* Parport device entry */
+};
+
+#define PP_NO 3
+struct tipar_struct  table[PP_NO];
+
+static int delay   = IO_DELAY;      /* inter-bit delay in microseconds */
+static int timeout = TIMAXTIME;     /* timeout in tenth of seconds     */
+
+static devfs_handle_t devfs_handle = NULL;
+static unsigned int tp_count = 0;   /* tipar_count */
+
+/* --- macros for parport access -------------------------------------- */
+
+#define r_dtr(x)        (parport_read_data(table[(x)].dev->port))
+#define r_str(x)        (parport_read_status(table[(x)].dev->port))
+#define w_ctr(x,y)      (parport_write_control(table[(x)].dev->port, (y)))
+#define w_dtr(x,y)      (parport_write_data(table[(x)].dev->port, (y)))
+
+/* --- setting states on the D-bus with the right timing: ------------- */
+
+static inline void outbyte(int value, int minor)
+{
+       w_dtr(minor, value);
+}
+
+static inline int inbyte(int minor)
+{
+       return (r_str(minor) & 0x30);
+}
+
+static inline void init_ti_parallel(int minor)
+{
+       outbyte(3, minor);
+}
+
+/* ----- global defines ----------------------------------------------- */
+
+#define START(x) { max=jiffies+HZ/(timeout/10); }
+#define WAIT(x) { if(!time_before(jiffies, (x))) return -1; schedule(); }
+
+/* ----- D-bus bit-banging functions ---------------------------------- */
+
+/* D-bus protocol:
+                    1                 0                      0
+       _______        ______|______    __________|________    __________
+Red  :        ________      |      ____          |        ____
+       _        ____________|________      ______|__________       _____
+White:  ________            |        ______      |          _______
+*/
+
+/* Try to transmit a byte on the specified port (-1 if error). */
+static int put_ti_parallel(int minor, unsigned char data)
+{
+       int bit, i;
+       unsigned long max;
+  
+       for (bit=0; bit<8; bit++) {
+               if (data & 1) {
+                       outbyte(2, minor);
+                       START(max); 
+                       do {
+                               WAIT(max);
+                       } while (inbyte(minor) & 0x10);
+                       
+                       outbyte(3, minor);
+                       START(max);
+                       do {
+                               WAIT(max);
+                       } while (!(inbyte(minor) & 0x10));
+               } else {
+                       outbyte(1, minor);
+                       START(max);
+                       do {
+                               WAIT(max);
+                       } while (inbyte(minor) & 0x20);
+                       
+                       outbyte(3, minor);
+                       START(max);
+                       do {
+                               WAIT(max);
+                       } while (!(inbyte(minor) & 0x20));
+               }
+               data >>= 1;
+               for(i=0; i < delay; i++) {
+                       inbyte(minor);
+               }
+               schedule();
+       }
+       
+       return 0;
+}
+
+/* Receive a byte on the specified port or -1 if error. */
+static int get_ti_parallel(int minor)
+{
+       int bit,i;
+       unsigned char v, data=0;
+       unsigned long max;
+
+       for (bit=0; bit<8; bit++) {
+               START(max); 
+               do {
+                       WAIT(max);
+               } while ((v=inbyte(minor) & 0x30) == 0x30);
+      
+               if (v == 0x10) { 
+                       data=(data>>1) | 0x80;
+                       outbyte(1, minor);
+                       START(max);
+                       do {
+                               WAIT(max);
+                       } while (!(inbyte(minor) & 0x20));
+                       outbyte(3, minor);
+               } else {
+                       data=data>>1;
+                       outbyte(2, minor);
+                       START(max);
+                       do {
+                               WAIT(max);
+                       } while (!(inbyte(minor) & 0x10));
+                       outbyte(3, minor);
+               }
+               for(i=0; i<delay; i++) {
+                       inbyte(minor);
+               }
+               schedule();
+       }
+       return (int)data;
+}
+
+/* Return non zero if both lines are at logical one */
+static int check_ti_parallel(int minor)
+{
+       return ((inbyte(minor) & 0x30) == 0x30);
+}
+
+/* Try to detect a parallel link cable on the specified port */
+static int probe_ti_parallel(int minor)
+{
+       int i, j;
+       int seq[]={ 0x00, 0x20, 0x10, 0x30 };
+       unsigned char data = 0;
+       
+       for(i=3; i>=0; i--) {
+               outbyte(3, minor);
+               outbyte(i, minor);
+               for(j=0; j<delay; j++) data = inbyte(minor);
+               /*printk("Probing -> %i: 0x%02x 0x%02x\n", i, data & 0x30,
seq[i]);*/
+               if( (data & 0x30) != seq[i]) {
+                       outbyte(3, minor);
+                       return -1;
+               }
+       } 
+       outbyte(3, minor);
+       return 0;
+}
+
+/* ----- kernel module functions--------------------------------------- */
+
+static int tipar_open(struct inode *inode, struct file *file)
+{
+       unsigned int minor = minor(inode->i_rdev) - TIPAR_MINOR_0;
+
+       if (minor >= PP_NO)
+               return -ENXIO;  
+       
+       init_ti_parallel(minor);
+
+       MOD_INC_USE_COUNT;
+       
+       return 0;
+}
+
+static int tipar_close(struct inode *inode, struct file *file)
+{
+       MOD_DEC_USE_COUNT;
+       
+       return 0;
+}
+
+static ssize_t tipar_write(struct file *file,
+                          const char *buf, size_t count, loff_t *ppos)
+{
+       unsigned int minor = minor(file->f_dentry->d_inode->i_rdev) - 
+               TIPAR_MINOR_0;
+       ssize_t n;
+  
+       if (minor >= PP_NO)
+               return -ENXIO;
+
+       if (table[minor].dev == NULL) 
+               return -ENXIO;
+
+       parport_claim_or_block (table[minor].dev);
+       
+       for(n=0; n<count; n++) {
+               unsigned char b;
+               
+               if(get_user(b, buf + n)) {
+                       n = -EFAULT;
+                       goto out;
+               }
+
+               if(put_ti_parallel(minor, b) == -1) {
+                       init_ti_parallel(minor);
+                       n = -ETIMEDOUT;
+                       goto out;
+               }
+       }
+
+ out:
+       parport_release (table[minor].dev);
+       return n;
+}
+
+static ssize_t tipar_read(struct file *file, char *buf, 
+                         size_t count, loff_t *ppos)
+{
+       int b=0;
+       unsigned int minor=minor(file->f_dentry->d_inode->i_rdev) - 
+               TIPAR_MINOR_0;
+       ssize_t retval = 0;
+
+       if(count == 0)
+               return 0;
+
+       if(ppos != &file->f_pos)
+               return -ESPIPE;
+
+       parport_claim_or_block(table[minor].dev);
+  
+       do {
+               b = get_ti_parallel(minor);
+               if(b == -1) {
+                       init_ti_parallel(minor);
+                       retval = -ETIMEDOUT;
+                       goto out;
+               }
+               else
+                       break;
+      
+               /* Non-blocking mode: try again ! */
+               if (file->f_flags & O_NONBLOCK) {
+                       retval = -EAGAIN;
+                       goto out;
+               }
+               
+               /* Signal pending, try again ! */
+               if (signal_pending(current)) {
+                       retval = -ERESTARTSYS;
+                       goto out;
+               }
+
+               schedule();
+       } while (1);
+
+       retval = put_user(b, (unsigned char *)buf);
+       if(!retval)
+               retval = 1;
+       else
+               retval = -EFAULT;
+
+ out:
+       parport_release(table[minor].dev);
+       return retval;
+}
+
+static unsigned int tipar_poll(struct file *file, poll_table * wait)
+{
+       unsigned int mask=0;
+       return mask;
+}
+
+static int tipar_ioctl(struct inode *inode, struct file *file,
+                      unsigned int cmd, unsigned long arg)
+{
+       unsigned int minor = minor(inode->i_rdev) - TIPAR_MINOR_0;
+       int retval = 0;
+
+       if (minor >= PP_NO) 
+               return -ENODEV;
+
+       switch (cmd) {
+       case 0:
+               break;
+       case TIPAR_DELAY:
+               delay = arg;
+               return 0;
+       case TIPAR_TIMEOUT:
+               timeout = arg;
+               return 0;
+       case O_NONBLOCK:
+               file->f_flags |= O_NONBLOCK;
+               return 0;
+       default:
+               retval = -EINVAL;
+               break;
+       }
+
+       return retval;
+}
+
+static long long tipar_lseek(struct file * file, long long offset, int origin)
+{
+       return -ESPIPE;
+}
+
+
+/* ----- kernel module registering ------------------------------------ */
+
+static struct file_operations tipar_fops = {
+       owner:   THIS_MODULE,
+       llseek:  tipar_lseek,
+       read:    tipar_read,
+       write:   tipar_write,
+       poll:    tipar_poll,
+       ioctl:   tipar_ioctl,
+       open:    tipar_open,
+       release: tipar_close,
+};
+
+/* --- initialisation code ------------------------------------- */
+
+#ifndef MODULE
+/*      You must set these - there is no sane way to probe for this cable.
+ *      You can use tipar=timeout,delay to set these now. */
+static int __init tipar_setup (char *str)
+{
+       int ints[2];
+
+        str = get_options (str, ARRAY_SIZE(ints), ints);
+
+        if (ints[0] > 0) {
+                timeout = ints[1];
+                if(ints[0] > 1) {
+                        delay = ints[2];
+               }
+        }
+        return 1;
+}
+#endif
+
+/*
+ * Register our module into parport.
+ * Pass also 2 callbacks functions to parport: a pre-emptive function and an
+ * interrupt handler function (unused).
+ * Display a message such "tipar0: using parport0 (polling)".
+ */
+static int tipar_register(int nr, struct parport *port)
+{
+       char name[8];
+       
+       /* Register our module into parport */
+       table[nr].dev = parport_register_device(port, "tipar",
+                                               NULL, NULL, NULL, 0,
+                                               (void *) &table[nr]);
+       
+       if (table[nr].dev == NULL)
+               return 1;
+ 
+       /* Use devfs, tree: /dev/ticables/par/[0..2] */
+       sprintf(name, "%d", nr);
+       devfs_register(devfs_handle, name,
+                       DEVFS_FL_AUTO_DEVNUM, TIPAR_MAJOR, nr,
+                       S_IFCHR | S_IRUGO | S_IWUGO,
+                       &tipar_fops, NULL);
+
+       /* Display informations */
+       printk(KERN_INFO "tipar%d: using %s (%s).\n", nr, port->name,
+              (port->irq == PARPORT_IRQ_NONE) ? "polling" :
"interrupt-driven");
+
+       if(probe_ti_parallel(nr) != -1)
+               printk("tipar%d: link cable found !\n", nr);
+       else
+               printk("tipar%d: link cable not found (do not plug cable to
calc).\n", nr);
+
+       return 0;
+}
+
+static void tipar_attach (struct parport *port)
+{
+       if (tp_count == PP_NO) {
+               printk("tipar: ignoring parallel port (max. %d)\n", 
+                      PP_NO);
+               return;
+       }
+       if (!tipar_register(tp_count, port))
+               tp_count++;
+}
+
+static void tipar_detach (struct parport *port)
+{
+       /* Will be written at some point in the future */
+}
+
+static struct parport_driver tipar_driver = {
+       "tipar",
+       tipar_attach,
+       tipar_detach,
+       NULL
+};
+
+int tipar_init(void)
+{
+       unsigned int i;
+       
+       /* Initialize structure */
+       for (i = 0; i < PP_NO; i++) {
+               table[i].dev = NULL;
+       }
+
+       /* Register parport device */  
+       if (devfs_register_chrdev (TIPAR_MAJOR, "tipar", &tipar_fops)) {
+               printk("tipar: unable to get major %d\n", TIPAR_MAJOR);
+               return -EIO;
+       }
+
+       /* Use devfs with tree: /dev/ticables/par/[0..2] */
+       devfs_handle = devfs_mk_dir (NULL, "ticables/par", NULL);
+
+       if (parport_register_driver (&tipar_driver)) {
+               printk ("tipar: unable to register with parport\n");
+               return -EIO;
+       }
+
+       return 0;
+}  
+
+int __init tipar_init_module(void)
+{
+       printk("tipar: parallel link cable driver, version %s\n", VERSION);
+       return tipar_init();
+}
+
+void __exit tipar_cleanup_module(void)
+{
+       unsigned int offset;
+
+       /* Unregistering module */
+       parport_unregister_driver (&tipar_driver);
+
+       devfs_unregister (devfs_handle);
+       devfs_unregister_chrdev(TIPAR_MAJOR, "tipar");  
+
+       for (offset = 0; offset < PP_NO; offset++) {
+               if (table[offset].dev == NULL)
+                       continue;
+               parport_unregister_device(table[offset].dev);
+       }
+}
+
+__setup("tipar=", tipar_setup);
+module_init(tipar_init_module);
+module_exit(tipar_cleanup_module);
+
+MODULE_AUTHOR("Author/Maintainer: Romain Lievin <roms@lpg.ticalc.org>");
+MODULE_DESCRIPTION("Device driver for TI/PC parallel link cables");
+MODULE_LICENSE("GPL");
+
+EXPORT_NO_SYMBOLS;
+
+MODULE_PARM(timeout, "i");
+MODULE_PARM_DESC(timeout, "Timeout, default=1.5 seconds");
+MODULE_PARM(delay, "i");
+MODULE_PARM_DESC(delay, "Inter-bit delay, default=10 microseconds");
--- linux.orig/include/linux/ticable.h  Wed Mar 13 19:42:30 2002
+++ linux/include/linux/ticable.h       Wed Mar 13 19:09:57 2002
@@ -0,0 +1,41 @@
+/* Hey EMACS -*- linux-c -*-
+ *
+ * tipar/tiser/tiglusb - low level driver for handling link cables
+ * designed for Texas Instruments graphing calculators.
+ *
+ * Copyright (C) 2000-2002, Romain Lievin <roms@lpg.ticalc.org>
+ * under the terms of the GNU General Public License.
+ */
+
+#ifndef TICABLE_H 
+#define TICABLE_H 1
+
+/* Internal default constants for the kernel module */
+#define TIMAXTIME 10      /* 1 seconds                         */
+#define IO_DELAY  10      /* 10 micro-seconds  */
+
+/* Major & minor number for character devices */
+#define TIPAR_MAJOR   61
+#define TIPAR_MINOR_0  1
+#define TIPAR_MINOR_1  2
+#define TIPAR_MINOR_2  3
+
+#define TISER_MAJOR   62
+#define TISER_MINOR_0  1
+#define TISER_MINOR_1  2
+#define TISER_MINOR_2  3
+#define TISER_MINOR_3  4
+
+/*
+ * Request values for the 'ioctl' function.
+ * Simply pass the appropriate value as arg of the ioctl call.
+ * These values do not conflict with other ones but they have to be
+ * allocated... (/usr/src/linux/Documentation/ioctl-number.txt).
+ */
+#define TIPAR_DELAY     _IOW('p', 0xa8, int) /* set delay   */
+#define TIPAR_TIMEOUT   _IOW('p', 0xa9, int) /* set timeout */
+
+#define TISER_DELAY     _IOW('p', 0xa0, int) /* set delay   */
+#define TISER_TIMEOUT   _IOW('p', 0xa1, int) /* set timeout */
+
+#endif /* TICABLE_H */
--- linux.orig/drivers/char/Config.help Fri Mar  8 03:18:28 2002
+++ linux/drivers/char/Config.help      Wed Mar 13 19:08:42 2002
@@ -595,6 +595,27 @@
 
   If unsure, say N.
 
+CONFIG_TI_PAR
+  If you own a Texas Instruments graphing calculator and use a
+  parallel link cable, then you might be interested in this driver.
+
+  If you enable this driver, you will be able to communicate with
+  your calculator through a set of device nodes under /dev. The
+  main advantage of this driver is that you don't have to be root
+  to use this precise link cable (depending on the permissions on
+  the device nodes, though).
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called tipar.o. If you want to compile it as a
+  module, say M here and read Documentation/modules.txt.
+
+  If you don't know what a parallel link cable is or what a Texas
+  Instruments graphing calculator is, then you probably don't need this
+  driver.
+
+  If unsure, say N.
+
 CONFIG_BUSMOUSE
   Say Y here if your machine has a bus mouse as opposed to a serial
   mouse. Most people have a regular serial MouseSystem or
--- linux.orig/drivers/char/Config.in   Fri Mar  8 03:18:17 2002
+++ linux/drivers/char/Config.in        Wed Mar 13 19:09:13 2002
@@ -103,6 +103,7 @@
       bool '  Support for console on line printer' CONFIG_LP_CONSOLE
    fi
    dep_tristate 'Support for user-space parallel port device drivers'
CONFIG_PPDEV $CONFIG_PARPORT
+   dep_tristate 'Texas Instruments parallel link cable support' CONFIG_TI_PAR
$CONFIG_PARPORT
 fi
 
 source drivers/i2c/Config.in
--- linux.orig/drivers/char/Makefile    Fri Mar  8 03:18:27 2002
+++ linux/drivers/char/Makefile Wed Mar 13 19:09:28 2002
@@ -16,7 +16,7 @@
 
 O_TARGET := char.o
 
-obj-y   += mem.o tty_io.o n_tty.o tty_ioctl.o raw.o pty.o misc.o random.o
+obj-y   += mem.o tty_io.o n_tty.o tty_ioctl.o raw.o pty.o misc.o random.o
tipar.o
 
 # All of the (potential) objects that export symbols.
 # This list comes from 'grep -l EXPORT_SYMBOL *.[hc]'.

Romain.

---
Romain Liévin (aka roms)
http://lpg.ticalc.org/prj_tilp, prj_usb, prj_tidev, prj_gtktiemu
mail: roms@lpg.ticalc.org

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: your mail
  2002-03-13 19:21 Romain Liévin
@ 2002-03-13 19:43 ` Alan Cox
  2002-03-13 20:28   ` Romain Liévin
  2002-03-14  7:08 ` your mail Zwane Mwaikambo
  1 sibling, 1 reply; 14+ messages in thread
From: Alan Cox @ 2002-03-13 19:43 UTC (permalink / raw)
  To: Romain Liévin; +Cc: Kernel List, Linus Torvalds, Alan Cox, Tim Waugh

> It has been tested on x86 for almost 2 years and on Alpha & Sparc too with 
> various calculators.

One oddity - some other comments

> +static int tipar_open(struct inode *inode, struct file *file)
> +{
> +       unsigned int minor = minor(inode->i_rdev) - TIPAR_MINOR_0;
> +
> +       if (minor >= PP_NO)
> +               return -ENXIO;  
> +       
> +       init_ti_parallel(minor);
> +
> +       MOD_INC_USE_COUNT;

You should remove these and use in 2.4 + . Also what stops multiple
simultaneous runs of init_ti_parallel if two people open it at once ?


> +static unsigned int tipar_poll(struct file *file, poll_table * wait)
> +{
> +       unsigned int mask=0;
> +       return mask;
> +}

That seems unfinished ??

> +static int tipar_ioctl(struct inode *inode, struct file *file,
> +                      unsigned int cmd, unsigned long arg)
> +       case O_NONBLOCK:
> +               file->f_flags |= O_NONBLOCK;
> +               return 0;

O_NDELAY is set by fcntl - your driver never needs this.

> +       default:
> +               retval = -EINVAL;

SuS says -ENOTTY here (lots of drivers get this wrong still)

> +static long long tipar_lseek(struct file * file, long long offset, int origin)
> +{
> +       return -ESPIPE;
> +}

There is a generic no_llseek function

> +/* Major & minor number for character devices */
> +#define TIPAR_MAJOR   61

These don't appear to be officially assigned via lanana ?

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: your mail
  2002-03-13 19:43 ` your mail Alan Cox
@ 2002-03-13 20:28   ` Romain Liévin
  2002-03-13 20:49     ` Richard B. Johnson
  2002-03-13 22:35     ` Alan Cox
  0 siblings, 2 replies; 14+ messages in thread
From: Romain Liévin @ 2002-03-13 20:28 UTC (permalink / raw)
  To: Alan Cox; +Cc: Kernel List

Quoting Alan Cox <alan@lxorguk.ukuu.org.uk>:

> > It has been tested on x86 for almost 2 years and on Alpha & Sparc too
> with 
> > various calculators.
> 
> One oddity - some other comments
> 
> > +static int tipar_open(struct inode *inode, struct file *file)
> > +{
> > +       unsigned int minor = minor(inode->i_rdev) - TIPAR_MINOR_0;
> > +
> > +       if (minor >= PP_NO)
> > +               return -ENXIO;  
> > +       
> > +       init_ti_parallel(minor);
> > +
> > +       MOD_INC_USE_COUNT;
> 
> You should remove these and use in 2.4 + . Also what stops multiple
> simultaneous runs of init_ti_parallel if two people open it at once ?
> 
> 
> > +static unsigned int tipar_poll(struct file *file, poll_table *
> wait)
> > +{
> > +       unsigned int mask=0;
> > +       return mask;
> > +}
> 
> That seems unfinished ??
> 
> > +static int tipar_ioctl(struct inode *inode, struct file *file,
> > +                      unsigned int cmd, unsigned long arg)
> > +       case O_NONBLOCK:
> > +               file->f_flags |= O_NONBLOCK;
> > +               return 0;
> 
> O_NDELAY is set by fcntl - your driver never needs this.
> 
> > +       default:
> > +               retval = -EINVAL;
> 
> SuS says -ENOTTY here (lots of drivers get this wrong still)
> 
> > +static long long tipar_lseek(struct file * file, long long offset,
> int origin)
> > +{
> > +       return -ESPIPE;
> > +}
> 
> There is a generic no_llseek function
> 
> > +/* Major & minor number for character devices */
> > +#define TIPAR_MAJOR   61
> 
> These don't appear to be officially assigned via lanana ?
> -
> To unsubscribe from this list: send the line "unsubscribe linux-kernel"
> in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/
> 

Fixed some stuffs according to your remarks.

Comments are welcome...

=================== [ cuts here ] =====================
--- linux.orig/drivers/char/tipar.c     Wed Mar 13 19:19:10 2002
+++ linux/drivers/char/tipar.c  Wed Mar 13 21:24:51 2002
@@ -0,0 +1,543 @@
+/* Hey EMACS -*- linux-c -*-
+ *
+ * tipar - low level driver for handling a parallel link cable
+ * designed for Texas Instruments graphing calculators.
+ *
+ * Copyright (C) 2000-2002, Romain Lievin <roms@lpg.ticalc.org>
+ * under the terms of the GNU General Public License.
+ */
+
+#define VERSION "1.12"
+
+/* This driver should, in theory, work with any parallel port that has an
+ * appropriate low-level driver; all I/O is done through the parport
+ * abstraction layer.
+ *
+ * If this driver is built into the kernel, you can configure it using the
+ * kernel command-line.  For example:
+ *
+ *      tipar=timeout,delay       (set timeout and delay)
+ *
+ * If the driver is loaded as a module, similar functionality is available
+ * using module parameters.  The equivalent of the above commands would be:
+ *
+ *      # insmod tipar.o tipar=15,10
+ */
+
+/* COMPATIBILITY WITH OLD KERNELS
+ *
+ * Usually, parallel cables were bound to ports at
+ * particular I/O addresses, as follows:
+ *
+ *      tipar0             0x378
+ *      tipar1             0x278
+ *      tipar2             0x3bc
+ *
+ *
+ * This driver, by default, binds tipar devices according to parport and
+ * the minor number.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/config.h>
+#include <linux/version.h>
+#include <linux/init.h>
+#include <asm/uaccess.h>
+#include <linux/ioport.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <asm/io.h>
+#include <linux/devfs_fs_kernel.h>
+#include <linux/parport.h> /* Our code depend on parport */
+
+/*
+ * TI definitions
+ */
+#include <linux/ticable.h>
+
+/*
+ * Deal with CONFIG_MODVERSIONS
+ */
+#if 0 /* Pb with MODVERSIONS */
+#if CONFIG_MODVERSIONS==1
+#define MODVERSIONS
+#include <linux/modversions.h>
+#endif
+#endif
+
+/* ----- global variables --------------------------------------------- */
+
+struct tipar_struct {
+       struct pardevice *dev;                  /* Parport device entry */
+       int opened;
+};
+
+#define PP_NO 3
+struct tipar_struct  table[PP_NO];
+
+static int delay   = IO_DELAY;      /* inter-bit delay in microseconds */
+static int timeout = TIMAXTIME;     /* timeout in tenth of seconds     */
+
+static devfs_handle_t devfs_handle = NULL;
+static unsigned int tp_count = 0;   /* tipar_count */
+
+/* --- macros for parport access -------------------------------------- */
+
+#define r_dtr(x)        (parport_read_data(table[(x)].dev->port))
+#define r_str(x)        (parport_read_status(table[(x)].dev->port))
+#define w_ctr(x,y)      (parport_write_control(table[(x)].dev->port, (y)))
+#define w_dtr(x,y)      (parport_write_data(table[(x)].dev->port, (y)))
+
+/* --- setting states on the D-bus with the right timing: ------------- */
+
+static inline void outbyte(int value, int minor)
+{
+       w_dtr(minor, value);
+}
+
+static inline int inbyte(int minor)
+{
+       return (r_str(minor) & 0x30);
+}
+
+static inline void init_ti_parallel(int minor)
+{
+       outbyte(3, minor);
+}
+
+/* ----- global defines ----------------------------------------------- */
+
+#define START(x) { max=jiffies+HZ/(timeout/10); }
+#define WAIT(x) { if(!time_before(jiffies, (x))) return -1; schedule(); }
+
+/* ----- D-bus bit-banging functions ---------------------------------- */
+
+/* D-bus protocol:
+                    1                 0                      0
+       _______        ______|______    __________|________    __________
+Red  :        ________      |      ____          |        ____
+       _        ____________|________      ______|__________       _____
+White:  ________            |        ______      |          _______
+*/
+
+/* Try to transmit a byte on the specified port (-1 if error). */
+static int put_ti_parallel(int minor, unsigned char data)
+{
+       int bit, i;
+       unsigned long max;
+  
+       for (bit=0; bit<8; bit++) {
+               if (data & 1) {
+                       outbyte(2, minor);
+                       START(max); 
+                       do {
+                               WAIT(max);
+                       } while (inbyte(minor) & 0x10);
+                       
+                       outbyte(3, minor);
+                       START(max);
+                       do {
+                               WAIT(max);
+                       } while (!(inbyte(minor) & 0x10));
+               } else {
+                       outbyte(1, minor);
+                       START(max);
+                       do {
+                               WAIT(max);
+                       } while (inbyte(minor) & 0x20);
+                       
+                       outbyte(3, minor);
+                       START(max);
+                       do {
+                               WAIT(max);
+                       } while (!(inbyte(minor) & 0x20));
+               }
+               data >>= 1;
+               for(i=0; i < delay; i++) {
+                       inbyte(minor);
+               }
+               schedule();
+       }
+       
+       return 0;
+}
+
+/* Receive a byte on the specified port or -1 if error. */
+static int get_ti_parallel(int minor)
+{
+       int bit,i;
+       unsigned char v, data=0;
+       unsigned long max;
+
+       for (bit=0; bit<8; bit++) {
+               START(max); 
+               do {
+                       WAIT(max);
+               } while ((v=inbyte(minor) & 0x30) == 0x30);
+      
+               if (v == 0x10) { 
+                       data=(data>>1) | 0x80;
+                       outbyte(1, minor);
+                       START(max);
+                       do {
+                               WAIT(max);
+                       } while (!(inbyte(minor) & 0x20));
+                       outbyte(3, minor);
+               } else {
+                       data=data>>1;
+                       outbyte(2, minor);
+                       START(max);
+                       do {
+                               WAIT(max);
+                       } while (!(inbyte(minor) & 0x10));
+                       outbyte(3, minor);
+               }
+               for(i=0; i<delay; i++) {
+                       inbyte(minor);
+               }
+               schedule();
+       }
+       return (int)data;
+}
+
+/* Return non zero if both lines are at logical one */
+static int check_ti_parallel(int minor)
+{
+       return ((inbyte(minor) & 0x30) == 0x30);
+}
+
+/* Try to detect a parallel link cable on the specified port */
+static int probe_ti_parallel(int minor)
+{
+       int i, j;
+       int seq[]={ 0x00, 0x20, 0x10, 0x30 };
+       unsigned char data = 0;
+       
+       for(i=3; i>=0; i--) {
+               outbyte(3, minor);
+               outbyte(i, minor);
+               for(j=0; j<delay; j++) data = inbyte(minor);
+               /*printk("Probing -> %i: 0x%02x 0x%02x\n", i, data & 0x30,
seq[i]);*/
+               if( (data & 0x30) != seq[i]) {
+                       outbyte(3, minor);
+                       return -1;
+               }
+       } 
+       outbyte(3, minor);
+       return 0;
+}
+
+/* ----- kernel module functions--------------------------------------- */
+
+static int tipar_open(struct inode *inode, struct file *file)
+{
+       unsigned int minor = minor(inode->i_rdev) - TIPAR_MINOR_0;
+
+       if (minor >= PP_NO)
+               return -ENXIO;
+
+       if(table[minor].opened)
+               return -EBUSY;
+
+       table[minor].opened++;
+
+       lp_claim_parport_or_block(table[minor].dev);
+       init_ti_parallel(minor);
+       lp_release_parport(table[minor].dev);
+
+       return 0;
+}
+
+static int tipar_close(struct inode *inode, struct file *file)
+{
+       if (minor >= PP_NO)
+               return -ENXIO;
+
+       if(!table[minor].opened)
+               return -EFAULT;
+
+       table[minor].opened--;
+
+       return 0;
+}
+
+static ssize_t tipar_write(struct file *file,
+                          const char *buf, size_t count, loff_t *ppos)
+{
+       unsigned int minor = minor(file->f_dentry->d_inode->i_rdev) - 
+               TIPAR_MINOR_0;
+       ssize_t n;
+  
+       if (minor >= PP_NO)
+               return -ENXIO;
+
+       if (table[minor].dev == NULL) 
+               return -ENXIO;
+
+       parport_claim_or_block (table[minor].dev);
+       
+       for(n=0; n<count; n++) {
+               unsigned char b;
+               
+               if(get_user(b, buf + n)) {
+                       n = -EFAULT;
+                       goto out;
+               }
+
+               if(put_ti_parallel(minor, b) == -1) {
+                       init_ti_parallel(minor);
+                       n = -ETIMEDOUT;
+                       goto out;
+               }
+       }
+
+ out:
+       parport_release (table[minor].dev);
+       return n;
+}
+
+static ssize_t tipar_read(struct file *file, char *buf, 
+                         size_t count, loff_t *ppos)
+{
+       int b=0;
+       unsigned int minor=minor(file->f_dentry->d_inode->i_rdev) - 
+               TIPAR_MINOR_0;
+       ssize_t retval = 0;
+
+       if(count == 0)
+               return 0;
+
+       if(ppos != &file->f_pos)
+               return -ESPIPE;
+
+       parport_claim_or_block(table[minor].dev);
+  
+       do {
+               b = get_ti_parallel(minor);
+               if(b == -1) {
+                       init_ti_parallel(minor);
+                       retval = -ETIMEDOUT;
+                       goto out;
+               }
+               else
+                       break;
+      
+               /* Non-blocking mode: try again ! */
+               if (file->f_flags & O_NONBLOCK) {
+                       retval = -EAGAIN;
+                       goto out;
+               }
+               
+               /* Signal pending, try again ! */
+               if (signal_pending(current)) {
+                       retval = -ERESTARTSYS;
+                       goto out;
+               }
+
+               schedule();
+       } while (1);
+
+       retval = put_user(b, (unsigned char *)buf);
+       if(!retval)
+               retval = 1;
+       else
+               retval = -EFAULT;
+
+ out:
+       parport_release(table[minor].dev);
+       return retval;
+}
+
+static int tipar_ioctl(struct inode *inode, struct file *file,
+                      unsigned int cmd, unsigned long arg)
+{
+       unsigned int minor = minor(inode->i_rdev) - TIPAR_MINOR_0;
+       int retval = 0;
+
+       if (minor >= PP_NO) 
+               return -ENODEV;
+
+       switch (cmd) {
+       case 0:
+               break;
+       case TIPAR_DELAY:
+               delay = arg;
+               return 0;
+       case TIPAR_TIMEOUT:
+               timeout = arg;
+               return 0;
+       default:
+               retval = -ENOTTY;
+               break;
+       }
+
+       return retval;
+}
+
+static long long tipar_lseek(struct file * file, long long offset, int origin)
+{
+       return -ESPIPE;
+}
+
+
+/* ----- kernel module registering ------------------------------------ */
+
+static struct file_operations tipar_fops = {
+       owner:   THIS_MODULE,
+       llseek:  no_llseek,
+       read:    tipar_read,
+       write:   tipar_write,
+       ioctl:   tipar_ioctl,
+       open:    tipar_open,
+       release: tipar_close,
+};
+
+/* --- initialisation code ------------------------------------- */
+
+#ifndef MODULE
+/*      You must set these - there is no sane way to probe for this cable.
+ *      You can use tipar=timeout,delay to set these now. */
+static int __init tipar_setup (char *str)
+{
+       int ints[2];
+
+        str = get_options (str, ARRAY_SIZE(ints), ints);
+
+        if (ints[0] > 0) {
+                timeout = ints[1];
+                if(ints[0] > 1) {
+                        delay = ints[2];
+               }
+        }
+        return 1;
+}
+#endif
+
+/*
+ * Register our module into parport.
+ * Pass also 2 callbacks functions to parport: a pre-emptive function and an
+ * interrupt handler function (unused).
+ * Display a message such "tipar0: using parport0 (polling)".
+ */
+static int tipar_register(int nr, struct parport *port)
+{
+       char name[8];
+       
+       /* Register our module into parport */
+       table[nr].dev = parport_register_device(port, "tipar",
+                                               NULL, NULL, NULL, 0,
+                                               (void *) &table[nr]);
+       
+       if (table[nr].dev == NULL)
+               return 1;
+ 
+       /* Use devfs, tree: /dev/ticables/par/[0..2] */
+       sprintf(name, "%d", nr);
+       devfs_register(devfs_handle, name,
+                       DEVFS_FL_AUTO_DEVNUM, TIPAR_MAJOR, nr,
+                       S_IFCHR | S_IRUGO | S_IWUGO,
+                       &tipar_fops, NULL);
+
+       /* Display informations */
+       printk(KERN_INFO "tipar%d: using %s (%s).\n", nr, port->name,
+              (port->irq == PARPORT_IRQ_NONE) ? "polling" :
"interrupt-driven");
+
+       if(probe_ti_parallel(nr) != -1)
+               printk("tipar%d: link cable found !\n", nr);
+       else
+               printk("tipar%d: link cable not found (do not plug cable to
calc).\n", nr);
+
+       return 0;
+}
+
+static void tipar_attach (struct parport *port)
+{
+       if (tp_count == PP_NO) {
+               printk("tipar: ignoring parallel port (max. %d)\n", 
+                      PP_NO);
+               return;
+       }
+       if (!tipar_register(tp_count, port))
+               tp_count++;
+}
+
+static void tipar_detach (struct parport *port)
+{
+       /* Will be written at some point in the future */
+}
+
+static struct parport_driver tipar_driver = {
+       "tipar",
+       tipar_attach,
+       tipar_detach,
+       NULL
+};
+
+int tipar_init(void)
+{
+       unsigned int i;
+       
+       /* Initialize structure */
+       for (i = 0; i < PP_NO; i++) {
+               table[i].dev = NULL;
+               table[i].opened = 0;
+       }
+
+       /* Register parport device */  
+       if (devfs_register_chrdev (TIPAR_MAJOR, "tipar", &tipar_fops)) {
+               printk("tipar: unable to get major %d\n", TIPAR_MAJOR);
+               return -EIO;
+       }
+
+       /* Use devfs with tree: /dev/ticables/par/[0..2] */
+       devfs_handle = devfs_mk_dir (NULL, "ticables/par", NULL);
+
+       if (parport_register_driver (&tipar_driver)) {
+               printk ("tipar: unable to register with parport\n");
+               return -EIO;
+       }
+
+       return 0;
+}  
+
+int __init tipar_init_module(void)
+{
+       printk("tipar: parallel link cable driver, version %s\n", VERSION);
+       return tipar_init();
+}
+
+void __exit tipar_cleanup_module(void)
+{
+       unsigned int offset;
+
+       /* Unregistering module */
+       parport_unregister_driver (&tipar_driver);
+
+       devfs_unregister (devfs_handle);
+       devfs_unregister_chrdev(TIPAR_MAJOR, "tipar");  
+
+       for (offset = 0; offset < PP_NO; offset++) {
+               if (table[offset].dev == NULL)
+                       continue;
+               parport_unregister_device(table[offset].dev);
+       }
+}
+
+__setup("tipar=", tipar_setup);
+module_init(tipar_init_module);
+module_exit(tipar_cleanup_module);
+
+MODULE_AUTHOR("Author/Maintainer: Romain Lievin <roms@lpg.ticalc.org>");
+MODULE_DESCRIPTION("Device driver for TI/PC parallel link cables");
+MODULE_LICENSE("GPL");
+
+EXPORT_NO_SYMBOLS;
+
+MODULE_PARM(timeout, "i");
+MODULE_PARM_DESC(timeout, "Timeout, default=1.5 seconds");
+MODULE_PARM(delay, "i");
+MODULE_PARM_DESC(delay, "Inter-bit delay, default=10 microseconds");
--- linux.orig/include/linux/ticable.h  Wed Mar 13 19:42:30 2002
+++ linux/include/linux/ticable.h       Wed Mar 13 21:25:03 2002
@@ -0,0 +1,41 @@
+/* Hey EMACS -*- linux-c -*-
+ *
+ * tipar/tiser/tiglusb - low level driver for handling link cables
+ * designed for Texas Instruments graphing calculators.
+ *
+ * Copyright (C) 2000-2002, Romain Lievin <roms@lpg.ticalc.org>
+ * under the terms of the GNU General Public License.
+ */
+
+#ifndef TICABLE_H 
+#define TICABLE_H 1
+
+/* Internal default constants for the kernel module */
+#define TIMAXTIME 10      /* 1 seconds                         */
+#define IO_DELAY  10      /* 10 micro-seconds  */
+
+/* Major & minor number for character devices */
+#define TIPAR_MAJOR   61
+#define TIPAR_MINOR_0  1
+#define TIPAR_MINOR_1  2
+#define TIPAR_MINOR_2  3
+
+#define TISER_MAJOR   62
+#define TISER_MINOR_0  1
+#define TISER_MINOR_1  2
+#define TISER_MINOR_2  3
+#define TISER_MINOR_3  4
+
+/*
+ * Request values for the 'ioctl' function.
+ * Simply pass the appropriate value as arg of the ioctl call.
+ * These values do not conflict with other ones but they have to be
+ * allocated... (/usr/src/linux/Documentation/ioctl-number.txt).
+ */
+#define TIPAR_DELAY     _IOW('p', 0xa8, int) /* set delay   */
+#define TIPAR_TIMEOUT   _IOW('p', 0xa9, int) /* set timeout */
+
+#define TISER_DELAY     _IOW('p', 0xa0, int) /* set delay   */
+#define TISER_TIMEOUT   _IOW('p', 0xa1, int) /* set timeout */
+
+#endif /* TICABLE_H */


Romain.

---
Romain Liévin (aka roms)
http://lpg.ticalc.org/prj_tilp, prj_usb, prj_tidev, prj_gtktiemu
mail: roms@lpg.ticalc.org

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: your mail
  2002-03-13 20:28   ` Romain Liévin
@ 2002-03-13 20:49     ` Richard B. Johnson
  2002-03-13 22:27       ` Alan Cox
  2002-03-13 22:35     ` Alan Cox
  1 sibling, 1 reply; 14+ messages in thread
From: Richard B. Johnson @ 2002-03-13 20:49 UTC (permalink / raw)
  To: Romain Liévin; +Cc: Alan Cox, Kernel List

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: TEXT/PLAIN; charset=US-ASCII, Size: 4611 bytes --]

On Wed, 13 Mar 2002, [ISO-8859-1] Romain Liévin wrote:
I'm going to comment on a few points:

[SNIPPED most...]

> +
> +/* D-bus protocol:
> +                    1                 0                      0
> +       _______        ______|______    __________|________    __________
> +Red  :        ________      |      ____          |        ____
> +       _        ____________|________      ______|__________       _____
> +White:  ________            |        ______      |          _______
> +*/
> +
> +/* Try to transmit a byte on the specified port (-1 if error). */
> +static int put_ti_parallel(int minor, unsigned char data)
> +{
> +       int bit, i;
> +       unsigned long max;
> +  
> +       for (bit=0; bit<8; bit++) {
> +               if (data & 1) {
> +                       outbyte(2, minor);
> +                       START(max); 
> +                       do {
> +                               WAIT(max);
> +                       } while (inbyte(minor) & 0x10);

             This may never happen. You end up waiting forever!
             If the port doesn't exist or is broken, it may return 0xff
             forever! You need to time-out and get out.


> +                       
> +                       outbyte(3, minor);
> +                       START(max);
> +                       do {
> +                               WAIT(max);
> +                       } while (!(inbyte(minor) & 0x10));

                     This may never happen. You end up awiting forever!
                     You need to time-out and get out.


> +               } else {
> +                       outbyte(1, minor);
> +                       START(max);
> +                       do {
> +                               WAIT(max);
> +                       } while (inbyte(minor) & 0x20);
> +                       
                       This also may never happen!
                       Same applies, time-out and get out.
                     
> +                       outbyte(3, minor);
> +                       START(max);
> +                       do {
> +                               WAIT(max);
> +                       } while (!(inbyte(minor) & 0x20));

                      This also may never happen!
                      Same applives, time-out and get out.

> +               }
> +               data >>= 1;
> +               for(i=0; i < delay; i++) {
> +                       inbyte(minor);
> +               }

> +               schedule();

                  This will just spin without setting
                  current->policy |= SCHED_YIELD;
                  (you really should use sys_sched_yield())


> +       }
> +       
> +       return 0;
> +}
> +
> +/* Receive a byte on the specified port or -1 if error. */
> +static int get_ti_parallel(int minor)
> +{
> +       int bit,i;
> +       unsigned char v, data=0;
> +       unsigned long max;
> +
> +       for (bit=0; bit<8; bit++) {
> +               START(max); 
> +               do {
> +                       WAIT(max);
> +               } while ((v=inbyte(minor) & 0x30) == 0x30);
> +      
                  More wait-forever above...

> +               if (v == 0x10) { 
> +                       data=(data>>1) | 0x80;
> +                       outbyte(1, minor);
> +                       START(max);
> +                       do {
> +                               WAIT(max);
> +                       } while (!(inbyte(minor) & 0x20));

                      More wait-forever above.


> +                       outbyte(3, minor);
> +               } else {
> +                       data=data>>1;
> +                       outbyte(2, minor);
> +                       START(max);
> +                       do {
> +                               WAIT(max);
> +                       } while (!(inbyte(minor) & 0x10));
> +                       outbyte(3, minor);
                      More wait-forever!

> +               }
> +               for(i=0; i<delay; i++) {
> +                       inbyte(minor);
> +               }
> +               schedule();
                  No current->policy

> +       }
> +       return (int)data;
> +}
> +

[SNIPPED rest]


Basically, this code performs a needed function. I have been waiting
for someone to write this! However, it's not yet ready for prime-time.
Never assume that hardware is going to produce what you expect. Don't
wait forever for something that was supposed to happen. You'll hang
the machine.


Cheers,
Dick Johnson

Penguin : Linux version 2.4.18 on an i686 machine (797.90 BogoMips).

                 Windows-2000/Professional isn't.


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: your mail
  2002-03-13 20:49     ` Richard B. Johnson
@ 2002-03-13 22:27       ` Alan Cox
  0 siblings, 0 replies; 14+ messages in thread
From: Alan Cox @ 2002-03-13 22:27 UTC (permalink / raw)
  To: root; +Cc: Romain Liévin, Alan Cox, Kernel List

> > +                       START(max);=20
> > +                       do {
> > +                               WAIT(max);
> > +                       } while (inbyte(minor) & 0x10);
> 
>              This may never happen. You end up waiting forever!

No - its hidden in his macros. Look harder



^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: your mail
  2002-03-13 20:28   ` Romain Liévin
  2002-03-13 20:49     ` Richard B. Johnson
@ 2002-03-13 22:35     ` Alan Cox
  2002-03-16 15:06       ` your mail, [PATCH] tipar Romain Liévin
  1 sibling, 1 reply; 14+ messages in thread
From: Alan Cox @ 2002-03-13 22:35 UTC (permalink / raw)
  To: Romain Liévin; +Cc: Alan Cox, Kernel List

> +/*
> + * Deal with CONFIG_MODVERSIONS
> + */
> +#if 0 /* Pb with MODVERSIONS */
> +#if CONFIG_MODVERSIONS==1
> +#define MODVERSIONS
> +#include <linux/modversions.h>
> +#endif
> +#endif

[modversions.h is magically included by the kernel for you when its in 
 kernel if you haven't worked that one out yet]

> +#define PP_NO 3
> +struct tipar_struct  table[PP_NO];
static ?

> +               for(i=0; i < delay; i++) {
> +                       inbyte(minor);
> +               }
> +               schedule();

Oh random tip

		  if(current->need_resched)
			schedule();

will just give up the CPU when you are out of time

> +       if(table[minor].opened)
> +               return -EBUSY;
> +       table[minor].opened++;

Think about open/close at the same moment or SMP - the watchdog drivers all
had this problem and now do

	unsigned long opened = 0;

	if(test_and_set_bit(0, &opened))
		return -EBUSY;

	clear_bit(0, &opened)

[this generates atomic operations so is always safe]

> +       if(!table[minor].opened)
> +               return -EFAULT;

	BUG() may be better - it can't happen so BUG() will get a backtrace
and actually get it reported 8)

> +static long long tipar_lseek(struct file * file, long long offset, int origin)
> +{
> +       return -ESPIPE;
> +}

Can go (you now use no_llseek)


Basically except for the open/close one I'm now just picking holes. 
For the device major/minors see http://www.lanana.org.




^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: your mail
  2002-03-13 19:21 Romain Liévin
  2002-03-13 19:43 ` your mail Alan Cox
@ 2002-03-14  7:08 ` Zwane Mwaikambo
  1 sibling, 0 replies; 14+ messages in thread
From: Zwane Mwaikambo @ 2002-03-14  7:08 UTC (permalink / raw)
  To: Romain Liévin; +Cc: Kernel List, Alan Cox, Tim Waugh

Firstly, thanks for doing this =) secondly i'll give your driver a try 
when you release the serial version (i have a serial cable + TI-83)

Cheers,
	Zwane



^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: your mail, [PATCH] tipar
  2002-03-13 22:35     ` Alan Cox
@ 2002-03-16 15:06       ` Romain Liévin
  2002-03-16 17:46         ` Alan Cox
                           ` (2 more replies)
  0 siblings, 3 replies; 14+ messages in thread
From: Romain Liévin @ 2002-03-16 15:06 UTC (permalink / raw)
  To: Alan Cox; +Cc: Kernel List

Hi,

according to various remarks, I improved the source code.
I submit it again for new comments & suggestions...

> Basically except for the open/close one I'm now just picking holes.
> For the device major/minors see http://www.lanana.org.

I mailed lanana on Thursday but no answer yet.

Romain.

================================[cut here]=====================
--- linux.orig/drivers/char/tipar.c     Sat Mar 16 15:35:29 2002
+++ linux/drivers/char/tipar.c  Sat Mar 16 15:37:25 2002
@@ -0,0 +1,505 @@
+/* Hey EMACS -*- linux-c -*-
+ *
+ * tipar - low level driver for handling a parallel link cable designed
+ * for Texas Instruments graphing calculators (http://lpg.ticalc.org).
+ *
+ * Copyright (C) 2000-2002, Romain Lievin <roms@lpg.ticalc.org>
+ * under the terms of the GNU General Public License.
+ *
+ * Various fixes & clean-up from the Linux Kernel Mailing List
+ * (Alan Cox, Richard B. Johnson, Christoph Hellwig).
+ */
+
+#define TIPAR_VERSION "1.12f" /* March 2002 */
+
+/* This driver should, in theory, work with any parallel port that has
an
+ * appropriate low-level driver; all I/O is done through the parport
+ * abstraction layer.
+ *
+ * If this driver is built into the kernel, you can configure it using
the
+ * kernel command-line.  For example:
+ *
+ *      tipar=timeout,delay       (set timeout and delay)
+ *
+ * If the driver is loaded as a module, similar functionality is
available
+ * using module parameters.  The equivalent of the above commands would
be:
+ *
+ *      # insmod tipar.o tipar=15,10
+ */
+
+/* COMPATIBILITY WITH OLD KERNELS
+ *
+ * Usually, parallel cables were bound to ports at
+ * particular I/O addresses, as follows:
+ *
+ *      tipar0             0x378
+ *      tipar1             0x278
+ *      tipar2             0x3bc
+ *
+ *
+ * This driver, by default, binds tipar devices according to parport
and
+ * the minor number.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/fcntl.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <asm/uaccess.h>
+#include <linux/ioport.h>
+#include <asm/io.h>
+#include <asm/bitops.h>
+#include <linux/devfs_fs_kernel.h> /* DevFs support */
+#include <linux/parport.h>         /* Our code depend on parport */
+
+/*
+ * TI definitions
+ */
+//#include <linux/ticable.h>
+#include "ticable.h"
+
+/* ----- global variables ---------------------------------------------
*/
+
+struct tipar_struct {
+       struct pardevice *dev;                  /* Parport device entry
*/
+};
+
+#define PP_NO 3
+static struct tipar_struct  table[PP_NO];
+
+static int delay   = IO_DELAY;      /* inter-bit delay in microseconds
*/
+static int timeout = TIMAXTIME;     /* timeout in tenth of seconds    
*/
+
+static devfs_handle_t devfs_handle = NULL;
+static unsigned int tp_count = 0;   /* tipar count */
+static unsigned long opened = 0;    /* opened devices */
+
+/* --- macros for parport access --------------------------------------
*/
+
+#define r_dtr(x)        (parport_read_data(table[(x)].dev->port))
+#define r_str(x)        (parport_read_status(table[(x)].dev->port))
+#define w_ctr(x,y)      (parport_write_control(table[(x)].dev->port,
(y)))
+#define w_dtr(x,y)      (parport_write_data(table[(x)].dev->port, (y)))
+
+/* --- setting states on the D-bus with the right timing: -------------
*/
+
+static inline void outbyte(int value, int minor)
+{
+       w_dtr(minor, value);
+}
+
+static inline int inbyte(int minor)
+{
+       return (r_str(minor));
+}
+
+static inline void init_ti_parallel(int minor)
+{
+       outbyte(3, minor);
+}
+
+/* ----- global defines -----------------------------------------------
*/
+
+#define START(x) { max=jiffies+HZ/(timeout/10); }
+#define WAIT(x)  { \
+  if (time_before((x), jiffies)) return -1; \
+  if (current->need_resched) schedule(); }
+
+/* ----- D-bus bit-banging functions ----------------------------------
*/
+
+/* D-bus protocol (45kbit/s max):
+                    1                 0                      0
+       _______        ______|______    __________|________   
__________
+Red  :        ________      |      ____          |        ____
+       _        ____________|________      ______|__________      
_____
+White:  ________            |        ______      |          _______
+*/
+
+/* Try to transmit a byte on the specified port (-1 if error). */
+static int put_ti_parallel(int minor, unsigned char data)
+{
+       int bit;
+       unsigned long max;
+       
+       for (bit=0; bit<8; bit++) {
+               if (data & 1) {
+                       outbyte(2, minor);
+                       START(max); 
+                       do {
+                               WAIT(max);
+                       } while (inbyte(minor) & 0x10);
+                       
+                       outbyte(3, minor);
+                       START(max);
+                       do {
+                               WAIT(max);
+                       } while (!(inbyte(minor) & 0x10));
+               } else {
+                       outbyte(1, minor);
+                       START(max);
+                       do {
+                               WAIT(max);
+                       } while (inbyte(minor) & 0x20);
+
+                       outbyte(3, minor);
+                       START(max);
+                       do {
+                               WAIT(max);
+                       } while (!(inbyte(minor) & 0x20));
+               }
+
+               data >>= 1;
+               udelay(delay);
+               
+               if(current->need_resched)
+                       schedule();
+       }
+       
+       return 0;
+}
+
+/* Receive a byte on the specified port or -1 if error. */
+static int get_ti_parallel(int minor)
+{
+       int bit;
+       unsigned char v, data=0;
+       unsigned long max;
+
+       for (bit=0; bit<8; bit++) {
+               START(max); 
+               do {
+                       WAIT(max);
+               } while ((v=inbyte(minor) & 0x30) == 0x30);
+      
+               if (v == 0x10) { 
+                       data=(data>>1) | 0x80;
+                       outbyte(1, minor);
+                       START(max);
+                       do {
+                               WAIT(max);
+                       } while (!(inbyte(minor) & 0x20));
+                       outbyte(3, minor);
+               } else {
+                       data=data>>1;
+                       outbyte(2, minor);
+                       START(max);
+                       do {
+                               WAIT(max);
+                       } while (!(inbyte(minor) & 0x10));
+                       outbyte(3, minor);
+               }
+
+               udelay(delay);          
+               if(current->need_resched)
+                        schedule();
+       }
+       
+       return (int)data;
+}
+
+/* Try to detect a parallel link cable on the specified port */
+static int probe_ti_parallel(int minor)
+{
+       int i;
+       int seq[]={ 0x00, 0x20, 0x10, 0x30 };
+       
+       for(i=3; i>=0; i--) {
+               outbyte(3, minor);
+               outbyte(i, minor);
+               udelay(delay);
+               /*printk(KERN_DEBUG "Probing -> %i: 0x%02x 0x%02x\n", i,
data & 0x30, seq[i]);*/
+               if ( (inbyte(minor) & 0x30) != seq[i]) {
+                       outbyte(3, minor);
+                       return -1;
+               }
+       } 
+       outbyte(3, minor);
+       return 0;
+}
+
+/* ----- kernel module functions---------------------------------------
*/
+
+static int tipar_open(struct inode *inode, struct file *file)
+{
+       unsigned int minor = MINOR(inode->i_rdev) - TIPAR_MINOR_0;
+
+       if (minor > tp_count-1)
+               return -ENXIO;  
+
+       if(test_and_set_bit(minor, &opened))
+               return -EBUSY;
+
+       parport_claim_or_block (table[minor].dev);
+       init_ti_parallel (minor);
+       parport_release (table[minor].dev);
+       
+       return 0;
+}
+
+static int tipar_close(struct inode *inode, struct file *file)
+{
+       unsigned int minor = MINOR(inode->i_rdev) - TIPAR_MINOR_0;
+
+       if (minor > tp_count-1)
+               return -ENXIO;
+
+       clear_bit(minor, &opened);
+       
+       return 0;
+}
+
+static ssize_t tipar_write(struct file *file,
+                          const char *buf, size_t count, loff_t *ppos)
+{
+       unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev) -
TIPAR_MINOR_0;
+       ssize_t n;
+  
+       parport_claim_or_block (table[minor].dev);
+       
+       for(n=0; n<count; n++) {
+               unsigned char b;
+               
+               if (get_user(b, buf + n)) {
+                       n = -EFAULT;
+                       goto out;
+               }
+
+               if (put_ti_parallel(minor, b) == -1) {
+                       init_ti_parallel(minor);
+                       n = -ETIMEDOUT;
+                       goto out;
+               }
+       }
+ out:
+       parport_release (table[minor].dev);
+       return n;
+}
+
+static ssize_t tipar_read(struct file *file, char *buf, 
+                         size_t count, loff_t *ppos)
+{
+       int b=0;
+       unsigned int minor=MINOR(file->f_dentry->d_inode->i_rdev) -
TIPAR_MINOR_0;
+       ssize_t retval = 0;
+
+       if (count == 0)
+               return 0;
+
+       if (ppos != &file->f_pos)
+               return -ESPIPE;
+
+       parport_claim_or_block(table[minor].dev);
+  
+       do {
+               b = get_ti_parallel(minor);
+               if (b == -1) {
+                       init_ti_parallel(minor);
+                       retval = -ETIMEDOUT;
+                       goto out;
+               }
+               else
+                       break;
+      
+               /* Non-blocking mode: try again ! */
+               if (file->f_flags & O_NONBLOCK) {
+                       retval = -EAGAIN;
+                       goto out;
+               }
+               
+               /* Signal pending, try again ! */
+               if (signal_pending(current)) {
+                       retval = -ERESTARTSYS;
+                       goto out;
+               }
+
+               if(current->need_resched)
+                        schedule();
+       } while (1);
+
+       retval = put_user(b, (unsigned char *)buf);
+       if (!retval)
+               retval = 1;
+       else
+               retval = -EFAULT;
+
+ out:
+       parport_release(table[minor].dev);
+       return retval;
+}
+
+static int tipar_ioctl(struct inode *inode, struct file *file,
+                      unsigned int cmd, unsigned long arg)
+{
+       int retval = 0;
+
+       switch (cmd) {
+       case TIPAR_DELAY:
+               get_user(delay, &arg);
+               break;
+       case TIPAR_TIMEOUT:
+               get_user(timeout, &arg);
+               break;
+       default:
+               retval = -ENOTTY;
+               break;
+       }
+
+       return retval;
+}
+
+/* ----- kernel module registering ------------------------------------
*/
+
+static struct file_operations tipar_fops = {
+       owner:   THIS_MODULE,
+       llseek:  no_llseek,
+       read:    tipar_read,
+       write:   tipar_write,
+       ioctl:   tipar_ioctl,
+       open:    tipar_open,
+       release: tipar_close,
+};
+
+/* --- initialisation code ------------------------------------- */
+
+#ifndef MODULE
+/*      You must set these - there is no sane way to probe for this
cable.
+ *      You can use 'tipar=timeout,delay' to set these now. */
+static int __init tipar_setup (char *str)
+{
+       int ints[2];
+       
+        str = get_options (str, ARRAY_SIZE(ints), ints);
+       
+        if (ints[0] > 0) {
+                timeout = ints[1];
+                if (ints[0] > 1) {
+                        delay = ints[2];
+               }
+        }
+       
+        return 1;
+}
+#endif
+
+/*
+ * Register our module into parport.
+ * Pass also 2 callbacks functions to parport: a pre-emptive function
and an
+ * interrupt handler function (unused).
+ * Display a message such "tipar0: using parport0 (polling)".
+ */
+static int tipar_register(int nr, struct parport *port)
+{
+       char name[8];
+       
+       /* Register our module into parport */
+       table[nr].dev = parport_register_device(port, "tipar",
+                                               NULL, NULL, NULL, 0,
+                                               (void *) &table[nr]);
+       
+       if (table[nr].dev == NULL)
+               return 1;
+ 
+       /* Use devfs, tree: /dev/ticables/par/[0..2] */
+       sprintf(name, "%d", nr);
+       devfs_register(devfs_handle, name,
+                       DEVFS_FL_DEFAULT, TIPAR_MAJOR, nr,
+                       S_IFCHR | S_IRUGO | S_IWUGO,
+                       &tipar_fops, NULL);
+
+       /* Display informations */
+       printk(KERN_INFO "tipar%d: using %s (%s).\n", nr, port->name,
+              (port->irq == PARPORT_IRQ_NONE) ? "polling" :
"interrupt-driven");
+
+       if (probe_ti_parallel(nr) != -1)
+               printk("tipar%d: link cable found !\n", nr);
+       else
+               printk("tipar%d: link cable not found.\n", nr);
+
+       return 0;
+}
+
+static void tipar_attach (struct parport *port)
+{
+       if (tp_count == PP_NO) {
+               printk("tipar: ignoring parallel port (max. %d)\n", 
+                      PP_NO);
+               return;
+       }
+
+       if (!tipar_register(tp_count, port))
+               tp_count++;
+}
+
+static void tipar_detach (struct parport *port)
+{
+       /* Nothing to do */
+}
+
+static struct parport_driver tipar_driver = {
+       "tipar",
+       tipar_attach,
+       tipar_detach,
+       NULL
+};
+
+int __init tipar_init_module(void)
+{
+       printk("tipar: parallel link cable driver, version %s\n",
TIPAR_VERSION);
+       
+       if (devfs_register_chrdev (TIPAR_MAJOR, "tipar", &tipar_fops)) {
+               printk("tipar: unable to get major %d\n", TIPAR_MAJOR);
+               return -EIO;
+       }
+
+       /* Use devfs with tree: /dev/ticables/par/[0..2] */
+       devfs_handle = devfs_mk_dir (NULL, "ticables/par", NULL);
+
+       if (parport_register_driver (&tipar_driver)) {
+               printk ("tipar: unable to register with parport\n");
+               return -EIO;
+       }
+
+       return 0;
+}
+
+void __exit tipar_cleanup_module(void)
+{
+       unsigned int i;
+
+       /* Unregistering module */
+       parport_unregister_driver (&tipar_driver);
+
+       devfs_unregister (devfs_handle);
+       devfs_unregister_chrdev(TIPAR_MAJOR, "tipar");  
+
+       for (i = 0; i < PP_NO; i++) {
+               if (table[i].dev == NULL)
+                       continue;
+               parport_unregister_device(table[i].dev);
+       }
+
+       printk("tipar: module unloaded !\n");
+}
+
+__setup("tipar=", tipar_setup);
+module_init(tipar_init_module);
+module_exit(tipar_cleanup_module);
+
+MODULE_AUTHOR("Author/Maintainer: Romain Lievin
<roms@lpg.ticalc.org>");
+MODULE_DESCRIPTION("Device driver for TI/PC parallel link cables");
+MODULE_LICENSE("GPL");
+
+EXPORT_NO_SYMBOLS;
+
+MODULE_PARM(timeout, "i");
+MODULE_PARM_DESC(timeout, "Timeout (default=1.5 seconds)");
+MODULE_PARM(delay, "i");
+MODULE_PARM_DESC(delay, "Inter-bit delay (default=10 microseconds)");
--- linux.orig/include/linux/ticable.h  Sat Mar 16 15:35:35 2002
+++ linux/include/linux/ticable.h       Sat Mar 16 15:37:43 2002
@@ -0,0 +1,41 @@
+/* Hey EMACS -*- linux-c -*-
+ *
+ * tipar/tiser/tiglusb - low level driver for handling link cables
+ * designed for Texas Instruments graphing calculators.
+ *
+ * Copyright (C) 2000-2002, Romain Lievin <roms@lpg.ticalc.org>
+ * under the terms of the GNU General Public License.
+ */
+
+#ifndef TICABLE_H 
+#define TICABLE_H 1
+
+/* Internal default constants for the kernel module */
+#define TIMAXTIME 10      /* 1 seconds                         */
+#define IO_DELAY  10      /* 10 micro-seconds  */
+
+/* Major & minor number for character devices */
+#define TIPAR_MAJOR   61
+#define TIPAR_MINOR_0  1
+#define TIPAR_MINOR_1  2
+#define TIPAR_MINOR_2  3
+
+#define TISER_MAJOR   62
+#define TISER_MINOR_0  1
+#define TISER_MINOR_1  2
+#define TISER_MINOR_2  3
+#define TISER_MINOR_3  4
+
+/*
+ * Request values for the 'ioctl' function.
+ * Simply pass the appropriate value as arg of the ioctl call.
+ * These values do not conflict with other ones but they have to be
+ * allocated... (/usr/src/linux/Documentation/ioctl-number.txt).
+ */
+#define TIPAR_DELAY     _IOW('p', 0xa8, int) /* set delay   */
+#define TIPAR_TIMEOUT   _IOW('p', 0xa9, int) /* set timeout */
+
+#define TISER_DELAY     _IOW('p', 0xa0, int) /* set delay   */
+#define TISER_TIMEOUT   _IOW('p', 0xa1, int) /* set timeout */
+
+#endif /* TICABLE_H */
--- linux.orig/MAINTAINERS      Fri Mar  8 03:18:07 2002
+++ linux/MAINTAINERS   Sat Mar 16 15:32:23 2002
@@ -1504,6 +1504,13 @@
 M:     hch@infradead.org
 S:     Maintained
 
+TI PARALLEL LINK CABLE DRIVER
+P:     Romain Lievin
+M:     roms@lpg.ticalc.org
+P:     Julien Blache
+M:     jb@technologeek.org
+S:     Maintained
+
 TLAN NETWORK DRIVER
 P:     Torben Mathiasen
 M:     torben.mathiasen@compaq.com
--- linux.orig/drivers/char/Config.help Fri Mar  8 03:18:28 2002
+++ linux/drivers/char/Config.help      Sat Mar 16 15:33:13 2002
@@ -595,6 +595,27 @@
 
   If unsure, say N.
 
+CONFIG_TI_PAR
+  If you own a Texas Instruments graphing calculator and use a
+  parallel link cable, then you might be interested in this driver.
+
+  If you enable this driver, you will be able to communicate with
+  your calculator through a set of device nodes under /dev. The
+  main advantage of this driver is that you don't have to be root
+  to use this precise link cable (depending on the permissions on
+  the device nodes, though).
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called tipar.o. If you want to compile it as a
+  module, say M here and read Documentation/modules.txt.
+
+  If you don't know what a parallel link cable is or what a Texas
+  Instruments graphing calculator is, then you probably don't need this
+  driver.
+
+  If unsure, say N.
+
 CONFIG_BUSMOUSE
   Say Y here if your machine has a bus mouse as opposed to a serial
   mouse. Most people have a regular serial MouseSystem or
--- linux.orig/drivers/char/Config.in   Fri Mar  8 03:18:17 2002
+++ linux/drivers/char/Config.in        Sat Mar 16 15:33:45 2002
@@ -103,6 +103,7 @@
       bool '  Support for console on line printer' CONFIG_LP_CONSOLE
    fi
    dep_tristate 'Support for user-space parallel port device drivers'
CONFIG_PPDEV $CONFIG_PARPORT
+   dep_tristate 'Texas Instruments parallel link cable support'
CONFIG_TI_PAR $CONFIG_PARPORT
 fi
 
 source drivers/i2c/Config.in
--- linux.orig/drivers/char/Makefile    Fri Mar  8 03:18:27 2002
+++ linux/drivers/char/Makefile Sat Mar 16 15:34:11 2002
@@ -205,6 +205,7 @@
 
 obj-$(CONFIG_H8) += h8.o
 obj-$(CONFIG_PPDEV) += ppdev.o
+obj-$(CONFIG_TI_PAR) += tipar.o
 obj-$(CONFIG_DZ) += dz.o
 obj-$(CONFIG_NWBUTTON) += nwbutton.o
 obj-$(CONFIG_NWFLASH) += nwflash.o


-- 
Romain LIEVIN aka Roms, mail: roms@lpg.ticalc.org
web: http://lpg.ticalc.org/prj_tilp (on www.ticalc.org)
ICQ: 43585029 (GtkIcq0.60/Linux)

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: your mail, [PATCH] tipar
  2002-03-16 15:06       ` your mail, [PATCH] tipar Romain Liévin
@ 2002-03-16 17:46         ` Alan Cox
  2002-03-31 10:39           ` [PATCH] kernel 2.5.7-pre2, tipar: TI graphing calculators Romain Liévin
  2002-03-16 20:06         ` your mail, [PATCH] tipar Christoph Hellwig
  2002-03-22 15:52         ` Jes Sorensen
  2 siblings, 1 reply; 14+ messages in thread
From: Alan Cox @ 2002-03-16 17:46 UTC (permalink / raw)
  To: roms; +Cc: Alan Cox, Kernel List

> according to various remarks, I improved the source code.
> I submit it again for new comments & suggestions...

Looks good to me

> I mailed lanana on Thursday but no answer yet.

Ok

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: your mail, [PATCH] tipar
  2002-03-16 15:06       ` your mail, [PATCH] tipar Romain Liévin
  2002-03-16 17:46         ` Alan Cox
@ 2002-03-16 20:06         ` Christoph Hellwig
  2002-03-16 20:20           ` Christoph Hellwig
  2002-03-17  6:16           ` Erik Andersen
  2002-03-22 15:52         ` Jes Sorensen
  2 siblings, 2 replies; 14+ messages in thread
From: Christoph Hellwig @ 2002-03-16 20:06 UTC (permalink / raw)
  To: roms; +Cc: Alan Cox, Kernel List

> +static devfs_handle_t devfs_handle = NULL;
> +static unsigned int tp_count = 0;   /* tipar count */
> +static unsigned long opened = 0;    /* opened devices */

Variables in .bcc are auto-zeroed - you can drop the intialization.


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: your mail, [PATCH] tipar
  2002-03-16 20:06         ` your mail, [PATCH] tipar Christoph Hellwig
@ 2002-03-16 20:20           ` Christoph Hellwig
  2002-03-17  6:16           ` Erik Andersen
  1 sibling, 0 replies; 14+ messages in thread
From: Christoph Hellwig @ 2002-03-16 20:20 UTC (permalink / raw)
  To: roms, Alan Cox, Kernel List

On Sat, Mar 16, 2002 at 08:06:51PM +0000, Christoph Hellwig wrote:
> > +static devfs_handle_t devfs_handle = NULL;
> > +static unsigned int tp_count = 0;   /* tipar count */
> > +static unsigned long opened = 0;    /* opened devices */
> 
> Variables in .bcc are auto-zeroed - you can drop the intialization.

.bss ..


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: your mail, [PATCH] tipar
  2002-03-16 20:06         ` your mail, [PATCH] tipar Christoph Hellwig
  2002-03-16 20:20           ` Christoph Hellwig
@ 2002-03-17  6:16           ` Erik Andersen
  1 sibling, 0 replies; 14+ messages in thread
From: Erik Andersen @ 2002-03-17  6:16 UTC (permalink / raw)
  To: Christoph Hellwig, roms, Alan Cox, Kernel List

On Sat Mar 16, 2002 at 08:06:51PM +0000, Christoph Hellwig wrote:
> > +static devfs_handle_t devfs_handle = NULL;
> > +static unsigned int tp_count = 0;   /* tipar count */
> > +static unsigned long opened = 0;    /* opened devices */
> 
> Variables in .bcc are auto-zeroed - you can drop the intialization.

I'm sure all the users of elks will be disappointed that their
compiler auto zeros all variables.  :)

I think you mean .bss...

 -Erik

--
Erik B. Andersen             http://codepoet-consulting.com/
--This message was written using 73% post-consumer electrons--

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: your mail, [PATCH] tipar
  2002-03-16 15:06       ` your mail, [PATCH] tipar Romain Liévin
  2002-03-16 17:46         ` Alan Cox
  2002-03-16 20:06         ` your mail, [PATCH] tipar Christoph Hellwig
@ 2002-03-22 15:52         ` Jes Sorensen
  2 siblings, 0 replies; 14+ messages in thread
From: Jes Sorensen @ 2002-03-22 15:52 UTC (permalink / raw)
  To: roms; +Cc: Alan Cox, Kernel List

Romain Liévin <rlievin@free.fr> writes:

> Hi,
> 
> according to various remarks, I improved the source code.
> I submit it again for new comments & suggestions...

Another comment. Your usage of the START macro is kinda
broken. Basically you declare it as #define START(x) but never use the
value, and instead rely on a local scope variable named max being
present.

> +/* ----- global defines -----------------------------------------------
> */
> +
> +#define START(x) { max=jiffies+HZ/(timeout/10); }
> +#define WAIT(x)  { \
> +  if (time_before((x), jiffies)) return -1; \
> +  if (current->need_resched) schedule(); }
> +/* Try to transmit a byte on the specified port (-1 if error). */
> +static int put_ti_parallel(int minor, unsigned char data)
> +{
> +       int bit;
> +       unsigned long max;
> +       
> +       for (bit=0; bit<8; bit++) {
> +               if (data & 1) {
> +                       outbyte(2, minor);
> +                       START(max); 

If you really want to use the START macro, you should redefine it as
follows:

#define START(x) { x=jiffies+HZ/(timeout/10); }

One example of where one has to be careful with macros ;(

Jes

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] kernel 2.5.7-pre2, tipar: TI graphing calculators
  2002-03-16 17:46         ` Alan Cox
@ 2002-03-31 10:39           ` Romain Liévin
  0 siblings, 0 replies; 14+ messages in thread
From: Romain Liévin @ 2002-03-31 10:39 UTC (permalink / raw)
  To: linux-kernel; +Cc: Alan Cox, Linus Torvalds

Hi,

> Alan Cox wrote:
> 
> > according to various remarks, I improved the source code.
> > I submit it again for new comments & suggestions...
> 
> Looks good to me
> 
> > I mailed lanana on Thursday but no answer yet.
> 
> Ok

I got official device numbers for my modules. I think that's all right
for including this module in the current Linux kernel.
Patch is provided below.

Romain.

==============================[ cut here ]==============================
--- linux.orig/drivers/char/tipar.c     Sun Mar 31 11:14:04 2002
+++ linux/drivers/char/tipar.c  Sun Mar 31 12:06:41 2002
@@ -0,0 +1,513 @@
+/* Hey EMACS -*- linux-c -*-
+ *
+ * tipar - low level driver for handling a parallel link cable designed
+ * for Texas Instruments graphing calculators (http://lpg.ticalc.org).
+ *
+ * Copyright (C) 2000-2002, Romain Lievin <roms@lpg.ticalc.org>
+ * under the terms of the GNU General Public License.
+ *
+ * Various fixes & clean-up from the Linux Kernel Mailing List
+ * (Alan Cox, Richard B. Johnson, Christoph Hellwig).
+ */
+
+/* This driver should, in theory, work with any parallel port that has
an
+ * appropriate low-level driver; all I/O is done through the parport
+ * abstraction layer.
+ *
+ * If this driver is built into the kernel, you can configure it using
the
+ * kernel command-line.  For example:
+ *
+ *      tipar=timeout,delay       (set timeout and delay)
+ *
+ * If the driver is loaded as a module, similar functionality is
available
+ * using module parameters.  The equivalent of the above commands would
be:
+ *
+ *      # insmod tipar.o tipar=15,10
+ */
+
+/* COMPATIBILITY WITH OLD KERNELS
+ *
+ * Usually, parallel cables were bound to ports at
+ * particular I/O addresses, as follows:
+ *
+ *      tipar0             0x378
+ *      tipar1             0x278
+ *      tipar2             0x3bc
+ *
+ *
+ * This driver, by default, binds tipar devices according to parport
and
+ * the minor number.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/fcntl.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <asm/uaccess.h>
+#include <linux/ioport.h>
+#include <asm/io.h>
+#include <asm/bitops.h>
+#include <linux/devfs_fs_kernel.h> /* DevFs support */
+#include <linux/parport.h>         /* Our code depend on parport */
+
+/*
+ * TI definitions
+ */
+#include "ticable.h" //#include <linux/ticable.h>
+
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "1.14"
+#define DRIVER_AUTHOR  "Romain Lievin <roms@lpg.ticalc.org>"
+#define DRIVER_DESC    "Device driver for TI/PC parallel link cables"
+#define DRIVER_LICENSE "GPL"
+
+/* ----- global variables ---------------------------------------------
*/
+
+struct tipar_struct {
+       struct pardevice *dev;                  /* Parport device entry
*/
+};
+
+#define PP_NO 3
+static struct tipar_struct  table[PP_NO];
+
+static int delay   = IO_DELAY;      /* inter-bit delay in microseconds
*/
+static int timeout = TIMAXTIME;     /* timeout in tenth of seconds    
*/
+
+static devfs_handle_t devfs_handle;
+static unsigned int tp_count;       /* tipar count */
+static unsigned long opened;        /* opened devices */
+
+/* --- macros for parport access --------------------------------------
*/
+
+#define r_dtr(x)        (parport_read_data(table[(x)].dev->port))
+#define r_str(x)        (parport_read_status(table[(x)].dev->port))
+#define w_ctr(x,y)      (parport_write_control(table[(x)].dev->port,
(y)))
+#define w_dtr(x,y)      (parport_write_data(table[(x)].dev->port, (y)))
+
+/* --- setting states on the D-bus with the right timing: -------------
*/
+
+static inline void outbyte(int value, int minor)
+{
+       w_dtr(minor, value);
+}
+
+static inline int inbyte(int minor)
+{
+       return (r_str(minor));
+}
+
+static inline void init_ti_parallel(int minor)
+{
+       outbyte(3, minor);
+}
+
+/* ----- global defines -----------------------------------------------
*/
+
+#define START(x) { x=jiffies+HZ/(timeout/10); }
+#define WAIT(x)  { \
+  if (time_before((x), jiffies)) return -1; \
+  if (current->need_resched) schedule(); }
+
+/* ----- D-bus bit-banging functions ----------------------------------
*/
+
+/* D-bus protocol (45kbit/s max):
+                    1                 0                      0
+       _______        ______|______    __________|________   
__________
+Red  :        ________      |      ____          |        ____
+       _        ____________|________      ______|__________      
_____
+White:  ________            |        ______      |          _______
+*/
+
+/* Try to transmit a byte on the specified port (-1 if error). */
+static int put_ti_parallel(int minor, unsigned char data)
+{
+       int bit;
+       unsigned long max;
+       
+       for (bit=0; bit<8; bit++) {
+               if (data & 1) {
+                       outbyte(2, minor);
+                       START(max); 
+                       do {
+                               WAIT(max);
+                       } while (inbyte(minor) & 0x10);
+                       
+                       outbyte(3, minor);
+                       START(max);
+                       do {
+                               WAIT(max);
+                       } while (!(inbyte(minor) & 0x10));
+               } else {
+                       outbyte(1, minor);
+                       START(max);
+                       do {
+                               WAIT(max);
+                       } while (inbyte(minor) & 0x20);
+
+                       outbyte(3, minor);
+                       START(max);
+                       do {
+                               WAIT(max);
+                       } while (!(inbyte(minor) & 0x20));
+               }
+
+               data >>= 1;
+               udelay(delay);
+               
+               if(current->need_resched)
+                       schedule();
+       }
+       
+       return 0;
+}
+
+/* Receive a byte on the specified port or -1 if error. */
+static int get_ti_parallel(int minor)
+{
+       int bit;
+       unsigned char v, data=0;
+       unsigned long max;
+
+       for (bit=0; bit<8; bit++) {
+               START(max); 
+               do {
+                       WAIT(max);
+               } while ((v=inbyte(minor) & 0x30) == 0x30);
+      
+               if (v == 0x10) { 
+                       data=(data>>1) | 0x80;
+                       outbyte(1, minor);
+                       START(max);
+                       do {
+                               WAIT(max);
+                       } while (!(inbyte(minor) & 0x20));
+                       outbyte(3, minor);
+               } else {
+                       data=data>>1;
+                       outbyte(2, minor);
+                       START(max);
+                       do {
+                               WAIT(max);
+                       } while (!(inbyte(minor) & 0x10));
+                       outbyte(3, minor);
+               }
+
+               udelay(delay);          
+               if(current->need_resched)
+                        schedule();
+       }
+       
+       return (int)data;
+}
+
+/* Try to detect a parallel link cable on the specified port */
+static int probe_ti_parallel(int minor)
+{
+       int i;
+       int seq[]={ 0x00, 0x20, 0x10, 0x30 };
+       
+       for(i=3; i>=0; i--) {
+               outbyte(3, minor);
+               outbyte(i, minor);
+               udelay(delay);
+               /*printk(KERN_DEBUG "Probing -> %i: 0x%02x 0x%02x\n", i,
data & 0x30, seq[i]);*/
+               if ( (inbyte(minor) & 0x30) != seq[i]) {
+                       outbyte(3, minor);
+                       return -1;
+               }
+       } 
+       outbyte(3, minor);
+       return 0;
+}
+
+/* ----- kernel module functions---------------------------------------
*/
+
+static int tipar_open(struct inode *inode, struct file *file)
+{
+       unsigned int minor = MINOR(inode->i_rdev) - TIPAR_MINOR;
+
+       if (minor > tp_count-1)
+               return -ENXIO;  
+
+       if(test_and_set_bit(minor, &opened))
+               return -EBUSY;
+
+       parport_claim_or_block (table[minor].dev);
+       init_ti_parallel (minor);
+       parport_release (table[minor].dev);
+       
+       return 0;
+}
+
+static int tipar_close(struct inode *inode, struct file *file)
+{
+       unsigned int minor = MINOR(inode->i_rdev) - TIPAR_MINOR;
+
+       if (minor > tp_count-1)
+               return -ENXIO;
+
+       clear_bit(minor, &opened);
+       
+       return 0;
+}
+
+static ssize_t tipar_write(struct file *file,
+                          const char *buf, size_t count, loff_t *ppos)
+{
+       unsigned int
minor=MINOR(file->f_dentry->d_inode->i_rdev)-TIPAR_MINOR;
+       ssize_t n;
+  
+       parport_claim_or_block (table[minor].dev);
+       
+       for(n=0; n<count; n++) {
+               unsigned char b;
+               
+               if (get_user(b, buf + n)) {
+                       n = -EFAULT;
+                       goto out;
+               }
+
+               if (put_ti_parallel(minor, b) == -1) {
+                       init_ti_parallel(minor);
+                       n = -ETIMEDOUT;
+                       goto out;
+               }
+       }
+ out:
+       parport_release (table[minor].dev);
+       return n;
+}
+
+static ssize_t tipar_read(struct file *file, char *buf, 
+                         size_t count, loff_t *ppos)
+{
+       int b=0;
+       unsigned int
minor=MINOR(file->f_dentry->d_inode->i_rdev)-TIPAR_MINOR;
+       ssize_t retval = 0;
+       ssize_t n = 0;
+
+       if (count == 0)
+               return 0;
+
+       if (ppos != &file->f_pos)
+               return -ESPIPE;
+
+       parport_claim_or_block(table[minor].dev);
+  
+       while(n < count) {
+               b = get_ti_parallel(minor);
+               if (b == -1) {
+                       init_ti_parallel(minor);
+                       retval = -ETIMEDOUT;
+                       goto out;
+               }
+               else {
+                       if(put_user(b, ((unsigned char *)buf)+n)) {
+                               retval = -EFAULT;
+                               break;
+                       } else retval = n;
+               }
+      
+               /* Non-blocking mode: try again ! */
+               if (file->f_flags & O_NONBLOCK) {
+                       retval = -EAGAIN;
+                       goto out;
+               }
+               
+               /* Signal pending, try again ! */
+               if (signal_pending(current)) {
+                       retval = -ERESTARTSYS;
+                       goto out;
+               }
+
+               n++;
+               if(current->need_resched)
+                        schedule();
+       }
+
+ out:
+       parport_release(table[minor].dev);
+       return retval;
+}
+
+static int tipar_ioctl(struct inode *inode, struct file *file,
+                      unsigned int cmd, unsigned long arg)
+{
+       int retval = 0;
+
+       switch (cmd) {
+       case IOCTL_TIPAR_DELAY:
+               get_user(delay, &arg);
+               break;
+       case IOCTL_TIPAR_TIMEOUT:
+               get_user(timeout, &arg);
+               break;
+       default:
+               retval = -ENOTTY;
+               break;
+       }
+
+       return retval;
+}
+
+/* ----- kernel module registering ------------------------------------
*/
+
+static struct file_operations tipar_fops = {
+       owner:   THIS_MODULE,
+       llseek:  no_llseek,
+       read:    tipar_read,
+       write:   tipar_write,
+       ioctl:   tipar_ioctl,
+       open:    tipar_open,
+       release: tipar_close,
+};
+
+/* --- initialisation code ------------------------------------- */
+
+#ifndef MODULE
+/*      You must set these - there is no sane way to probe for this
cable.
+ *      You can use 'tipar=timeout,delay' to set these now. */
+static int __init tipar_setup (char *str)
+{
+       int ints[2];
+       
+        str = get_options (str, ARRAY_SIZE(ints), ints);
+       
+        if (ints[0] > 0) {
+                timeout = ints[1];
+                if (ints[0] > 1) {
+                        delay = ints[2];
+               }
+        }
+       
+        return 1;
+}
+#endif
+
+/*
+ * Register our module into parport.
+ * Pass also 2 callbacks functions to parport: a pre-emptive function
and an
+ * interrupt handler function (unused).
+ * Display a message such "tipar0: using parport0 (polling)".
+ */
+static int tipar_register(int nr, struct parport *port)
+{
+       char name[8];
+       
+       /* Register our module into parport */
+       table[nr].dev = parport_register_device(port, "tipar",
+                                               NULL, NULL, NULL, 0,
+                                               (void *) &table[nr]);
+       
+       if (table[nr].dev == NULL)
+               return 1;
+ 
+       /* Use devfs, tree: /dev/ticables/par/[0..2] */
+       sprintf(name, "%d", nr);
+       printk("tipar: registering to devfs : major = %d, minor = %d,
node = %s\n", TISER_MAJOR, (TIPAR_MINOR + nr), name);
+       devfs_register(devfs_handle, name,
+                       DEVFS_FL_DEFAULT, TIPAR_MAJOR, TIPAR_MINOR + nr,
+                       S_IFCHR | S_IRUGO | S_IWUGO,
+                       &tipar_fops, NULL);
+
+       /* Display informations */
+       printk(KERN_INFO "tipar%d: using %s (%s).\n", nr, port->name,
+              (port->irq == PARPORT_IRQ_NONE) ? "polling" :
"interrupt-driven");
+
+       if (probe_ti_parallel(nr) != -1)
+               printk("tipar%d: link cable found !\n", nr);
+       else
+               printk("tipar%d: link cable not found.\n", nr);
+
+       return 0;
+}
+
+static void tipar_attach (struct parport *port)
+{
+       if (tp_count == PP_NO) {
+               printk("tipar: ignoring parallel port (max. %d)\n", 
+                      PP_NO);
+               return;
+       }
+
+       if (!tipar_register(tp_count, port))
+               tp_count++;
+}
+
+static void tipar_detach (struct parport *port)
+{
+       /* Nothing to do */
+}
+
+static struct parport_driver tipar_driver = {
+       "tipar",
+       tipar_attach,
+       tipar_detach,
+       NULL
+};
+
+int __init tipar_init_module(void)
+{
+       printk("tipar: parallel link cable driver, version %s\n",
DRIVER_VERSION);
+       
+       if (devfs_register_chrdev (TIPAR_MAJOR, "tipar", &tipar_fops)) {
+               printk("tipar: unable to get major %d\n", TIPAR_MAJOR);
+               return -EIO;
+       }
+
+       /* Use devfs with tree: /dev/ticables/par/[0..2] */
+       devfs_handle = devfs_mk_dir (NULL, "ticables/par", NULL);
+
+       if (parport_register_driver (&tipar_driver)) {
+               printk ("tipar: unable to register with parport\n");
+               return -EIO;
+       }
+
+       return 0;
+}
+
+void __exit tipar_cleanup_module(void)
+{
+       unsigned int i;
+
+       /* Unregistering module */
+       parport_unregister_driver (&tipar_driver);
+
+       devfs_unregister (devfs_handle);
+       devfs_unregister_chrdev(TIPAR_MAJOR, "tipar");  
+
+       for (i = 0; i < PP_NO; i++) {
+               if (table[i].dev == NULL)
+                       continue;
+               parport_unregister_device(table[i].dev);
+       }
+
+       printk("tipar: module unloaded !\n");
+}
+
+/*
--------------------------------------------------------------------- */
+
+__setup("tipar=", tipar_setup);
+module_init(tipar_init_module);
+module_exit(tipar_cleanup_module);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE(DRIVER_LICENSE);
+
+EXPORT_NO_SYMBOLS;
+
+MODULE_PARM(timeout, "i");
+MODULE_PARM_DESC(timeout, "Timeout (default=1.5 seconds)");
+MODULE_PARM(delay, "i");
+MODULE_PARM_DESC(delay, "Inter-bit delay (default=10 microseconds)");
--- linux.orig/include/linux/ticable.h  Sun Mar 31 11:14:23 2002
+++ linux/include/linux/ticable.h       Sun Mar 31 12:06:18 2002
@@ -0,0 +1,42 @@
+/* Hey EMACS -*- linux-c -*-
+ *
+ * tipar/tiser/tiusb - low level driver for handling link cables
+ * designed for Texas Instruments graphing calculators.
+ *
+ * Copyright (C) 2000-2002, Romain Lievin <roms@lpg.ticalc.org>
+ *
+ * Redistribution of this file is permitted under the terms of the GNU
+ * Public License (GPL)
+ */
+
+#ifndef _TICABLE_H 
+#define _TICABLE_H 1
+
+/* Internal default constants for the kernel module */
+#define TIMAXTIME 15      /* 1.5 seconds       */
+#define IO_DELAY  10      /* 10 micro-seconds  */
+
+/* Major & minor number for character devices */
+#define TIPAR_MAJOR  115 /* 0 to 7 */
+#define TIPAR_MINOR    0
+
+#define TISER_MAJOR  115 /* 8 to 15 */
+#define TISER_MINOR    8
+
+#define TIUSB_MAJOR  115  /* 16 to 31 */
+#define TIUSB_MINOR   16
+
+/*
+ * Request values for the 'ioctl' function.
+ */
+#define IOCTL_TIPAR_DELAY     _IOW('p', 0xa8, int) /* set delay   */
+#define IOCTL_TIPAR_TIMEOUT   _IOW('p', 0xa9, int) /* set timeout */
+
+#define IOCTL_TISER_DELAY     _IOW('p', 0xa0, int) /* set delay   */
+#define IOCTL_TISER_TIMEOUT   _IOW('p', 0xa1, int) /* set timeout */
+
+#define IOCTL_TIUSB_TIMEOUT        _IOW('N', 0x20, int) /* set timeout
*/
+#define IOCTL_TIUSB_RESET_DEVICE   _IOW('N', 0x21, int) /* reset device
*/
+#define IOCTL_TIUSB_RESET_PIPES    _IOW('N', 0x22, int) /* reset both
pipes*/
+
+#endif /* TICABLE_H */
--- linux.orig/MAINTAINERS      Mon Mar 18 21:37:04 2002
+++ linux/MAINTAINERS   Sun Mar 31 12:08:26 2002
@@ -1502,6 +1502,13 @@
 M:     hch@infradead.org
 S:     Maintained
 
+TI PARALLEL LINK CABLE DRIVER
+P:     Romain Lievin
+M:     roms@lpg.ticalc.org
+P:     Julien Blache
+M:     jb@technologeek.org
+S:     Maintained
+
 TLAN NETWORK DRIVER
 P:     Torben Mathiasen
 M:     torben.mathiasen@compaq.com
--- linux.orig/drivers/char/Config.help Mon Mar 18 21:37:13 2002
+++ linux/drivers/char/Config.help      Sun Mar 31 12:04:16 2002
@@ -595,6 +595,27 @@
 
   If unsure, say N.
 
+CONFIG_TIPAR
+  If you own a Texas Instruments graphing calculator and use a
+  parallel link cable, then you might be interested in this driver.
+
+  If you enable this driver, you will be able to communicate with
+  your calculator through a set of device nodes under /dev. The
+  main advantage of this driver is that you don't have to be root
+  to use this precise link cable (depending on the permissions on
+  the device nodes, though).
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called tipar.o. If you want to compile it as a
+  module, say M here and read Documentation/modules.txt.
+
+  If you don't know what a parallel link cable is or what a Texas
+  Instruments graphing calculator is, then you probably don't need this
+  driver.
+
+  If unsure, say N.
+
 CONFIG_BUSMOUSE
   Say Y here if your machine has a bus mouse as opposed to a serial
   mouse. Most people have a regular serial MouseSystem or
--- linux.orig/drivers/char/Config.in   Mon Mar 18 21:37:08 2002
+++ linux/drivers/char/Config.in        Sun Mar 31 12:04:56 2002
@@ -103,6 +103,7 @@
       bool '  Support for console on line printer' CONFIG_LP_CONSOLE
    fi
    dep_tristate 'Support for user-space parallel port device drivers'
CONFIG_PPDEV $CONFIG_PARPORT
+   dep_tristate 'Texas Instruments parallel link cable support'
CONFIG_TIPAR $CONFIG_PARPORT
 fi
 
 source drivers/i2c/Config.in
--- linux.orig/drivers/char/Makefile    Mon Mar 18 21:37:13 2002
+++ linux/drivers/char/Makefile Sun Mar 31 12:29:52 2002
@@ -208,6 +208,7 @@
 obj-$(CONFIG_DZ) += dz.o
 obj-$(CONFIG_NWBUTTON) += nwbutton.o
 obj-$(CONFIG_NWFLASH) += nwflash.o
+obj-$(CONFIG_TIPAR) += tipar.o
 
 # Only one watchdog can succeed. We probe the hardware watchdog
 # drivers first, then the softdog driver.  This means if your hardware

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2002-03-31 11:38 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-03-13 19:21 Romain Liévin
2002-03-13 19:43 ` your mail Alan Cox
2002-03-13 20:28   ` Romain Liévin
2002-03-13 20:49     ` Richard B. Johnson
2002-03-13 22:27       ` Alan Cox
2002-03-13 22:35     ` Alan Cox
2002-03-16 15:06       ` your mail, [PATCH] tipar Romain Liévin
2002-03-16 17:46         ` Alan Cox
2002-03-31 10:39           ` [PATCH] kernel 2.5.7-pre2, tipar: TI graphing calculators Romain Liévin
2002-03-16 20:06         ` your mail, [PATCH] tipar Christoph Hellwig
2002-03-16 20:20           ` Christoph Hellwig
2002-03-17  6:16           ` Erik Andersen
2002-03-22 15:52         ` Jes Sorensen
2002-03-14  7:08 ` your mail Zwane Mwaikambo

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.