Exotic PCI hardware that busts under 2.1.xx

First Spirit Sauron (sauron@angband.ee.ualberta.ca)
Mon, 9 Mar 1998 22:13:55 -0700


Hi there,

I've got a rather exotic piece of hardware:

It's a dipix capture card ( very cool, it's got a TI C40 DSP chip on it,
maybe I could get that thing checking rc5 keys too. )

Anyhow, the people at dipix were kind enough to write a driver for it for
linux. I insert it into the running kernel: ( config follows ), and it's
happy. The fun thing, is it worked under 2.0.33, but if I try and use it
under 2.1.89, I get the kernel pukes on me.

Any and all help is appreciated. I've tried to provide as much info as
possible.

--Jack

[root@angband driver2.1]# insmod xpgdrv.o
xpg: Driver initialized on major 60

[root@angband getpic]# ./getpic blem
xpg: Device opened
PCI->APIC IRQ transform: (B0,I10,P0) -> 18
xpg: Attempted I/O to illegal port 653f.
xpg: Attempted I/O to illegal port 653e.
xpg: Attempted I/O to illegal port 653f.
xpg: Attempted I/O to illegal port 653e.
xpg: Attempted I/O to illegal port 653f.
Loading the COFF file
xpg: Attempted I/O to illegal port 653c.
xpg: Attempted I/O to illegal port 653c.
xpg: Attempted I/O to illegal port 6601.
xpg: Attempted I/O to illegal port 6600.
xpg: Attempted I/O to illegal port 653c.
xpg: Attempted I/O to illegal port 6538.
xpg: Attempted I/O to illegal port 6601.
xpg: Attempted I/O to illegal port 653c.
xpg: Attempted I/O to illegal port 653c.
xpg: Attempted I/O to illegal port 6601.
xpg: Attempted I/O to illegal port 6600.
xog: Attempted I/O to illegal port 653c.
xpg: Attempted I/O to illegal port 6538.
xpg: Attempted I/O to illegal port 6601.
xpg: Attempted I/O to illegal port 6520.
xpg: Attempted I/O to illegal port 6520.
xpg: Attempted I/O to illegal port 6520.
xpg: Attempted I/O to illegal port 6520.
xpg: Attempted I/O to illegal port 6520.
....

=======================================================

PCI devices found:
Bus 0, device 12, function 0:
SCSI storage controller: Adaptec AIC-7880U (rev 0).
Medium devsel. Fast back-to-back capable. IRQ 3. Master Capable. Latency=32. Min Gnt=8.Max Lat=8.
I/O at 0x6000 [0x6001].
Non-prefetchable 32 bit memory at 0xe1001000 [0xe1001000].
Bus 0, device 11, function 0:
VGA compatible controller: ATI Mach64 GT (Rage II) (rev 72).
Medium devsel. Fast back-to-back capable. IRQ ff.
Non-prefetchable 32 bit memory at 0xe0000000 [0xe0000000].
I/O at 0x6700 [0x6701].
Bus 0, device 10, function 0:
Unknown class: Unknown vendor Unknown device (rev 0).
Vendor id=1246. Device id=2e5c.
Fast devsel. Fast back-to-back capable. IRQ a. Master Capable. Latency=32.
I/O at 0x6500 [0x6501].
I/O at 0x6600 [0x6601].
Bus 0, device 9, function 0:
Ethernet controller: DEC DC21140 (rev 34).
Medium devsel. Fast back-to-back capable. IRQ b. Master Capable. Latency=32. Min Gnt=20.Max Lat=40.
I/O at 0x6400 [0x6401].
Non-prefetchable 32 bit memory at 0xe1000000 [0xe1000000].
Bus 0, device 7, function 1:
IDE interface: Intel 82371SB PIIX3 IDE (rev 0).
Medium devsel. Fast back-to-back capable. Master Capable. Latency=32.
I/O at 0xf000 [0xf001].
Bus 0, device 7, function 0:
ISA bridge: Intel 82371SB PIIX3 ISA (rev 1).
Medium devsel. Fast back-to-back capable. Master Capable. No bursts.
Bus 0, device 0, function 0:
Host bridge: Intel 82439HX Triton II (rev 3).
Medium devsel. Master Capable. Latency=32.

