Linux 2.6.x driver installation instructions and notes for Tahoma Technology's PCI Hardcopy interface Model 10117. Tahoma Technology (formerly IKON Corporation) 107 2nd Avenue, Seattle, WA, USA 98109 206.728.6465 http://www.tahomatech.com tahoma@tahomatech.com About Tahoma Technology: Tahoma Technology has purchased certain of the assets of Ikon Corporation from IKON Office Solutions (IOS). That's the legal version. What has happened is that the people who started and operated Ikon Corporation initially and under IOS have purchased the division back. We continue the same product line and support. References to "Ikon" here and elsewhere are left in place for historical and compatibility reasons. Tahoma/Ikon code and documentation has been previously, and remains, in the public domain. Driver Installation & Notes: This version of the driver was tested under Linux 2.6. It is NOT compatible with earlier versions of Linux. The initial release of this driver was the first that did DMA direct from user buffers, using the kiobuf capability in Linux 2.3/2.6. This version moves the user buffer mapping code into the driver itself - since kiobufs are not available in 2.6x. If the kernel has been configured for greater than 4G of RAM, the driver will be compiled to use a kernel copy buffer instead of mapping user buffers for DMA. Copy buffer mode may also be forced by an install script option. In x86_64 systems, the available iommu is used to map high memory addresses to 32 bit address space, so a copy buffer is not necessary. Hopefully our HIGHMEM config detection won't trip on x86_64 systems. The install script also attempts to autodetect the appropriate include directory: /lib/modules/`uname -r/build/inlcude and /usr/src/linux, in that order. NOTE: the driver and install script now support both 10115 and 10117 boards. This document is written assuming a 10117, but it also applies to the 10115. Board types may be mixed in a system. Other install script options are described below. Other files included in this release: ihcp_driver.c code source module for the Linux PCI hardcopy driver ihcp_var.h structure definition file for the PCI hardcopy driver ihcp_reg.h register definition file for the PCI hardcopy driver ihcp_io.h ioctl command definition file for the PCI hardcopy driver - to be #include'd' in the calling program ihcp_changes.h change dates and descriptions & module ID macros for the driver Makefile simple makefile for the new kbuild system ihcp_install-2.6 used to compile and load driver module iktest0.c very simple sample program that calls the hardcopy driver filtertest.c simple filter that adds carriage returns to text files for printing (on laserjet, for example) ikonex.c command line or interactive driver/board/plotter exercise & test utility The hardcopy driver is a module that can be loaded into a running kernel. Before loading, the driver should be compiled on the target machine, and the object module placed in an appropriate /lib/module directory. The install script will do this automatically. ihcp_install-2.6: ihcp_install-2.6 can be used to compile, load, and enable boot loading of the driver, or may be used to manually perform each of these steps individually. The ihcp_install-2.6 script provided can be used to compile the standard or debug version of the driver and place it in the correct directory. To compile the object and place in /lib/modules/`uname -r`/misc: (as super user) ./ihcp_install-2.6 compile To compile the debug version of the driver: (as super user) ./ihcp_install-2.6 compile debug Note that the debug version of the driver generates numerous printk() calls, and should only be used for diagnostic purposes! The ihcp_install-2.6 script provided will load the module and create the device node(s) in the /dev directory. Node names will be ihcp0, ihcp1, ... To load the driver module into a running kernel: (as super user) ihcp_install-2.6 load Once loaded, the driver will be available until unloaded or the system is rebooted. To cause the driver to be loaded when the system is booted: (as super user) ihcp_install-2.6 autoload This will create /etc/ihcp (if not already present) and copy ihcp_install-2.6 to /etc/ihcp. It also adds a line to the end of /etc/rc.d/rc.local which will invoke "/etc/ihcp/ihcp_install-2.6 load" at boot time. Directory and script permissions are set to rwx access for root, and read only for everyone else. When the install script is invoked via rc.local at boot time, standard and error outputs are logged to /etc/ihcp/ihcp_install-2.6.bootlog. In the event of problems with autoloading the driver at boot time, inspect this log for possible diagnostic information. NOTE that any changes made to the local copy of ihcp_install-2.6 after this point will not be reflected in the copy in /etc/ihcp which is invoked at boot time. Use the ihcp_install-2.6 "autoload" or "all" option to update the copy in /etc/ihcp. To remove the driver module from the kernel, delete the driver object from the modules directory, remove the rc.local entry, remove /etc/ihcp (if empty after removing ihcp_install-2.6*), and delete the device node(s): (as super user) ihcp_install-2.6 remove To remove, compile, load, and enable autoloading of the driver with a single command: (as super user) ihcp_install-2.6 all or (as super user) ihcp_install-2.6 all debug The script will try to determine the appropriate compile include directory: This is somewhat of a moving target. Tested for, in order, are: /lib/modules/`uname -r`/build/include and /usr/src/linux. If no directory in the list is detected, the compiler is allowed to use its default include directory (probably /usr/include). The default directory is usually not suitable for compiling driver modules, and will cause warnings and errors. The install script will allow for multiple boards up to a maximum set by the IHCP_BOARDS variable. The current default is 4. Increase as necessary. The script will only create device nodes for boards actually found (as determined by idr devices found in /proc/interrupts. The device node(s) will be created with owner=bin group=bin and permissions=666. Other script variables that control the default configuration of the driver and board, as well as the behavior of the script itself may be modified. See the Driver Default Parameters section, below, for information on driver "defines". See the script code for script variable information. NOTES: Residual Byte Counts: It is a unix convention that the read and write routines return a count of the number of bytes actually transferred. Unfortunately, the pci interface chip on the 10117 does not have a readable dma range counter. Therefore, the hardcopy driver always indicates that all bytes requested in a write call were transferred. Unless an error was encountered, this will in fact always be the case. Errors will be indicated by the driver returning an error code after a read or write call. In general, bytes lost in an aborted read or write cannot be re-sent successfully anyway, so the "actual" byte count would serve little purpose. IOCTL parameters: The PCI hardcopy driver maintains ioctl() compatibility with Tahoma's SunOS and Solaris drivers for Sbus boards, and with the Solaris and Solaris 7 drivers for Pci boards. It is also compatible with Tahoma's HP-UX drivers. Also defined are a set of commands intended to be compatible with SUN's and Versatec's drivers for Tahoma's model 10088 VMEbus board. This should allow existing printer/plotter applications to run with little or no modification. Note that the ihcp_io.h file for Linux is slightly different from the ihcp_io.h files provided with the drivers for Solaris 1 and 2 and HP-UX. The old and new ....io.h files will generate the same ioctl commands, but are not interchangeable. Use the new xxxx_io.h files when compiling on a Linux machine. NOTE: A call to the 10117 driver ioctl code looks like: ioctl(filedes,cmd,arg); filedes is the file descriptor of the open device, cmd is a command defined in ihcp_io.h, and arg is a pointer. For most ioctls arg will point to a 32 bit variable. IHCP_GET_REGS requires an array of IHCP_RETURN_ARRAY_SIZE 32 bit integers, as in: __u32 argarray[IHCP_RETURN_ARRAY_SIZE]; IHCP_DATA_OUT takes a char array of output data bytes. These variable and array sizes are the same for both 32 and 64 bit applications. Size-invariant data types such as __u32 should be used when defining ioctl arg pointer targets variables. #include "./idr_io.h" will pick up and include the fixed types. Auto Line Terminate ioctls: The Pci Hardcopy boards and driver support auto line terminate when in Versatec mode. When this mode is enabled, raster data can be streamed through the driver and board, and the board will automatically transmit line terminate commands to the plotter based on a programmable count. This can provide additional transfer efficiency when plotting to an area smaller than the plotters full raster width. With this feature, it is not necessary to pad each raster to the full plotter width. Use IHCPIO_AUTO_LTR_COUNT to set the desired count. IHCPIO_AUTO_LTR_ON and _OFF enable and disable the auto ltr functrion. The _ON and _OFF ioctls flow through the fifo with other data and commands, but _COUNT does NOT. The count should not be written when there is any data in the fifo if auto ltr is currently enabled, or has been previously enabled. In the current implementation of the driver, this requirement persists across open() and close(). In order to maintain maximum pipelining, the driver does not wait for fifo empty and device ready in either open() or close(). If the calling program(s) use the auto ltr feature, it may be necessary to use the IHCPIO_RDY_WAIT ioctl after open, and/or before close. Calling this ioctl after open, rather than prior to close will allow maximum overlap between calling program execution, and data transfer to the attached plotter. Device Names: The application code calling the Hardcopy driver may expect a different node name than that created by the install script (vp0, lp0, etc.) if it was originally written to talk to the VME hardcopy driver or Versatec's Sbus driver. It may be necessary to establish a symbolic link between the /dev/... entry that the application expects to see, and the /dev/ihcp0 (or 1, or 2, or ...) that ihcp_install-2.6 creates. Hardcopy Sample Program: Iktest0.c is a (very) simple sample program that calls the hardcopy driver, and prints a few lines of "hello world". This can be used as a simple test, and indicates in general how to use the ioctl call, and how writes are done. Iktest0 sets PRINT mode if VPI strapping is detected. iktest0.c detects the board strapping - Centronics or VPI - and sets print mode if the board is set for VPI. Filtertest: This tiny program is a sample filter that can be used when printing through the hardcopy driver. It will scan its input, looking for new line characters, and will add a carriage return when it finds a new line. This allows printing unix text files to printers that require carriage returns - HP laserjet is one example. To print directly to the hardcopy device, one might do something like: pr | ./filtertest > /dev/ihcp0 Ikonex: This is a command line utility that can be used to exercise the driver/board/plotter combination. With ikonex it is possible to issue commands, send (pre-existing)data files, and read status to/from the attached plotter. It must be compiled in the same directory as ihcp_io.h. Ikonex may be run entirely from a command line, or in interactive mode. It is self- documenting. After compiling, run ./ikonex for further information. Driver Default Properties: Several driver defaults and compile options may be changed by editing ihcp_install-2.6 and reloading the driver. A debug compile options may also be selected as a command line option to the install script. Many of these defaults may also be overridden by application programs, using ioctl() calls. IHCP_BOARDS: The driver init_module code will probe for the number of boards specified by IHCP_BOARDS. The pci bios probe function will be called repeatedly until no further boards are found, or IHCP_BOARDS is exhausted. Specifying a board count larger than the number of boards present will be somewhat wasteful of kernel memory, as each (potential) board requires a kmalloc'd state structure. The install script wil create as many device nodes as specified by IDR_BOARDS, regardless of the number of boards actually found. Node names will be ihcp0, ihcp1, ... The default value is 4. IHCP_VERS_SPEED: IHCP_CENT_SPEED: The handshake speed for Centronics and Versatec compatible plotters may be set separately using the IHCP_VERS_SPEED and IHCP_CENT_SPEED variables, respectively. The available choices for each are 0 through 3, with 0 giving the fastest handshake. Generally speaking, the fastest handshake that gives relaible data transfer should be used. Many Versatec compatible plotters will tolerate speed 0, while most Centronics compatible devices will require speed 1 or slower. The factory defaults are both 1. IHCP_MODE: The load-time default mode for Versatec compatible devices is selected by the IHCP_MODE variable. If it is 0, the board and plotter will default to print mode. If it is 1, plot mode will be selected. The default mode as shipped is plot mode. IHCP_DMA_TIME: IHCP_FIFO_TIME: Two software timers are used in the driver. One controls how long the driver waits for a DMA transfer to complete. The other times the wait for device ready or fifo <1/2 full ioctl. These times are set by IHCP_DMA_TIME, and IHCP_FIFO_TIME, respectively. The appropriate variable should be set equal to the desired timeout value in SECONDS. Some plotters can take a relatively long time to complete a transfer, or a plot, so numbers like 1800 seconds (30 minutes) are not unreasonable. The values as shipped from the factory are 1800 seconds for each timer. IHCP_MAX_PHYS_ORDER: This version of the driver does DMA directly from mapped and pinned user buffer when possible. It will do a maximum of 2**IHCP_MAX_PHYS_ORDER * PAGE_SIZE bytes per DMA transfer. User buffers larger than this value will be transferred in multiple DMA blocks, transparently to the calling program. In the case of a HIGHMEM_64G (but not x86_64) enabled kernel a copy buffer of 2**IHCP_MAX_PHYS_ORDER * PAGE_SIZE bytes will be allocated. Larger DMA transfers will improve overall efficiency somewhat, by minimizing the number of interrupts taken per user buffer (one per DMA block transfer). The tradeoff, of course, is the kernel memory and mapping resources used to map and pin the buffer, and build the scatter-gather list for the board's DMA mechanism. (On non-PC architectures - not tested yet - there will also be increased usage of iommu mapping resources). Given the quantities of cheap memory available on PC's, one should probably just choose a buffer size that keeps the plotter happy. IHCP_MAX_PHYS_ORDER is specified in "orders". That is, 2**IHCP_MAX_PHYS_ORDER * PAGE_SIZE gives the max transfer size in bytes. The default is 4, which with the current 4K page size gives 64k max bytes per transfer. IHCP_BYTE_ORDER: Typically, PCI bus DMA transfers on a PC shold be done low byte first (little endian mode). Some platforms may require transfers to be high byte first (big endian mode). Setting this default parameter to 0 puts the board and driver into little endian mode. A 1 selects big endian mode. The default is 0. Compile Options: IHCP_DEBUG: Causes the driver to emit _many_ diagnostic printfs during operation. Do not use during normal production plotting! IHCP_USER_DMA: IHCP_USER_DMA = AUTO allows the driver to compile in user buffer DMA mode, as long as CONFIG_HIGHMEM_64G is not true. If the kernel supports > 4G of RMA (CONFIG_HIGHMEM_64G true) a copy buffer will be used - except in x86_64 systems. If IHCP_USER_DMA = NO, a copy buffer will always be used. IHCP_FORCE_LOAD: If this option = YES, the -f (force) option will be used when the driver is loaded by insmod. This is probably not a good idea as it will ignore some important driver/kernel compatibility checks. It may be helpful during driver development.