
This driver supports mapping of KPCI-PIO96 ports and control registers
into user process memory on x86 architectures. It will not work on
Power PC or Alpha machines. The driver is designed to support multiple
cards, but this feature is not tested. Work on multi-CPU machines is not
tested. Questions and bug reports should be addressed to Igor Volobouev,
igv@lbl.gov.


Installation Instructions
-------------------------

1. Uncompress and untar the downloaded file:

   gunzip kpci_pio96.tar.gz
   tar -xvf kpci_pio96.tar

   This should create the directory Kpci_pio96. Do "cd Kpci_pio96".

2. If the major device number 26 is in use then edit the following line
   in the Makefile:

   MAJOR_DEV = 26
	
   Run "cat /proc/devices" to find out which major numbers are in use.

3. To compile, type:

   make

4. To make the appropriate devices, run the following as root:
 
   make devices

   This will create a new device node /dev/kpci/card0. If you have more
   than one KPCI-PIO96 card, you need to create more device nodes:

   /bin/mknod /dev/kpci/card1 c $(MAJOR_DEV) 1
   /bin/mknod /dev/kpci/card2 c $(MAJOR_DEV) 2

   etc., one device node for each card. Here, $(MAJOR_DEV) is the major
   device number (default value is 26). I don't know which device node
   will correspond to which card, you'll have to experiment (or ask
   your local PCI & Linux guru).

5. To install the driver, run as root:

   make install

6. Make sure nothing is connected to the last port on the card (the test
   program will try to write there). Run the test program:

   kpci_test

   On a few machines, the test program may fail because the card PCI memory
   address is not mapped by the BIOS into the CPU memory space on a page
   boundary. Run "/sbin/lspci -v" (or "cat /proc/pci" on older kernels).
   If the last three hex digits of the card memory physical address are not
   zeros, you will have to change the definition of PHYSICAL_OFFSET in
   the kpci_test.c file. For example, the lspci program may print something
   like this:

   > 00:0d.0 Class ff00: Keithley Metrabyte: Unknown device 0012
   >         Flags: bus master, fast devsel, latency 32
   >         Memory at ea106060 (32-bit, non-prefetchable)
   >         Memory at ea106020 (32-bit, non-prefetchable)
   >         Expansion ROM at e9000000 [disabled]

   In this case PHYSICAL_OFFSET has to be set to 0x020.

   If you see this problem, it may be a sign that the PCI memory space
   is too congested. Check that no other PCI cards use the same memory
   page (in the example above, that would be any address between
   0xea106000 and 0xea106fff). If PCI memory from other cards is also
   mapped into this page then you might want to tweak your BIOS so that
   this is no longer the case. Otherwise you run the risk of screwing up
   some other card in case of inappropriate use of the driver.

7. To start the driver automatically at boot time add the following
   line to the end of your /etc/rc.d/rc.local file:

   /sbin/insmod /usr/local/lib/kpci_pio96.o



Using the Driver
----------------

Basic usage is as follows:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <errno.h>
#include "kpci_pio96.h"

#define PHYSICAL_OFFSET 0x0          /* This is usually OK, but see
                                        item 6 in the installation
                                        instructions */
#define DEVICENAME "/dev/kpci/card0" /* or card1, card2, etc. if you
                                        have more than one card in the
                                        system */

int fd;                          /* file descriptor for the device */
Kpci_registers volatile * card;  /* Kpci_registers must be declared 
                                    volatile so that port accesses
                                    are not optimized away */
void *mem;                       /* temporary variable to hold
                                    the result of "mmap" system call */

if ((fd = open(DEVICENAME, O_RDWR)) < 0) {	
    fprintf(stderr, "error opening device %s\n", DEVICENAME);
    perror("your_program_name");
    exit(1);
}
mem = mmap(NULL, getpagesize(), PROT_WRITE | PROT_READ, MAP_SHARED, fd, 0);
if (mem == MAP_FAILED) {
    fprintf(stderr, "memory mapping failed\n");
    perror("your_program_name");
    exit(2);
}
card = (Kpci_registers *)(mem + PHYSICAL_OFFSET);

If everything goes fine, at this point in your program you will have
full access to the card ports and control registers. See the
description of type Kpci_registers in file kpci_pio96.h and read the
KPCI-PIO96 user's manual I/O address mapping section in order to
understand port access in full detail. For example, to configure
ports A and B for input and port C for output in port group 2 do the
following:

card->ctrl[2] = KPCI_PORTC_LO_OUT | KPCI_PORTC_HI_OUT;

Now, to set port C to some value do:

card->port[2] = kpci_toport(0, 0, some_8bit_value);

To read all ports in group 1 as a 32-bit number use something like:

unsigned int tmp;
tmp = card->port[1];

This 32-bit number has idiosyncratic bit assignments (see kpci_pio96.h
for details). To convert it into a "normal" number, where port A
represents the least significant byte, port B is the second byte, and
port C is the third byte, use

kpci_fromport32(tmp);

The driver makes sure that another process can not access the same card
while the device file is open. If you really want to access the card from 
several processes simultaneously, undefine ENABLE_BUSY_CONTROL in file
kpci_pio96.c.