=======================================================

#
# Automatically generated by make menuconfig: don't edit
#

#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y

#
# Processor type and features
#
# CONFIG_M386 is not set
# CONFIG_M486 is not set
CONFIG_M586=y
# CONFIG_M686 is not set
# CONFIG_MATH_EMULATION is not set

#
# Loadable module support
#
CONFIG_MODULES=y
# CONFIG_MODVERSIONS is not set
# CONFIG_KERNELD is not set

#
# General setup
#
CONFIG_NET=y
CONFIG_PCI=y
CONFIG_PCI_BIOS=y
CONFIG_PCI_DIRECT=y
CONFIG_PCI_OPTIMIZE=y
CONFIG_PCI_OLD_PROC=y
# CONFIG_MCA is not set
CONFIG_SYSVIPC=y
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
CONFIG_BINFMT_AOUT=y
CONFIG_BINFMT_ELF=y
CONFIG_BINFMT_MISC=y
# CONFIG_BINFMT_JAVA is not set
# CONFIG_VIDEO_SELECT is not set
# CONFIG_PARPORT is not set

#
# Plug and Play support
#
# CONFIG_PNP is not set

#
# Floppy, IDE, and other block devices
#
CONFIG_BLK_DEV_FD=y
CONFIG_BLK_DEV_IDE=y
# CONFIG_BLK_DEV_HD_IDE is not set
# CONFIG_BLK_DEV_IDEDISK is not set
CONFIG_BLK_DEV_IDECD=y
# CONFIG_BLK_DEV_IDETAPE is not set
# CONFIG_BLK_DEV_IDEFLOPPY is not set
# CONFIG_BLK_DEV_IDESCSI is not set
# CONFIG_BLK_DEV_CMD640 is not set
# CONFIG_BLK_DEV_RZ1000 is not set
CONFIG_BLK_DEV_IDEPCI=y
CONFIG_BLK_DEV_IDEDMA=y
# CONFIG_BLK_DEV_OPTI621 is not set
# CONFIG_BLK_DEV_TRM290 is not set
# CONFIG_BLK_DEV_NS87415 is not set
# CONFIG_IDE_CHIPSETS is not set
# CONFIG_BLK_DEV_LOOP is not set
# CONFIG_BLK_DEV_MD is not set
# CONFIG_BLK_DEV_RAM is not set
# CONFIG_BLK_DEV_XD is not set
CONFIG_PARIDE_PARPORT=y
# CONFIG_PARIDE is not set
# CONFIG_BLK_DEV_HD is not set

#
# Networking options
#
CONFIG_PACKET=y
# CONFIG_NETLINK is not set
# CONFIG_FIREWALL is not set
# CONFIG_NET_ALIAS is not set
# CONFIG_FILTER is not set
CONFIG_UNIX=y
CONFIG_INET=y
# CONFIG_IP_MULTICAST is not set
# CONFIG_IP_ADVANCED_ROUTER is not set
# CONFIG_IP_PNP is not set
# CONFIG_IP_ACCT is not set
# CONFIG_IP_ROUTER is not set
# CONFIG_NET_IPIP is not set
# CONFIG_NET_IPGRE is not set
# CONFIG_IP_ALIAS is not set
# CONFIG_SYN_COOKIES is not set
# CONFIG_INET_RARP is not set
CONFIG_IP_NOSR=y
CONFIG_SKB_LARGE=y
# CONFIG_IPV6 is not set
# CONFIG_IPX is not set
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
# CONFIG_BRIDGE is not set
# CONFIG_LLC is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_FASTROUTE is not set
# CONFIG_NET_HW_FLOWCONTROL is not set
# CONFIG_CPU_IS_SLOW is not set
# CONFIG_NET_SCHED is not set
# CONFIG_NET_PROFILE is not set

#
# SCSI support
#
CONFIG_SCSI=y
CONFIG_BLK_DEV_SD=y
# CONFIG_CHR_DEV_ST is not set
# CONFIG_BLK_DEV_SR is not set
# CONFIG_CHR_DEV_SG is not set
CONFIG_SCSI_MULTI_LUN=y
CONFIG_SCSI_CONSTANTS=y
# CONFIG_SCSI_LOGGING is not set

