Bug 77472

Summary: Inproper result from openning a parallel port device "/dev/pport";
Product: [Retired] Red Hat Linux Reporter: Need Real Name <martin_wpm>
Component: kernelAssignee: Tim Waugh <twaugh>
Status: CLOSED WONTFIX QA Contact: Brian Brock <bbrock>
Severity: medium Docs Contact:
Priority: medium    
Version: 7.3   
Target Milestone: ---   
Target Release: ---   
Hardware: i386   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2002-11-07 17:40:57 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description Need Real Name 2002-11-07 16:36:25 UTC
From Bugzilla Helper:
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)

Description of problem:
1)I can't read out the status register(base+1) of a new-installed
  parallel port device at base 0x378, 0x278, and 0x3bc using a test
  program that has been tested on redhat 7.0/7.1 told by the author
  of book <<practical linux programming>>@2002. Note:1) the parallel 
  port DB25 connector is free, has no wire connection; 2) my printer 
  works well when connected.
2)The more strange is : using the simple test program I can open the
  uninstalled parallel port device "pport", even any named device, say
  "xyz09". And from that I have got the same result as the ones from 
  the installed pport. 

Version-Release number of selected component (if applicable):


How reproducible:
Always

Steps to Reproduce:
1.copy into your machine (a6)pport.c,(a5)test.c,(a4)makefilep,(a3)
  makefilet,(a2)pp_load, and (a1)pp_unload attached at the end of 
  this steps; Note: you may need change INCLUDEDIR of makefilep for 
  pport.c for your redhat version;
2.run make the pport.c and get pport.o;
3.as root, run pp_load;
4.run make the test.c and get t;
5.and in another window, run t and type in 0x55, 0xAA, 0x00, 67, ...
  one each time.
6.run pp_unload goto step 5 or goto step 2 with changing pport-base,
  or replace line 13 fh= open("dev/pport",O_RDWR) with fh = open
  ("/dev/xyz09",O_RDWR), goto step 4.

===================Attached files below here=========================
(a1)pp_unload:
#!/bin/sh
module="pport.o"
device="pport"
# invoke rmmod with all arguments we got
/sbin/rmmod $device || exit 1
# Remove stale nodes
rm -f /dev/${device}

(a2)pp_load:
#!/bin/sh
module="pport.o"
device="pport"
group="root"
mode="664"
#remove any existing node
/sbin/rmmod pport
# invoke insmod with all arguments we got
/sbin/insmod -f $module $device || exit 1
major=`cat /proc/devices | awk "\\$2==\"$device\" {print \\$1}"`
echo "Major number = $major"
rm -f /dev/${device}
mknod /dev/${device} c $major 0
chgrp $group /dev/${device}
chmod $mode  /dev/${device}

(a3)makefilet:
all: t
CC = gcc
INCLUDEDIR = /usr/include
CFLAGS = -g -O2 -Wall -I$(INCLUDEDIR)
t: test.o 
	$(CC) -o t test.o 
test.o: test.c
	$(CC) -c test.c $(CFLAGS)
clean:
	rm -f *.o t

(a4)makefilep:
#INCLUDEDIR = /usr/include
INCLUDEDIR = /usr/src/linux-2.4.18-3/include
DEBFLAGS = -O2
CFLAGS = -D__KERNEL__ -DMODULE -Wall $(DEBFLAGS)
CFLAGS += -I$(INCLUDEDIR)
OBJS = pport.o
all: $(OBJS)
clean:
	rm -f *.o

(a5)test.c:
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>

/*****************************/
void LoopBackTest(int pattern)
{
  int fh, cnt;
   char bfr[2];
   bfr[0] = (char) pattern;
   printf("LoopBack test begin %2.2x\n",bfr[0]);
   fh = open("/dev/pport",O_RDWR);
//   fh = open("/dev/xyz09",O_RDWR);
   if (fh)
   {
     write(fh,bfr,1);
     cnt = read(fh,bfr,1);     
     printf("Status Port bits %2.2x\n",bfr[0] & 0xff);
 close(fh);
   }
   else
     printf("Fail open device\n");
}

