/******************************** includes ********************************/

#ifdef LINUX
/* linux stuph, not all of it is necessary */
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/busmouse.h>
#include <linux/signal.h>
#include <linux/errno.h>
#include <linux/mm.h>

/* assembly stuph, not all of it is necessary */
#include <asm/io.h>
#include <asm/segment.h>
#include <asm/system.h>
#include <asm/irq.h>

#include <unistd.h>
#endif

#ifdef DOS
#include <dos.h>
#define  inb(a)     inp(a)
#define  outb(a,b)  outp(b,a)
#endif

#include <stdio.h>

/********************************* defines **********************************/

/* stylistic defines */
#define IS   ==
#define AINT !=
#define AND  &&
#define OR   ||

/* kit timeout in hard-coded loops */
#define TIMEOUT 100000

/* hardware naming abstractions */
/* information from
       http://www.paranoia.com/~filipg/HTML/LINK/PORTS/F_PARALLEL5.html
    by
       Kris Heidenstrom <kheidenstrom@actrix.gen.nz>, 10/19/1994

    and 

       http://www.paranoia.com/~filipg/HTML/LINK/PORTS/F_PARALLEL1.html
    by
       Zahahai Stewart <parport@hisys.com>, 1/9/94
                          (general good stuff here)
 */

/*** offsets for parallel port ***/
/* I'm hard coding in the device address of lpt1 because this needs
 * to be portable between linux and DOS.  :-P   Wait...that doesn't 
 * quite make sense, but let's just say it's harder to code an autodetect
 * sequence for both linux and DOS than to assume that lpt1 is always at
 * the same place (which it usually is, and most people only use lpt1 
 * anyways).
 */

#define LP1_BASE  0x378 
#define DR_OFF    0x0
#define SR_OFF    0x1
#define CR_OFF    0x2

#define LP1_DR    LP1_BASE + DR_OFF
#define LP1_SR    LP1_BASE + SR_OFF
#define LP1_CR    LP1_BASE + CR_OFF

/****
 * 7. Data Register
 * 
 * The data register is at IOBase+0. It may be read and written (using
 * the IN and OUT instructions, or inportb() and outportb() or inp() and
 * outp()). Writing a byte to this register causes the byte value to
 * appear on pins 2 through 9 of the D-sub connector (unless the port is
 * bidirectional and is set to input mode). The value will remain latched
 * until you write another value to the data register. Reading this
 * register yields the state of those pins.
 * 
 *         7 6 5 4 3 2 1 0
 *         * . . . . . . .  D7 (pin 9), 1=High, 0=Low
 *         . * . . . . . .  D6 (pin 8), 1=High, 0=Low
 *         . . * . . . . .  D5 (pin 7), 1=High, 0=Low
 *         . . . * . . . .  D4 (pin 6), 1=High, 0=Low
 *         . . . . * . . .  D3 (pin 5), 1=High, 0=Low
 *         . . . . . * . .  D2 (pin 4), 1=High, 0=Low
 *         . . . . . . * .  D1 (pin 3), 1=High, 0=Low
 *         . . . . . . . *  D0 (pin 2), 1=High, 0=Low
 * 
 ****/

/* no bit twiddles here */

/****
 * 8. Status Register
 * 
 * The status register is at IOBase+1. It is read-only (writes will be
 * ignored). Reading the port yields the state of the five status input
 * pins on the parallel port connector at the time of the read access:
 * 
 *         7 6 5 4 3 2 1 0
 *         * . . . . . . .  Busy . . (pin 11), high=0, low=1 (inverted)
 *         . * . . . . . .  Ack  . . (pin 10), high=1, low=0 (true)
 *         . . * . . . . .  No paper (pin 12), high=1, low=0 (true)
 *         . . . * . . . .  Selected (pin 13), high=1, low=0 (true)
 *         . . . . * . . .  Error. . (pin 15), high=1, low=0 (true)
 *         . . . . . * * *  Undefined
 * 
 ****/

#define SR_BUSY  0x80
#define SR_ACK   0x40
#define SR_NP    0x20
#define SR_SEL   0x10
#define SR_ERR   0x08

/**** 
 * 9. Control Register
 * 
 * The control register is at IOBase+2. It is read/write: 
 * 
 *         7 6 5 4 3 2 1 0
 *         * * . . . . . .  Unused (undefined on read, ignored on write)
 *         . . * . . . . .  Bidirectional control, see below
 *         . . . * . . . .  Interrupt control, 1=enable, 0=disable
 *         . . . . * . . .  Select . . (pin 17), 1=low, 0=high (inverted)
 *         . . . . . * . .  Initialize (pin 16), 1=high, 0=low (true)
 *         . . . . . . * .  Auto Feed  (pin 14), 1=low, 0=high (inverted)
 *         . . . . . . . *  Strobe . . (pin 1),  1=low, 0=high (inverted)
 * 
 ****/

#define CR_BID  0x20
#define CR_INT  0x10
#define CR_SEL  0x08
#define CR_INIT 0x04
#define CR_AUTO 0x02
#define CR_STB  0x01

/****
 * 10. Bidirectional Control Bit
 * 
 * The bidirectional control bit is only supported on true bidirectional
 * ports - on other ports, it behaves like bits 7 and 6. On a proper
 * bidirectional port, setting this bit to '1' causes the outputs of the
 * buffer that drives pins 2 through 9 of the 25-pin connector to go into
 * a high-impedance state, so that data can be _input_ on those pins.
 * 
 * In this state, values written to the data register will be stored in
 * the latch chip, but not asserted on the connector, and reading the
 * data register will yield the states of the pins, which may be driven
 * by an external device without stressing or damaging the port driver.
 * 
 * Also note that on some machines, another port must be set correctly to
 * enable the bidirectional features, in addition to this bit.
 ****/