#
# SCSI low-level drivers
#
# CONFIG_SCSI_7000FASST is not set
# CONFIG_SCSI_AHA152X is not set
# CONFIG_SCSI_AHA1542 is not set
# CONFIG_SCSI_AHA1740 is not set
CONFIG_SCSI_AIC7XXX=y
CONFIG_AIC7XXX_TAGGED_QUEUEING=y
CONFIG_OVERRIDE_CMDS=y
CONFIG_AIC7XXX_CMDS_PER_LUN=8
CONFIG_AIC7XXX_PAGE_ENABLE=y
CONFIG_AIC7XXX_PROC_STATS=y
CONFIG_AIC7XXX_RESET_DELAY=15
# CONFIG_SCSI_ADVANSYS is not set
# CONFIG_SCSI_IN2000 is not set
# CONFIG_SCSI_AM53C974 is not set
# CONFIG_SCSI_BUSLOGIC is not set
# CONFIG_SCSI_DTC3280 is not set
# CONFIG_SCSI_EATA_DMA is not set
# CONFIG_SCSI_EATA_PIO is not set
# CONFIG_SCSI_EATA is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
# CONFIG_SCSI_GDTH is not set
# CONFIG_SCSI_GENERIC_NCR5380 is not set
# CONFIG_SCSI_NCR53C406A is not set
# CONFIG_SCSI_NCR53C7xx is not set
# CONFIG_SCSI_NCR53C8XX is not set
# CONFIG_SCSI_PAS16 is not set
# CONFIG_SCSI_PCI2000 is not set
# CONFIG_SCSI_PCI2220I is not set
# CONFIG_SCSI_PSI240I is not set
# CONFIG_SCSI_QLOGIC_FAS is not set
# CONFIG_SCSI_QLOGIC_ISP is not set
# CONFIG_SCSI_SEAGATE is not set
# CONFIG_SCSI_DC390T is not set
# CONFIG_SCSI_T128 is not set
# CONFIG_SCSI_U14_34F is not set
# CONFIG_SCSI_ULTRASTOR is not set
# CONFIG_SCSI_DEBUG is not set

#
# Network device support
#
CONFIG_NETDEVICES=y
# CONFIG_ARCNET is not set
CONFIG_DUMMY=y
# CONFIG_EQUALIZER is not set
CONFIG_NET_ETHERNET=y
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_LANCE is not set
CONFIG_NET_VENDOR_SMC=y
CONFIG_WD80x3=y
# CONFIG_ULTRA is not set
# CONFIG_ULTRA32 is not set
# CONFIG_SMC9194 is not set
# CONFIG_NET_VENDOR_RACAL is not set
# CONFIG_NET_ISA is not set
# CONFIG_NET_EISA is not set
# CONFIG_NET_POCKET is not set
# CONFIG_FDDI is not set
# CONFIG_DLCI is not set
# CONFIG_PPP is not set
# CONFIG_SLIP is not set
# CONFIG_NET_RADIO is not set
# CONFIG_TR is not set
# CONFIG_SHAPER is not set

#
# Amateur Radio support
#
# CONFIG_HAMRADIO is not set

#
# ISDN subsystem
#
# CONFIG_ISDN is not set

#
# CD-ROM drivers (not for SCSI or IDE/ATAPI drives)
#
# CONFIG_CD_NO_IDESCSI is not set
CONFIG_CDROM=y

#
# Filesystems
#
# CONFIG_QUOTA is not set
# CONFIG_MINIX_FS is not set
CONFIG_EXT2_FS=y
CONFIG_ISO9660_FS=y
# CONFIG_JOLIET is not set
# CONFIG_FAT_FS is not set
# CONFIG_MSDOS_FS is not set
# CONFIG_UMSDOS_FS is not set
# CONFIG_VFAT_FS is not set
CONFIG_PROC_FS=y
# CONFIG_NFS_FS is not set
# CONFIG_NFSD is not set
# CONFIG_SUNRPC is not set
# CONFIG_LOCKD is not set
# CONFIG_CODA_FS is not set
# CONFIG_SMB_FS is not set
# CONFIG_HPFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
# CONFIG_ROMFS_FS is not set
CONFIG_AUTOFS_FS=y
# CONFIG_UFS_FS is not set
# CONFIG_ADFS_FS is not set
# CONFIG_MAC_PARTITION is not set
# CONFIG_NLS is not set