/*****************************/
int main(int argc , char *argv[])
{
  int pattern;
   printf("Loop Back test for the parallel port device driver \n");
   printf("Press Ctrl C to exit\n");
   while(1)
   {
     printf ("Data register\n");
     printf ("bit 0 ------> DB25 pin 2\n");
     printf ("bit 1 ------> DB25 pin 3\n");
     printf ("bit 2 ------> DB25 pin 4\n");
     printf ("bit 3 ------> DB25 pin 5\n");
     printf ("bit 4 ------> DB25 pin 6\n");
     printf ("bit 5 ------> DB25 pin 7\n");
     printf ("bit 6 ------> DB25 pin 8\n");
     printf ("bit 7 ------> DB25 pin 9\n");
     printf ("Status register (Notice bit 0,1,2 are not available)\n");
     printf ("bit 3 <------ DB25 pin 15\n");
     printf ("bit 4 <------ DB25 pin 13\n");
     printf ("bit 5 <------ DB25 pin 12\n");
     printf ("bit 6 <--Inverted---- DB25 pin 10\n");
     printf ("bit 7 <------ DB25 pin 11\n");

      printf("Enter bit pattern in hex for data register ");
      scanf ("%x",&pattern);
      LoopBackTest(pattern);
   }
}

(a6)pport.c:
/*
 * pp.c -- Simple Hardware Operations and Raw Tests
 * pp.c -- also a brief example of interrupt handling ("pp int")
 *
 * untested (by now) the hardware r/w
 *
 * Tested with 2.0.18 (intel & alpha -- but no irq available for me)
 * This module won't work on the sparc, where there's no concept of I/O space
 * 
 *********/

#include <linux/module.h>

#include <linux/sched.h>
#include <linux/kernel.h> /* printk() */
#include <linux/fs.h>     /* everything... */
#include <linux/errno.h>  /* error codes */
#include <linux/malloc.h>
#include <linux/mm.h>
#include <linux/ioport.h>
#include <linux/interrupt.h>
#include <linux/tqueue.h>

#include <asm/io.h>
#include <asm/segment.h>
/* #include "sysdep-2.1.h" */

#include <linux/poll.h>


#define READ_IRQ 1


int pp_major = 0;
//int pp_base = 0x378; /* intel: default to lp0 */
//int pp_base = 0x278; /* */
int pp_base = 0x3bc; /* */
int pp_irq = 7;
unsigned long pp_buffer = 0;
int minor = 0;
int IrqCount = 0;
unsigned long volatile pp_head;
volatile unsigned long pp_tail;
struct wait_queue *pp_queue;



int pp_open (struct inode *inode, struct file *filp)
{
    MOD_INC_USE_COUNT;
    minor =(MINOR(inode->i_rdev)&0x0f);

            printk(KERN_INFO "pp:U OPEN %d\n", minor);
    return 0;
}

int pp_close (struct file *filp)
{
    MOD_DEC_USE_COUNT;
    return(0);
}


int pp_read (struct file * filp, char *buf, size_t count, loff_t * t)
{

    unsigned char *kbuf=kmalloc(16, GFP_KERNEL);
    kbuf[1]='\0';

    kbuf[0] = inb(pp_base+1);

    printk(KERN_INFO " READ VALUE pp: %2x\n",*kbuf); 

    copy_to_user(buf, kbuf, 1);

    kfree(kbuf);
    return (0);
}

int pp_write (struct file * filp, const char *buf, size_t count, loff_t * t)
{

    int retval = count;
    unsigned char *kbuf=kmalloc(16, GFP_KERNEL);

    if (!kbuf) 
      return -ENOMEM;

    copy_from_user(kbuf, buf, 1);
    printk(KERN_INFO "pp: WRITE %2x\n",kbuf[0]);

    outb(kbuf[0], pp_base);

    kfree(kbuf);
    return retval;
}

struct file_operations pp_fops = {
  NULL,
    NULL,          /* pp_lseek */
    pp_read,
    pp_write,
    NULL,          /* pp_readdir */
    NULL,
    NULL,
    NULL,          /* mmap */
    pp_open,
    pp_close,
    NULL,          /* pp_fsync */
    NULL,          /* pp_fasync */
                   /* nothing more, fill with NULLs */
};



