Ingo and Thomas,

Here's a clean up of the lpptest. I removed the dependency to the TSC
and I now use the getnstimeofday for measuring the latency. I also added
code to request the port region.

I plan on doing more with this utility, but figured I'd send updates at
stages of progress.

-- Steve

Index: linux-2.6.20-rt7/drivers/char/lpptest.c
===================================================================
--- linux-2.6.20-rt7.orig/drivers/char/lpptest.c        2007-02-16 
10:56:01.000000000 -0500
+++ linux-2.6.20-rt7/drivers/char/lpptest.c     2007-02-16 14:12:49.000000000 
-0500
@@ -3,11 +3,42 @@
  *
  *      Copyright (C) 2005 Thomas Gleixner, Ingo Molnar
  *
+ * Resurrected by Steven Rostedt:
+ *   - Slight code clean up.
+ *   - Remove dependency on TSC (getnstimeofday is good enough)
+ *
  * licensed under the GPL
  *
  * You need to have CONFIG_PARPORT disabled for this device, it is a
  * completely self-contained device that assumes sole ownership of the
  * parallel port.
+ *
+ * Notes:
+ *   1.  The above is VERY important! Don't even load the parport module
+ *       because once it is loaded, you might as well reboot.  The parport
+ *       modules (specifically parport_pc) screws up the parport and this
+ *       poor simple lpptest module goes haywire.  Removing the module is
+ *       not even good enough. The parport code just ruins it for lpptest.
+ *       So turn CONFIG_PARPORT to No.
+ *
+ *   2.  This has been tested with the parallel port mode settings of both
+ *       SPP(PS/2) and EPP.  Both should work for both test and monitor
+ *       machines.
+ *
+ *   3.  If it doesn't work:
+ *         a. Check to make sure none of the parport drivers were ever
+ *            loaded (including lp).
+ *         b. Check to make sure you have a data transfer cable.
+ *            Min pin layout:
+ *                 5 - 10
+ *                10 -  5
+ *               GRD - GRD
+ *          c. Make sure that the parallel port connector that sticks out
+ *             of the chassis actually connects to the motherboard **.
+ *
+ *  ** - I spent an entire day trying to figure out why it wasn't working,
+ *       until I opened up the box to find that the connector wasn't plugged
+ *       into the motherboard. Needless to say, I wasn't too happy - SDR
  */
 #include <linux/sched.h>
 #include <linux/kernel.h>
@@ -47,11 +78,24 @@
 #define LPPTEST_DISABLE _IOR (LPPTEST_CHAR_MAJOR, 2, unsigned long long)
 #define LPPTEST_ENABLE  _IOR (LPPTEST_CHAR_MAJOR, 3, unsigned long long)
 
+#define LPPTEST_PORT_BASE 0x378
+
+#define LPPTEST_DATA_PORT (LPPTEST_PORT_BASE)
+#define LPPTEST_STAT_PORT (LPPTEST_PORT_BASE+1)
+#define LPPTEST_CTRL_PORT (LPPTEST_PORT_BASE+2)
+
+#define LPPTEST_PORT_SIZE 3
+
 static char dev_id[] = "lpptest";
 
-#define INIT_PORT()    outb(0x04, 0x37a)
-#define ENABLE_IRQ()   outb(0x10, 0x37a)
-#define DISABLE_IRQ()  outb(0, 0x37a)
+#define lpptest_data_out(x)    outb(x, LPPTEST_DATA_PORT)
+#define lpptest_data_in(x)     inb(LPPTEST_DATA_PORT)
+#define lpptest_stat_in()      inb(LPPTEST_STAT_PORT)
+#define lpptest_ctrl_out(x)    outb(x, LPPTEST_CTRL_PORT)
+
+#define INIT_PORT()    lpptest_ctrl_out(0x04)
+#define ENABLE_IRQ()   lpptest_ctrl_out(0x10)
+#define DISABLE_IRQ()  lpptest_ctrl_out(0x00)
 
 static unsigned char out = 0x5a;
 
@@ -61,37 +105,44 @@ static unsigned char out = 0x5a;
 static int lpptest_irq (int irq, void *dev_id)
 {
        out ^= 0xff;
-       outb(out, 0x378);
+       lpptest_data_out(out);
 
        return IRQ_HANDLED;
 }
 
-static cycles_t test_response(void)
+static u64 test_response(void)
 {
-       cycles_t now, end;
+       struct timespec start, end;
+       u64 startns, endns;
        unsigned char in;
        int timeout = 0;
 
        local_irq_disable();
-       in = inb(0x379);
-       inb(0x378);
-       outb(0x08, 0x378);
-       now = get_cycles();
+
+       in = lpptest_stat_in();
+       lpptest_data_in();
+       lpptest_data_out(0x08);
+
+       getnstimeofday(&start);
        while(1) {
                if (inb(0x379) != in)
                        break;
                if (timeout++ > 1000000) {
-                       outb(0x00, 0x378);
+                       lpptest_data_out(0x00);
                        local_irq_enable();
-
                        return 0;
                }
        }
-       end = get_cycles();
-       outb(0x00, 0x378);
+       getnstimeofday(&end);
+       lpptest_data_out(0x00);
        local_irq_enable();
 
-       return end - now;
+       startns = (u64)start.tv_sec * 1000000000ULL;
+       startns += start.tv_nsec;
+       endns = (u64)end.tv_sec * 1000000000ULL;
+       endns += end.tv_nsec;
+
+       return endns - startns;
 }
 
 static int lpptest_open(struct inode *inode, struct file *file)