#
# Character devices
#
CONFIG_VT=y
CONFIG_VT_CONSOLE=y
CONFIG_SERIAL=y
# CONFIG_SERIAL_CONSOLE is not set
# CONFIG_SERIAL_EXTENDED is not set
# CONFIG_SERIAL_NONSTANDARD is not set
CONFIG_MOUSE=y
# CONFIG_ATIXL_BUSMOUSE is not set
# CONFIG_BUSMOUSE is not set
# CONFIG_MS_BUSMOUSE is not set
CONFIG_PSMOUSE=y
# CONFIG_82C710_MOUSE is not set
# CONFIG_PC110_PAD is not set
# CONFIG_UMISC is not set
# CONFIG_QIC02_TAPE is not set
# CONFIG_APM is not set
# CONFIG_WATCHDOG is not set
# CONFIG_RTC is not set
# CONFIG_VIDEO_DEV is not set
# CONFIG_NVRAM is not set
# CONFIG_JOYSTICK is not set
# CONFIG_MISC_RADIO is not set

#
# Ftape, the floppy tape device driver
#
# CONFIG_FTAPE is not set

#
# Sound
#
CONFIG_SOUND=y
# CONFIG_PAS is not set
# CONFIG_SB is not set
# CONFIG_ADLIB is not set
# CONFIG_GUS is not set
# CONFIG_MPU401 is not set
# CONFIG_PSS is not set
# CONFIG_MSS is not set
# CONFIG_SSCAPE is not set
# CONFIG_TRIX is not set
# CONFIG_MAD16 is not set
CONFIG_CS4232=y
CONFIG_CS4232_BASE=534
CONFIG_CS4232_IRQ=5
CONFIG_CS4232_DMA=0
CONFIG_CS4232_DMA2=1
CONFIG_CS4232_MPU_BASE=330
CONFIG_CS4232_MPU_IRQ=9
# CONFIG_MAUI is not set
# CONFIG_OPL3SA1 is not set
# CONFIG_SOFTOSS is not set
# CONFIG_YM3812 is not set
# CONFIG_VMIDI is not set
# CONFIG_UART6850 is not set
# CONFIG_LOWLEVEL_SOUND is not set

#
# Kernel hacking
#
# CONFIG_PROFILE is not set
# CONFIG_MAGIC_SYSRQ is not set
CONFIG_VGA_CONSOLE=y

=======================================================

#define DO_PCISTUFF
#include <linux/config.h>

#ifdef MODULE
#include <linux/module.h>
#include <linux/version.h>
#include <linux/modversions.h>
#else
#define MOD_INC_USE_COUNT
#define MOD_DEC_USE_COUNT
#endif

#include <linux/bios32.h>
#include <linux/pci.h>
#include <linux/malloc.h>

#include <asm/segment.h>
#include <asm/uaccess.h>
#include <asm/io.h>

#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/mm.h>
/*
#define DEBUG
*/
#include "xpg.h"

/* PTW 24/02/97 so we can get the valid PCI base address for the first fpg
and do some safety checks on I/O
the driver would need a re-write to support multiple cards
i.e. do the scan for cards properly in init, and set up a table
of cards/valid I/O locations
*/
#define XPG_MAJOR 60

#define BUF_SIZE 32

#ifndef MODULE
int init_module(long mem_start, long mem_end);
#else
int init_module(void);

#endif
void cleanup_module(void);
static int xpg_ioctl(struct inode *, struct file *, unsigned int,
unsigned long);
static int xpg_open(struct inode *, struct file *);
static void xpg_release(struct inode *, struct file *);
static long xpg_read(struct inode *inode,struct file * file,char * buf,long count);
static long xpg_write(struct inode *inode, struct file *filp,
const char *buf, long count);

#define MAXISA 0x3f /* this + iobase is max writable ISA */
#define MAXPCI 0x3f /* this + iobase is max writable PCI 0 */
#define MAXPCI1 0x03 /* this + iobase1 is max writable PCI 1 */

static int xpg_iobase = 0x300; /* the usual default - can be changed
by a module load, or an IOCTL */
static int xpg_comms_offset = 4;