int init_module(void)
{
    int result = check_region(pp_base,4);

    printk(KERN_INFO "pp: INIT_MOD\n");
    if (result) 
    {
        printk(KERN_INFO "pp: can't get I/O address 0x%x\n",pp_base);
        return result;
    }
    request_region(pp_base,4,"pport");

    result = register_chrdev(pp_major, "pport", &pp_fops);
    if (result < 0) {
        printk(KERN_INFO "pp: can't get major number\n");
        release_region(pp_base,4);
        return result;
    }
    if (pp_major == 0) pp_major = result; /* dynamic */

    pp_buffer = __get_free_page(GFP_KERNEL); /* never fails */
    pp_head = pp_tail = pp_buffer;

    return 0;
}

void cleanup_module(void)
{
    free_irq(pp_irq, NULL);

    unregister_chrdev(pp_major, "pport");
    release_region(pp_base,4);
    if (pp_buffer) 
      free_page(pp_buffer);
}

======================End attached files==========================
	

Actual Results:  
1) Using pport.o with base address 0x378, yuo can't pass pp_load due
   to device or resources busy, see result below;
2) with installed pport.o, you will get what you type in: that's,
   in 0x55, out 55; in 0xAA, out aa; in 0x00, out 00; in 67,out 67;
   ... see the attached results at the end of this section;
3) with pp_unload pport.o or without installed pport.o at all(from
   restart system after pp_unload), you will get the same result as
   1) even you can change the opened device name of the test progam 
   into "dev/xyz09". 

======================Attached results below here===================
1) using pport.o with base_address 0x378:
[root simple:684]# pp_load
rmmod: module pport is not loaded
Warning: loading pport.o will taint the kernel: no license
Warning: loading pport.o will taint the kernel: forced load
pport.o: init_module: Device or resource busy
Hint: insmod errors can be caused by incorrect module parameters, including 
invalid IO or IRQ parameters
[root simple:685]#

2) with or without pport.o installed with base address 0x278 or 0x3bc:
[test:1002]$ t
Loop Back test for the parallel port device driver
Press Ctrl C to exit
Data register
bit 0 ------> DB25 pin 2
bit 1 ------> DB25 pin 3
bit 2 ------> DB25 pin 4
bit 3 ------> DB25 pin 5
bit 4 ------> DB25 pin 6
bit 5 ------> DB25 pin 7
bit 6 ------> DB25 pin 8
bit 7 ------> DB25 pin 9
Status register (Notice bit 0,1,2 are not available)
bit 3 <------ DB25 pin 15
bit 4 <------ DB25 pin 13
bit 5 <------ DB25 pin 12
bit 6 <--Inverted---- DB25 pin 10
bit 7 <------ DB25 pin 11
Enter bit pattern in hex for data register 0x55
LoopBack test begin 55
Status Port bits 55
Data register
bit 0 ------> DB25 pin 2
bit 1 ------> DB25 pin 3
bit 2 ------> DB25 pin 4
bit 3 ------> DB25 pin 5
bit 4 ------> DB25 pin 6
bit 5 ------> DB25 pin 7
bit 6 ------> DB25 pin 8
bit 7 ------> DB25 pin 9
Status register (Notice bit 0,1,2 are not available)
bit 3 <------ DB25 pin 15
bit 4 <------ DB25 pin 13
bit 5 <------ DB25 pin 12
bit 6 <--Inverted---- DB25 pin 10
bit 7 <------ DB25 pin 11
Enter bit pattern in hex for data register
00
LoopBack test begin 00
Status Port bits 00
Data register
bit 0 ------> DB25 pin 2
bit 1 ------> DB25 pin 3
bit 2 ------> DB25 pin 4
bit 3 ------> DB25 pin 5
bit 4 ------> DB25 pin 6
bit 5 ------> DB25 pin 7
bit 6 ------> DB25 pin 8
bit 7 ------> DB25 pin 9
Status register (Notice bit 0,1,2 are not available)
bit 3 <------ DB25 pin 15
bit 4 <------ DB25 pin 13
bit 5 <------ DB25 pin 12
bit 6 <--Inverted---- DB25 pin 10
bit 7 <------ DB25 pin 11
Enter bit pattern in hex for data register 0xAA
LoopBack test begin ffffffaa
Status Port bits aa
Data register
bit 0 ------> DB25 pin 2
bit 1 ------> DB25 pin 3
bit 2 ------> DB25 pin 4
bit 3 ------> DB25 pin 5
bit 4 ------> DB25 pin 6
bit 5 ------> DB25 pin 7
bit 6 ------> DB25 pin 8
bit 7 ------> DB25 pin 9
Status register (Notice bit 0,1,2 are not available)
bit 3 <------ DB25 pin 15
bit 4 <------ DB25 pin 13
bit 5 <------ DB25 pin 12
bit 6 <--Inverted---- DB25 pin 10
bit 7 <------ DB25 pin 11
Enter bit pattern in hex for data register
[test:1003]$