@@ -120,7 +171,7 @@ int lpptest_ioctl(struct inode *inode, s
 
        case LPPTEST_TEST: {
 
-               cycles_t diff = test_response();
+               unsigned long long diff = test_response();
                if (copy_to_user((void *)ioctl_param, (void*) &diff, 
sizeof(diff)))
                        goto errcpy;
                break;
@@ -142,17 +193,26 @@ static struct file_operations lpptest_de
 
 static int __init lpptest_init (void)
 {
+       struct resource *res;
+       int ret = -EAGAIN;
+
+       res = request_region(LPPTEST_PORT_BASE, LPPTEST_PORT_SIZE, 
LPPTEST_DEVICE_NAME);
+       if (!res) {
+               printk(KERN_NOTICE "Can't allocate region %x for lpp.\n",
+                      LPPTEST_PORT_BASE);
+               goto out;
+       }
+
        if (register_chrdev(LPPTEST_CHAR_MAJOR, LPPTEST_DEVICE_NAME, 
&lpptest_dev_fops))
        {
                printk(KERN_NOTICE "Can't allocate major number %d for 
lpptest.\n",
                       LPPTEST_CHAR_MAJOR);
-               return -EAGAIN;
+               goto out1;
        }
 
        if (request_irq (LPPTEST_IRQ, lpptest_irq, 0, "lpptest", dev_id)) {
                printk (KERN_WARNING "lpptest: irq %d in use. Unload parport 
module!\n", LPPTEST_IRQ);
-               unregister_chrdev(LPPTEST_CHAR_MAJOR, LPPTEST_DEVICE_NAME);
-               return -EAGAIN;
+               goto out2;
        }
        irq_desc[LPPTEST_IRQ].status |= IRQ_NODELAY;
        irq_desc[LPPTEST_IRQ].action->flags |= IRQF_NODELAY | IRQF_DISABLED;
@@ -161,6 +221,13 @@ static int __init lpptest_init (void)
        ENABLE_IRQ();
 
        return 0;
+ out2:
+       unregister_chrdev(LPPTEST_CHAR_MAJOR, LPPTEST_DEVICE_NAME);
+ out1:
+       release_region(LPPTEST_PORT_BASE, LPPTEST_PORT_SIZE);
+ out:
+       return ret;
+
 }
 module_init (lpptest_init);
 
@@ -170,6 +237,7 @@ static void __exit lpptest_exit (void)
 
        free_irq(LPPTEST_IRQ, dev_id);
        unregister_chrdev(LPPTEST_CHAR_MAJOR, LPPTEST_DEVICE_NAME);
+       release_region(LPPTEST_PORT_BASE, LPPTEST_PORT_SIZE);
 }
 module_exit (lpptest_exit);
 
Index: linux-2.6.20-rt7/scripts/testlpp.c
===================================================================
--- linux-2.6.20-rt7.orig/scripts/testlpp.c     2007-02-16 10:46:56.000000000 
-0500
+++ linux-2.6.20-rt7/scripts/testlpp.c  2007-02-16 14:02:57.000000000 -0500
@@ -4,6 +4,10 @@
  *
  *      Copyright (C) 2005 Thomas Gleixner
  *
+ * Resurrected by Steven Rostedt:
+ *   - Slight code clean up.
+ *   - Remove dependency on TSC (the driver returns nsecs).
+ *
  * licensed under the GPL
  */
 #include <unistd.h>
@@ -51,34 +55,12 @@ static void print_hist(void)
        }
 }
 
-static inline unsigned long long int rdtsc(void)
-{
-       unsigned long long int x, y;
-       for (;;) {
-               __asm__ volatile ("rdtsc" : "=A" (x));
-               __asm__ volatile ("rdtsc" : "=A" (y));
-               if (y - x < 1000)
-                       return y;
-       }
-}
-
-static unsigned long long calibrate_loop(void)
-{
-       unsigned long long mytime1, mytime2;
-
-       mytime1 = rdtsc();
-       usleep(500000);
-       mytime2 = rdtsc();
-
-       return (mytime2 - mytime1) * 2;
-}
-
-#define time_to_usecs(time) ((double)time*1000000.0/(double)cycles_per_sec)
+#define time_to_usecs(time) ((double)time/1000.0)
 
-#define time_to_usecs_l(time) (long)(time*1000000/cycles_per_sec)
+#define time_to_usecs_l(time) (long)(time/1000)
 
 int fd, total;
-unsigned long long tim, sum_tim, min_tim = -1ULL, max_tim, cycles_per_sec;
+unsigned long long tim, sum_tim, min_tim = -1ULL, max_tim;
 
 void cleanup(int sig)
 {
@@ -125,9 +107,6 @@ int main (int argc, char **argv)
 
        ioctl (fd, LPPTEST_DISABLE, &tim);
 
-       fprintf(stderr, "calibrating cycles to usecs: ");
-       cycles_per_sec = calibrate_loop();
-       fprintf(stderr, "%lld cycles per usec\n", cycles_per_sec/1000000);
        if (nr_requests)
                fprintf(stderr, "[max # of requests: %u]\n", nr_requests);
        fprintf(stderr, "starting %dHz test, hit Ctrl-C to stop:\n\n", HZ);
@@ -139,7 +118,7 @@ int main (int argc, char **argv)
                else {
                        hist_hit(time_to_usecs_l(tim));
                        if (tim > max_tim) {
-                               printf ("new max latency: %.2lf usecs (%Ld 
cycles)\n", time_to_usecs(tim), tim);
+                               printf ("new max latency: %.2lf usecs (%Ld 
nsecs)\n", time_to_usecs(tim), tim);
                                max_tim = tim;
                        }
                        if (tim < min_tim)


-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to