static int xpg_iobase1 = 0x0; /* secondary PCI port */
static int pci = 0;

/* This structure is described in the KHG */
static struct file_operations xpg_fops = {
NULL, /* seek */
xpg_read, /* read */
xpg_write, /* write */
NULL, /* readdir */
NULL, /* select */
xpg_ioctl, /* ioctl */
NULL, /* mmap */
xpg_open, /* open */
xpg_release, /* release */
NULL /*fsync */
};

#ifdef DEBUG
static char *mess[MAX_IOCTL+1] = IOCTL_LIST ;
#endif

#ifndef MODULE
int init_module(long mem_start, long mem_end)
{
if (register_chrdev(XPG_MAJOR, "xpg", &xpg_fops))
printk("xpg: unable to get major %d\n", XPG_MAJOR);
return mem_start;
}
#else
int init_module(void)
{
if (register_chrdev(XPG_MAJOR, "xpg", &xpg_fops)) {
printk("xpg: unable to get major %d\n", XPG_MAJOR);
return -EIO;
}
printk("xpg: Driver initialized on major %d\n",XPG_MAJOR);
return 0;
}

void cleanup_module(void)
{
unregister_chrdev(XPG_MAJOR, "xpg");
printk("xpg: Driver cleanup.\n");
}
#endif
/* check that the ioaddress we are using is within bounds for the board */
static int chk_io(unsigned port)
{
if(!port)
{
printk("xpg: Attempted I/O to uninitialized board.\n");
return 0;
}
if(!pci) /* check ISA address range only */
{
if( (port >= xpg_iobase) && (port <= (xpg_iobase + MAXISA)) ) return 1;
printk("xpg: Attempted I/O to illegal port %x.\n",port);
return 0;
}
else
{
if( (port >= xpg_iobase) && (port <= (xpg_iobase +MAXPCI)) ) return 1;
if( (port >= xpg_iobase1) && (port <= (xpg_iobase1 + MAXPCI1)) ) return 1;
printk("xpg: Attempted I/O to illegal port %x.\n",port);
return 0;
}
return 0;
}

/*
Load the device with insmod xpgdrv.o base=XXX to now load it

The iobase can also be changed by the ioctl - SET_IO_BASE
*/
static int xpg_open(struct inode *inode, struct file *file)
{
printk("xpg: Device opened \n");
MOD_INC_USE_COUNT;
return 0;
}

static void xpg_release(struct inode *inode, struct file *file)
{
MOD_DEC_USE_COUNT;
}