3) check if there is a port related name "pport" or "xyz09":no at all;
[root simple:681]# /sbin/lsmod
Module                  Size  Used by    Not tainted
nls_iso8859-1           3488   1  (autoclean)
sr_mod                 16920   2  (autoclean)
emu10k1                64096   0  (autoclean)
ac97_codec             11904   0  (autoclean) [emu10k1]
sound                  72012   0  (autoclean) [emu10k1]
soundcore               6692   7  (autoclean) [emu10k1 sound]
r128                   94680   1
agpgart                39488   3
binfmt_misc             7556   1
parport_pc             18724   1  (autoclean)
lp                      8864   0  (autoclean)
parport                34208   1  (autoclean) [parport_pc lp]
autofs                 12164   0  (autoclean) (unused)
8139too                16448   1
mii                     2408   0  [8139too]
ipchains               43560  12
ide-scsi                9664   1
scsi_mod              108608   2  [sr_mod ide-scsi]
ide-cd                 30272   0
cdrom                  32192   0  [sr_mod ide-cd]
usb-uhci               24484   0  (unused)
usbcore                73152   1  [usb-uhci]
ext3                   67136   3
jbd                    49400   3  [ext3]
[root simple:682]# cat /proc/devices
Character devices:
  1 mem
  2 pty
  3 ttyp
  4 ttyS
  5 cua
  6 lp
  7 vcs
 10 misc
 14 sound
 29 fb
 36 netlink
128 ptm
129 ptm
130 ptm
131 ptm
132 ptm
133 ptm
134 ptm
135 ptm
136 pts
137 pts
138 pts
139 pts
140 pts
141 pts
142 pts
143 pts
162 raw
180 usb
226 drm

Block devices:
  1 ramdisk
  2 fd
  3 ide0
  9 md
 11 sr
 12 unnamed
 14 unnamed
 22 ide1
 38 unnamed
 39 unnamed
[root simple:683]# ls /dev/pp*
/dev/ppp  /dev/pppox0  /dev/pppox1  /dev/pppox2  /dev/pppox3

======================End attached results========================== 

Expected Results:  I should get the initialize value of the status register of 
pc
whatever I type in : for an example, I should have 00 if the 
register is initialized as 0x00, or have ff if initialized as 
0xff, and  so on;

Additional info:

No any wire connection on DB25 connector for all testing.

Comment 1 Need Real Name 2002-11-07 17:29:32 UTC
expected results added:

for uninstalled parallel port driver, I should get -1 return from open function

for unsuccesful device openning instead the current successful openning.

Comment 2 Tim Waugh 2002-11-07 17:40:50 UTC
This is a driver that we do not ship, and so can't support.

Why not use the 'ppdev' driver, which we *do* ship?  It provides backing for
/dev/parport0.  To read how to use it look at http://cyberelk.net/tim/parport/html/.

For even better results, use the libieee1284 library from
http://cyberelk.net/tim/libieee1284.

Comment 3 Need Real Name 2002-11-08 00:36:49 UTC
I got what you mean from cyberelk.net/tim/parport/html: k2.4 and k2.0 have
different locations and methods for their parallel ports.

I will try libieee1284.

Thank you very much.

Martin