static int xpg_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
unsigned long arg)
{
int ret;
unsigned int args[BUF_SIZE/(sizeof(unsigned int))];
unsigned char pcibus;

/* if ((args = (unsigned int *)vmalloc(BUF_SIZE)) == NULL)
return -ENOMEM; */
#ifdef DEBUG
if(cmd <= MAX_IOCTL && cmd >= 0) {
printk("xpg:%22s buffer %lx ", mess[cmd], arg);
}
else {
printk("xpg: ioctl - cmd %d arg %lx\n",cmd, arg);
}
#endif
ret = -1;
switch(cmd) {

#ifdef DO_PCISTUFF
case PCI_BIOS_PRESENT:
#ifdef DEBUG
printk("xpg: PCI present test.\n");
#endif
ret = (!pcibios_present());
break;

case PCI_FIND_DEVICE:

ret = verify_area(VERIFY_READ, (unsigned int *)arg,BUF_SIZE);
if(!ret) {
copy_from_user(args, (unsigned int *)arg, BUF_SIZE);
ret = pcibios_find_device((unsigned short)args[1],
(unsigned short)args[0],
(unsigned short)args[2],
(unsigned char *)&args[3],
(unsigned char *)&args[4]);
if (ret) {
#ifdef DEBUG
printk("xpg: find device %d, pci case %d\n", ret, cmd);
#endif
ret = -ENODEV;
} else {
ret = verify_area(VERIFY_WRITE, (unsigned int *)arg,BUF_SIZE);
if(!ret) {
copy_to_user((unsigned int *)arg, args, BUF_SIZE);
pcibus = args[3];
/* get base addresses for XPG-IO at this point */
pcibios_read_config_dword(pcibus,
0x48,
0x10, /*PCI_CS_BASE_ADDRESS_0 */
(unsigned int *)&args[3]);
args[3] &= 0xfffffffcL;
xpg_iobase = args[3];
xpg_comms_offset = 0x20;
pcibios_read_config_dword(pcibus,
0x48,
0x14,/* PCI_CS_BASE_ADDRESS_1 */
(unsigned int *)&args[3]);
args[3] &= 0xfffffffcL;
xpg_iobase1 = args[3];
pci = 1;
}
}
}

break;

case PCI_READ_CONFIG_BYTE:
ret = verify_area(VERIFY_READ,(unsigned int *)arg,BUF_SIZE);
if(!ret) {
copy_from_user(args, (unsigned int *)arg, BUF_SIZE);
ret = pcibios_read_config_byte((unsigned char)args[0],
(unsigned char)args[1],
(unsigned char)args[2],
(unsigned char *)&args[3]);
#ifdef DEBUG
printk(" bus %d d&f %x reg %x ",args[0],args[1],args[2]);
#endif
if (ret) {
#ifdef DEBUG
printk("xpg: device error %d, pci case %d\n", ret, cmd);
#endif
ret = -EIO;
} else {
#ifdef DEBUG
printk(" value %x ",*(unsigned char *)&args[3]);
#endif
ret = verify_area(VERIFY_WRITE,(unsigned int *)arg,BUF_SIZE);
if(!ret) {
copy_to_user((unsigned int *)arg, args, BUF_SIZE);
}
}
}
break;

case PCI_READ_CONFIG_WORD:
ret = verify_area(VERIFY_READ,(unsigned int *)arg,BUF_SIZE);
if(!ret) {
copy_from_user(args, (unsigned int *)arg, BUF_SIZE);
ret = pcibios_read_config_word((unsigned char)args[0],
(unsigned char)args[1],
(unsigned char)args[2],
(unsigned short *)&args[3]);
#ifdef DEBUG
printk(" bus %d d&f %x reg %x ",args[0],args[1],args[2]);
#endif
if (ret) {
printk("xpg: pcibios error %d, pci case %d\n", ret, cmd);
ret = -EIO;
} else {
#ifdef DEBUG
printk(" value %x ",*(unsigned int *)&args[3]);
#endif
ret = verify_area(VERIFY_WRITE,(unsigned int *)arg,BUF_SIZE);
if(!ret) {
copy_to_user((unsigned int *)arg, args, BUF_SIZE);
}
}
}
break;

case PCI_READ_CONFIG_DWORD:
ret = verify_area(VERIFY_READ,(unsigned int *)arg,BUF_SIZE);
if(!ret) {
copy_from_user(args, (unsigned int *)arg, BUF_SIZE);
ret = pcibios_read_config_dword((unsigned char)args[0],
(unsigned char)args[1],
(unsigned char)args[2],
(unsigned int *)&args[3]);
#ifdef DEBUG
printk(" bus %d d&f %x reg %x ",args[0],args[1],args[2]);
#endif
if (ret) {
printk("xpg: pcibios error %d, pci case %d\n", ret, cmd);
ret = -EIO;
} else {
#ifdef DEBUG
printk(" value %lx ",*(unsigned long *)&args[3]);
#endif
ret = verify_area(VERIFY_WRITE,(unsigned int *)arg,BUF_SIZE);
if(!ret) {
copy_to_user((unsigned int *)arg, args, BUF_SIZE);
}
}
}
break;
#ifdef ALLOWPCICONFIGWRITE
/* These were done for completeness, but are unsafe and unneeded here
PTW 1997
*/
case PCI_WRITE_CONFIG_BYTE:
ret = verify_area(VERIFY_READ,(unsigned int *)arg,BUF_SIZE);
if(!ret) {
copy_from_user(args, (unsigned int *)arg, BUF_SIZE);
ret = pcibios_write_config_byte((unsigned char)args[0],
(unsigned char)args[1],
(unsigned char)args[2],
*((unsigned char *)&args[3]));
printk(" bus %d d&f %x reg %x val %x",args[0],args[1],
args[2],*((unsigned char *)&args[3]));
if (ret) {
printk("xpg: device error %d, pci case %d\n", ret, cmd);
ret = -EIO;
}
}
break;

case PCI_WRITE_CONFIG_WORD:
ret = verify_area(VERIFY_READ,(unsigned int *)arg,BUF_SIZE);
if(!ret) {
copy_from_user(args, (unsigned int *)arg, BUF_SIZE);
ret = pcibios_write_config_word((unsigned char)args[0],
(unsigned char)args[1],
(unsigned char)args[2],
*((unsigned short *)&args[3]));
printk(" bus %d d&f %x reg %x val %x",args[0],args[1],
args[2],args[3]);
if (ret) {
printk("xpg: pcibios error %d, pci case %d\n", ret, cmd);
ret = -EIO;
}
}
break;

case PCI_WRITE_CONFIG_DWORD:
ret = verify_area(VERIFY_READ,(unsigned int *)arg,BUF_SIZE);
if(!ret) {
copy_from_user(args, (unsigned int *)arg, BUF_SIZE);
ret = pcibios_write_config_dword((unsigned char)args[0],
(unsigned char)args[1],
(unsigned char)args[2],
*((unsigned int *)&args[3]));

printk(" bus %d d&f %x reg %x val %x",args[0],args[1],
args[2],*((unsigned int *)&args[3]));
if (ret) {
printk("xpg: pcibios error %d, pci case %d\n", ret, cmd);
ret = -EIO;
}
}
break;
#endif
#endif

case INPORT_BYTE:
ret = verify_area(VERIFY_READ, (unsigned int *)arg,8);
if(!ret) {
copy_from_user(args, (unsigned int *)arg, 8);
#ifdef DEBUG
printk(" adr %8x",args[0]);
#endif
args[1] = (unsigned int) inb(args[0]);
#ifdef DEBUG
printk(" val %8x ",*(unsigned char *)&args[1]);
#endif
ret = verify_area(VERIFY_WRITE, (unsigned int *)arg,8);
if(!ret) {
copy_to_user((unsigned int *)arg, args, 8);
}
}
break;

case INPORT_WORD:
ret = verify_area(VERIFY_READ, (unsigned int *)arg,8);
if(!ret) {
copy_from_user(args, (unsigned int *)arg, 8);
#ifdef DEBUG
printk(" adr %8x",args[0]);
#endif
args[1] = (unsigned int) inw(args[0]);
#ifdef DEBUG
printk(" val %8x ",args[1]);
#endif
ret = verify_area(VERIFY_WRITE, (unsigned int *)arg,8);
if(!ret) {
copy_to_user((unsigned int *)arg, args, 8);
}
}
break;

case INPORT_LONGWORD:
ret = verify_area(VERIFY_READ, (unsigned int *)arg,8);
if(!ret) {
copy_from_user(args, (unsigned int *)arg, 8);
#ifdef DEBUG
printk(" adr %8x",args[0]);
#endif
*((unsigned long *)&args[1]) = (unsigned long) inl(args[0]);
#ifdef DEBUG
printk("val %8lx",*((unsigned long *)&args[1]));
#endif
ret = verify_area(VERIFY_WRITE, (unsigned int *)arg,8);
if(!ret) {
copy_to_user((unsigned int *)arg, args, 8);
}
}
break;

case INPORT_LONGWORD_STREAM:
ret = verify_area(VERIFY_READ, (unsigned int *)arg,8);
if(!ret) {
copy_from_user(args, (unsigned int *)arg, 8);
#ifdef DEBUG
printk(" adr %8x",args[0]);
#endif
*((unsigned long *)&args[1]) = (unsigned long) inl(args[0]);
#ifdef DEBUG
printk("val %8lx",*((unsigned long *)&args[1]));
#endif
ret = verify_area(VERIFY_WRITE, (unsigned int *)arg,8);
if(!ret) {
copy_to_user((unsigned int *)arg, args, 8);
}
}
break;

case OUTPORT_BYTE:
ret = verify_area(VERIFY_READ, (unsigned int *)arg,8);
if(!ret) {
copy_from_user(args, (unsigned int *)arg, 8);
#ifdef DEBUG
printk(" adr %8x val %8x",args[0],args[1]);
#endif
if(chk_io(args[0]))
outb((unsigned char)args[1], args[0]);
else ret = -EIO;
}
break;

case OUTPORT_WORD:
ret = verify_area(VERIFY_READ, (unsigned int *)arg,8);
if(!ret) {
copy_from_user(args, (unsigned int *)arg, 8);
#ifdef DEBUG
printk(" adr %8x val %x",args[0],args[1]);
#endif
if(chk_io(args[0]))
outw((unsigned short)args[1], args[0]);
else ret = -EIO;
}
break;

case OUTPORT_LONGWORD: /* this one is broken */
ret = verify_area(VERIFY_READ, (unsigned int *)arg,8);
if(!ret) {
copy_from_user(args, (unsigned int *)arg, 8);
#ifdef DEBUG
printk(" adr %8x val %8lx",args[0],*((unsigned long *)&args[1]));
#endif
if(chk_io(args[0]))
outl(*((unsigned long *)&args[1]), args[0]);
else ret = -EIO;
}
break;

case OUTPORT_LONGWORD_STREAM: /* this one is broken */
ret = verify_area(VERIFY_READ, (unsigned int *)arg,8);
if(!ret) {
copy_from_user(args, (unsigned int *)arg, 8);
#ifdef DEBUG
printk(" adr %8x val %8lx",args[0],*((unsigned long *)&args[1]));
#endif
if(chk_io(args[0]))
outl(*((unsigned long *)&args[1]), args[0]);
else ret = -EIO;
}
break;
/* Disabled, PTW 1997. Should be unnesseccary
case SET_IO_BASE:
ret = verify_area(VERIFY_READ, (unsigned int *)arg,8);
if(!ret) {
copy_from_user(args, (unsigned int *)arg, 8);
printk("IN Set IO BAse - %8x %8x \n",args[0], args[1]);
#ifdef DEBUG
printk(" adr %8x",args[0]);
#endif
xpg_iobase = args[0];
}
*/
break;

default:
printk("xpg: Unknown ioctl request.\n");
ret = -EINVAL;
break;
}

/* vfree(args); */

#ifdef DEBUG
if(ret) {
printk(" error %08x\n",ret);
} else {
printk("\n");
}
#endif

return ret;
}

static long xpg_read(struct inode *inode,struct file * file,char * buf,long count)
{
unsigned long *Ubuf = (unsigned long *)buf;
unsigned long i = file->f_pos; /* Not used at present */
int ulCount = count>>2; /* use only 4 byte transfers */
#ifdef DEBUG
printk("\nXPG read: try read %d bytes address %x\n",count,xpg_iobase+xpg_comms_offset);
#endif
if( (count & 0x3) != 0 ) {
printk("\n XPG read: count %ld incorrect - not multiple of 4\n",count);
return(-1);
}
if( verify_area(VERIFY_WRITE, buf, count) == -EFAULT) {
return(-EFAULT);
}
insl(xpg_iobase+xpg_comms_offset,Ubuf,ulCount);
/*
while( ulCount-- > 0 ) {
put_user((unsigned long) inl(xpg_iobase+xpg_comms_offset), Ubuf);
Ubuf++;
}
*/
return count;

}

static long xpg_write(struct inode *inode, struct file *filp,
const char *buf, long count)
{
unsigned long *Ubuf = (unsigned long *)buf;
int ulCount = count >> 2;
long val;
#ifdef DEBUG
printk("\nXPG write: try write %ld bytes\n",count);
#endif
if( (count & 0x3) != 0 ) {
printk("\n XPG read: count %ld incorrect - not multiple of 4\n",count);
return(-1);
}
if( verify_area(VERIFY_READ, buf, count) == -EFAULT) {
return(-EFAULT);
}
outsl(xpg_iobase+xpg_comms_offset,Ubuf,ulCount);
/*
while( ulCount -- > 0 ) {
outl((unsigned long ) get_user(val,Ubuf), xpg_iobase+xpg_comms_offset);
Ubuf++;

}
*/
return count;
}

If you have to ask what jazz is, you'll never know.
-- Louis Armstrong
====-=-==== Jack (John) Cummings == cummings@nyquist.ee.ualberta.ca ====-=-====
========== for pgp public key --- finger the above address, and pray ==========

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu