Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging-2.6: (714 commits)
  Staging: sxg: slicoss: Specify the license for Sahara SXG and Slicoss drivers
  Staging: serqt_usb: fix build due to proc tty changes
  Staging: serqt_usb: fix checkpatch errors
  Staging: serqt_usb: add TODO file
  Staging: serqt_usb: Lindent the code
  Staging: add USB serial Quatech driver
  staging: document that the wifi staging drivers a bit better
  Staging: echo cleanup
  Staging: BUG to BUG_ON changes
  Staging: remove some pointless conditionals before kfree_skb()
  Staging: line6: fix build error, select SND_RAWMIDI
  Staging: line6: fix checkpatch errors in variax.c
  Staging: line6: fix checkpatch errors in toneport.c
  Staging: line6: fix checkpatch errors in pcm.c
  Staging: line6: fix checkpatch errors in midibuf.c
  Staging: line6: fix checkpatch errors in midi.c
  Staging: line6: fix checkpatch errors in dumprequest.c
  Staging: line6: fix checkpatch errors in driver.c
  Staging: line6: fix checkpatch errors in audio.c
  Staging: line6: fix checkpatch errors in pod.c
  ...
This commit is contained in:
Linus Torvalds 2009-04-05 11:06:45 -07:00
commit 3516c6a8dc
713 changed files with 311988 additions and 64077 deletions

View file

@ -0,0 +1,70 @@
POHMELFS: Parallel Optimized Host Message Exchange Layered File System.
Evgeniy Polyakov <zbr@ioremap.net>
Homepage: http://www.ioremap.net/projects/pohmelfs
POHMELFS first began as a network filesystem with coherent local data and
metadata caches but is now evolving into a parallel distributed filesystem.
Main features of this FS include:
* Locally coherent cache for data and metadata with (potentially) byte-range locks.
Since all Linux filesystems lock the whole inode during writing, algorithm
is very simple and does not use byte-ranges, although they are sent in
locking messages.
* Completely async processing of all events except creation of hard and symbolic
links, and rename events.
Object creation and data reading and writing are processed asynchronously.
* Flexible object architecture optimized for network processing.
Ability to create long paths to objects and remove arbitrarily huge
directories with a single network command.
(like removing the whole kernel tree via a single network command).
* Very high performance.
* Fast and scalable multithreaded userspace server. Being in userspace it works
with any underlying filesystem and still is much faster than async in-kernel NFS one.
* Client is able to switch between different servers (if one goes down, client
automatically reconnects to second and so on).
* Transactions support. Full failover for all operations.
Resending transactions to different servers on timeout or error.
* Read request (data read, directory listing, lookup requests) balancing between multiple servers.
* Write requests are replicated to multiple servers and completed only when all of them are acked.
* Ability to add and/or remove servers from the working set at run-time.
* Strong authentification and possible data encryption in network channel.
* Extended attributes support.
POHMELFS is based on transactions, which are potentially long-standing objects that live
in the client's memory. Each transaction contains all the information needed to process a given
command (or set of commands, which is frequently used during data writing: single transactions
can contain creation and data writing commands). Transactions are committed by all the servers
to which they are sent and, in case of failures, are eventually resent or dropped with an error.
For example, reading will return an error if no servers are available.
POHMELFS uses a asynchronous approach to data processing. Courtesy of transactions, it is
possible to detach replies from requests and, if the command requires data to be received, the
caller sleeps waiting for it. Thus, it is possible to issue multiple read commands to different
servers and async threads will pick up replies in parallel, find appropriate transactions in the
system and put the data where it belongs (like the page or inode cache).
The main feature of POHMELFS is writeback data and the metadata cache.
Only a few non-performance critical operations use the write-through cache and
are synchronous: hard and symbolic link creation, and object rename. Creation,
removal of objects and data writing are asynchronous and are sent to
the server during system writeback. Only one writer at a time is allowed for any
given inode, which is guarded by an appropriate locking protocol.
Because of this feature, POHMELFS is extremely fast at metadata intensive
workloads and can fully utilize the bandwidth to the servers when doing bulk
data transfers.
POHMELFS clients operate with a working set of servers and are capable of balancing read-only
operations (like lookups or directory listings) between them.
Administrators can add or remove servers from the set at run-time via special commands (described
in Documentation/pohmelfs/info.txt file). Writes are replicated to all servers.
POHMELFS is capable of full data channel encryption and/or strong crypto hashing.
One can select any kernel supported cipher, encryption mode, hash type and operation mode
(hmac or digest). It is also possible to use both or neither (default). Crypto configuration
is checked during mount time and, if the server does not support it, appropriate capabilities
will be disabled or mount will fail (if 'crypto_fail_unsupported' mount option is specified).
Crypto performance heavily depends on the number of crypto threads, which asynchronously perform
crypto operations and send the resulting data to server or submit it up the stack. This number
can be controlled via a mount option.

View file

@ -0,0 +1,86 @@
POHMELFS usage information.
Mount options:
idx=%u
Each mountpoint is associated with a special index via this option.
Administrator can add or remove servers from the given index, so all mounts,
which were attached to it, are updated.
Default it is 0.
trans_scan_timeout=%u
This timeout, expressed in milliseconds, specifies time to scan transaction
trees looking for stale requests, which have to be resent, or if number of
retries exceed specified limit, dropped with error.
Default is 5 seconds.
drop_scan_timeout=%u
Internal timeout, expressed in milliseconds, which specifies how frequently
inodes marked to be dropped are freed. It also specifies how frequently
the system checks that servers have to be added or removed from current working set.
Default is 1 second.
wait_on_page_timeout=%u
Number of milliseconds to wait for reply from remote server for data reading command.
If this timeout is exceeded, reading returns an error.
Default is 5 seconds.
trans_retries=%u
This is the number of times that a transaction will be resent to a server that did
not answer for the last @trans_scan_timeout milliseconds.
When the number of resends exceeds this limit, the transaction is completed with error.
Default is 5 resends.
crypto_thread_num=%u
Number of crypto processing threads. Threads are used both for RX and TX traffic.
Default is 2, or no threads if crypto operations are not supported.
trans_max_pages=%u
Maximum number of pages in a single transaction. This parameter also controls
the number of pages, allocated for crypto processing (each crypto thread has
pool of pages, the number of which is equal to 'trans_max_pages'.
Default is 100 pages.
crypto_fail_unsupported
If specified, mount will fail if the server does not support requested crypto operations.
By default mount will disable non-matching crypto operations.
mcache_timeout=%u
Maximum number of milliseconds to wait for the mcache objects to be processed.
Mcache includes locks (given lock should be granted by server), attributes (they should be
fully received in the given timeframe).
Default is 5 seconds.
Usage examples.
Add (or remove if it already exists) server server1.net:1025 into the working set with index $idx
with appropriate hash algorithm and key file and cipher algorithm, mode and key file:
$cfg -a server1.net -p 1025 -i $idx -K $hash_key -k $cipher_key
Mount filesystem with given index $idx to /mnt mountpoint.
Client will connect to all servers specified in the working set via previous command:
mount -t pohmel -o idx=$idx q /mnt
One can add or remove servers from working set after mounting too.
Server installation.
Creating a server, which listens at port 1025 and 0.0.0.0 address.
Working root directory (note, that server chroots there, so you have to have appropriate permissions)
is set to /mnt, server will negotiate hash/cipher with client, in case client requested it, there
are appropriate key files.
Number of working threads is set to 10.
# ./fserver -a 0.0.0.0 -p 1025 -r /mnt -w 10 -K hash_key -k cipher_key
-A 6 - listen on ipv6 address. Default: Disabled.
-r root - path to root directory. Default: /tmp.
-a addr - listen address. Default: 0.0.0.0.
-p port - listen port. Default: 1025.
-w workers - number of workers per connected client. Default: 1.
-K file - hash key size. Default: none.
-k file - cipher key size. Default: none.
-h - this help.
Number of worker threads specifies how many workers will be created for each client.
Bulk single-client transafers usually are better handled with smaller number (like 1-3).

View file

@ -0,0 +1,227 @@
POHMELFS network protocol.
Basic structure used in network communication is following command:
struct netfs_cmd
{
__u16 cmd; /* Command number */
__u16 csize; /* Attached crypto information size */
__u16 cpad; /* Attached padding size */
__u16 ext; /* External flags */
__u32 size; /* Size of the attached data */
__u32 trans; /* Transaction id */
__u64 id; /* Object ID to operate on. Used for feedback.*/
__u64 start; /* Start of the object. */
__u64 iv; /* IV sequence */
__u8 data[0];
};
Commands can be embedded into transaction command (which in turn has own command),
so one can extend protocol as needed without breaking backward compatibility as long
as old commands are supported. All string lengths include tail 0 byte.
All commans are transfered over the network in big-endian. CPU endianess is used at the end peers.
@cmd - command number, which specifies command to be processed. Following
commands are used currently:
NETFS_READDIR = 1, /* Read directory for given inode number */
NETFS_READ_PAGE, /* Read data page from the server */
NETFS_WRITE_PAGE, /* Write data page to the server */
NETFS_CREATE, /* Create directory entry */
NETFS_REMOVE, /* Remove directory entry */
NETFS_LOOKUP, /* Lookup single object */
NETFS_LINK, /* Create a link */
NETFS_TRANS, /* Transaction */
NETFS_OPEN, /* Open intent */
NETFS_INODE_INFO, /* Metadata cache coherency synchronization message */
NETFS_PAGE_CACHE, /* Page cache invalidation message */
NETFS_READ_PAGES, /* Read multiple contiguous pages in one go */
NETFS_RENAME, /* Rename object */
NETFS_CAPABILITIES, /* Capabilities of the client, for example supported crypto */
NETFS_LOCK, /* Distributed lock message */
NETFS_XATTR_SET, /* Set extended attribute */
NETFS_XATTR_GET, /* Get extended attribute */
@ext - external flags. Used by different commands to specify some extra arguments
like partial size of the embedded objects or creation flags.
@size - size of the attached data. For NETFS_READ_PAGE and NETFS_READ_PAGES no data is attached,
but size of the requested data is incorporated here. It does not include size of the command
header (struct netfs_cmd) itself.
@id - id of the object this command operates on. Each command can use it for own purpose.
@start - start of the object this command operates on. Each command can use it for own purpose.
@csize, @cpad - size and padding size of the (attached if needed) crypto information.
Command specifications.
@NETFS_READDIR
This command is used to sync content of the remote dir to the client.
@ext - length of the path to object.
@size - the same.
@id - local inode number of the directory to read.
@start - zero.
@NETFS_READ_PAGE
This command is used to read data from remote server.
Data size does not exceed local page cache size.
@id - inode number.
@start - first byte offset.
@size - number of bytes to read plus length of the path to object.
@ext - object path length.
@NETFS_CREATE
Used to create object.
It does not require that all directories on top of the object were
already created, it will create them automatically. Each object has
associated @netfs_path_entry data structure, which contains creation
mode (permissions and type) and length of the name as long as name itself.
@start - 0
@size - size of the all data structures needed to create a path
@id - local inode number
@ext - 0
@NETFS_REMOVE
Used to remove object.
@ext - length of the path to object.
@size - the same.
@id - local inode number.
@start - zero.
@NETFS_LOOKUP
Lookup information about object on server.
@ext - length of the path to object.
@size - the same.
@id - local inode number of the directory to look object in.
@start - local inode number of the object to look at.
@NETFS_LINK
Create hard of symlink.
Command is sent as "object_path|target_path".
@size - size of the above string.
@id - parent local inode number.
@start - 1 for symlink, 0 for hardlink.
@ext - size of the "object_path" above.
@NETFS_TRANS
Transaction header.
@size - incorporates all embedded command sizes including theirs header sizes.
@start - transaction generation number - unique id used to find transaction.
@ext - transaction flags. Unused at the moment.
@id - 0.
@NETFS_OPEN
Open intent for given transaction.
@id - local inode number.
@start - 0.
@size - path length to the object.
@ext - open flags (O_RDWR and so on).
@NETFS_INODE_INFO
Metadata update command.
It is sent to servers when attributes of the object are changed and received
when data or metadata were updated. It operates with the following structure:
struct netfs_inode_info
{
unsigned int mode;
unsigned int nlink;
unsigned int uid;
unsigned int gid;
unsigned int blocksize;
unsigned int padding;
__u64 ino;
__u64 blocks;
__u64 rdev;
__u64 size;
__u64 version;
};
It effectively mirrors stat(2) returned data.
@ext - path length to the object.
@size - the same plus size of the netfs_inode_info structure.
@id - local inode number.
@start - 0.
@NETFS_PAGE_CACHE
Command is only received by clients. It contains information about
page to be marked as not up-to-date.
@id - client's inode number.
@start - last byte of the page to be invalidated. If it is not equal to
current inode size, it will be vmtruncated().
@size - 0
@ext - 0
@NETFS_READ_PAGES
Used to read multiple contiguous pages in one go.
@start - first byte of the contiguous region to read.
@size - contains of two fields: lower 8 bits are used to represent page cache shift
used by client, another 3 bytes are used to get number of pages.
@id - local inode number.
@ext - path length to the object.
@NETFS_RENAME
Used to rename object.
Attached data is formed into following string: "old_path|new_path".
@id - local inode number.
@start - parent inode number.
@size - length of the above string.
@ext - length of the old path part.
@NETFS_CAPABILITIES
Used to exchange crypto capabilities with server.
If crypto capabilities are not supported by server, then client will disable it
or fail (if 'crypto_fail_unsupported' mount options was specified).
@id - superblock index. Used to specify crypto information for group of servers.
@size - size of the attached capabilities structure.
@start - 0.
@size - 0.
@scsize - 0.
@NETFS_LOCK
Used to send lock request/release messages. Although it sends byte range request
and is capable of flushing pages based on that, it is not used, since all Linux
filesystems lock the whole inode.
@id - lock generation number.
@start - start of the locked range.
@size - size of the locked range.
@ext - lock type: read/write. Not used actually. 15'th bit is used to determine,
if it is lock request (1) or release (0).
@NETFS_XATTR_SET
@NETFS_XATTR_GET
Used to set/get extended attributes for given inode.
@id - attribute generation number or xattr setting type
@start - size of the attribute (request or attached)
@size - name length, path len and data size for given attribute
@ext - path length for given object

View file

@ -73,6 +73,8 @@ source "drivers/staging/rt2860/Kconfig"
source "drivers/staging/rt2870/Kconfig"
source "drivers/staging/rt3070/Kconfig"
source "drivers/staging/comedi/Kconfig"
source "drivers/staging/asus_oled/Kconfig"
@ -93,5 +95,25 @@ source "drivers/staging/epl/Kconfig"
source "drivers/staging/android/Kconfig"
source "drivers/staging/dst/Kconfig"
source "drivers/staging/pohmelfs/Kconfig"
source "drivers/staging/stlc45xx/Kconfig"
source "drivers/staging/uc2322/Kconfig"
source "drivers/staging/b3dfg/Kconfig"
source "drivers/staging/phison/Kconfig"
source "drivers/staging/p9auth/Kconfig"
source "drivers/staging/heci/Kconfig"
source "drivers/staging/line6/Kconfig"
source "drivers/staging/serqt_usb/Kconfig"
endif # !STAGING_EXCLUDE_BUILD
endif # STAGING

View file

@ -19,6 +19,7 @@ obj-$(CONFIG_AGNX) += agnx/
obj-$(CONFIG_OTUS) += otus/
obj-$(CONFIG_RT2860) += rt2860/
obj-$(CONFIG_RT2870) += rt2870/
obj-$(CONFIG_RT3070) += rt3070/
obj-$(CONFIG_COMEDI) += comedi/
obj-$(CONFIG_ASUS_OLED) += asus_oled/
obj-$(CONFIG_PANEL) += panel/
@ -29,3 +30,13 @@ obj-$(CONFIG_INPUT_MIMIO) += mimio/
obj-$(CONFIG_TRANZPORT) += frontier/
obj-$(CONFIG_EPL) += epl/
obj-$(CONFIG_ANDROID) += android/
obj-$(CONFIG_DST) += dst/
obj-$(CONFIG_POHMELFS) += pohmelfs/
obj-$(CONFIG_STLC45XX) += stlc45xx/
obj-$(CONFIG_USB_SERIAL_ATEN2011) += uc2322/
obj-$(CONFIG_B3DFG) += b3dfg/
obj-$(CONFIG_IDE_PHISON) += phison/
obj-$(CONFIG_PLAN9AUTH) += p9auth/
obj-$(CONFIG_HECI) += heci/
obj-$(CONFIG_LINE6_USB) += line6/
obj-$(CONFIG_USB_SERIAL_QUATECH_ESU100) += serqt_usb/

View file

@ -41,16 +41,16 @@ static const struct ieee80211_rate agnx_rates_80211g[] = {
/* { .bitrate = 20, .hw_value = 2, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, */
/* { .bitrate = 55, .hw_value = 3, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, */
/* { .bitrate = 110, .hw_value = 4, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, */
{ .bitrate = 10, .hw_value = 1, },
{ .bitrate = 20, .hw_value = 2, },
{ .bitrate = 55, .hw_value = 3, },
{ .bitrate = 110, .hw_value = 4,},
{ .bitrate = 10, .hw_value = 1, },
{ .bitrate = 20, .hw_value = 2, },
{ .bitrate = 55, .hw_value = 3, },
{ .bitrate = 110, .hw_value = 4,},
{ .bitrate = 60, .hw_value = 0xB, },
{ .bitrate = 90, .hw_value = 0xF, },
{ .bitrate = 120, .hw_value = 0xA },
{ .bitrate = 180, .hw_value = 0xE, },
// { .bitrate = 240, .hw_value = 0xd, },
/* { .bitrate = 240, .hw_value = 0xd, }, */
{ .bitrate = 360, .hw_value = 0xD, },
{ .bitrate = 480, .hw_value = 0x8, },
{ .bitrate = 540, .hw_value = 0xC, },
@ -110,10 +110,10 @@ struct agnx_priv {
/* Need volatile? */
u32 irq_status;
struct delayed_work periodic_work; /* Periodic tasks like recalibrate*/
struct delayed_work periodic_work; /* Periodic tasks like recalibrate */
struct ieee80211_low_level_stats stats;
// unsigned int phymode;
/* unsigned int phymode; */
int mode;
int channel;
u8 bssid[ETH_ALEN];

View file

@ -23,7 +23,7 @@ static inline void agnx_bug(char *reason)
static inline void agnx_print_desc(struct agnx_desc *desc)
{
u32 reg = be32_to_cpu(desc->frag);
u32 reg = be32_to_cpu(desc->frag);
PRINTK_BITS(DESC, PACKET_LEN);
@ -291,7 +291,7 @@ static inline void agnx_print_sta(struct agnx_priv *priv, unsigned int sta_idx)
PRINTK_LE32(STA, sta->phy_stats_high);
PRINTK_LE32(STA, sta->phy_stats_low);
// for (i = 0; i < 8; i++)
/* for (i = 0; i < 8; i++) */
agnx_print_sta_traffic(sta->traffic + 0);
PRINTK_LE16(STA, sta->traffic_class0_frag_success);
@ -311,10 +311,10 @@ static inline void agnx_print_sta(struct agnx_priv *priv, unsigned int sta_idx)
static inline void dump_ieee80211_hdr(struct ieee80211_hdr *hdr, char *tag)
{
u16 fctl;
int hdrlen;
int hdrlen;
DECLARE_MAC_BUF(mac);
fctl = le16_to_cpu(hdr->frame_control);
fctl = le16_to_cpu(hdr->frame_control);
switch (fctl & IEEE80211_FCTL_FTYPE) {
case IEEE80211_FTYPE_DATA:
printk(PFX "%s DATA ", tag);
@ -324,7 +324,7 @@ static inline void dump_ieee80211_hdr(struct ieee80211_hdr *hdr, char *tag)
break;
case IEEE80211_FTYPE_MGMT:
printk(PFX "%s MGMT ", tag);
switch(fctl & IEEE80211_FCTL_STYPE) {
switch (fctl & IEEE80211_FCTL_STYPE) {
case IEEE80211_STYPE_ASSOC_REQ:
printk("SubType: ASSOC_REQ ");
break;
@ -369,7 +369,7 @@ static inline void dump_ieee80211_hdr(struct ieee80211_hdr *hdr, char *tag)
printk(PFX "%s Packet type: Unknow\n", tag);
}
hdrlen = ieee80211_hdrlen(fctl);
hdrlen = ieee80211_hdrlen(fctl);
if (hdrlen >= 4)
printk("FC=0x%04x DUR=0x%04x",
@ -389,29 +389,28 @@ static inline void dump_txm_registers(struct agnx_priv *priv)
{
void __iomem *ctl = priv->ctl;
int i;
for (i = 0; i <=0x1e8; i += 4) {
for (i = 0; i <= 0x1e8; i += 4)
printk(KERN_DEBUG PFX "TXM: %x---> 0x%.8x\n", i, ioread32(ctl + i));
}
}
static inline void dump_rxm_registers(struct agnx_priv *priv)
{
void __iomem *ctl = priv->ctl;
int i;
for (i = 0; i <=0x108; i += 4)
for (i = 0; i <= 0x108; i += 4)
printk(KERN_DEBUG PFX "RXM: %x---> 0x%.8x\n", i, ioread32(ctl + 0x2000 + i));
}
static inline void dump_bm_registers(struct agnx_priv *priv)
{
void __iomem *ctl = priv->ctl;
int i;
for (i = 0; i <=0x90; i += 4)
for (i = 0; i <= 0x90; i += 4)
printk(KERN_DEBUG PFX "BM: %x---> 0x%.8x\n", i, ioread32(ctl + 0x2c00 + i));
}
static inline void dump_cir_registers(struct agnx_priv *priv)
{
void __iomem *ctl = priv->ctl;
int i;
for (i = 0; i <=0xb8; i += 4)
for (i = 0; i <= 0xb8; i += 4)
printk(KERN_DEBUG PFX "CIR: %x---> 0x%.8x\n", i, ioread32(ctl + 0x3000 + i));
}

View file

@ -39,34 +39,34 @@ static inline void agnx_interrupt_ack(struct agnx_priv *priv, u32 *reason)
void __iomem *ctl = priv->ctl;
u32 reg;
if ( *reason & AGNX_STAT_RX ) {
if (*reason & AGNX_STAT_RX) {
/* Mark complete RX */
reg = ioread32(ctl + AGNX_CIR_RXCTL);
reg |= 0x4;
iowrite32(reg, ctl + AGNX_CIR_RXCTL);
/* disable Rx interrupt */
}
if ( *reason & AGNX_STAT_TX ) {
if (*reason & AGNX_STAT_TX) {
reg = ioread32(ctl + AGNX_CIR_TXDCTL);
if (reg & 0x4) {
iowrite32(reg, ctl + AGNX_CIR_TXDCTL);
*reason |= AGNX_STAT_TXD;
}
reg = ioread32(ctl + AGNX_CIR_TXMCTL);
reg = ioread32(ctl + AGNX_CIR_TXMCTL);
if (reg & 0x4) {
iowrite32(reg, ctl + AGNX_CIR_TXMCTL);
*reason |= AGNX_STAT_TXM;
}
}
if ( *reason & AGNX_STAT_X ) {
/* reg = ioread32(ctl + AGNX_INT_STAT); */
/* iowrite32(reg, ctl + AGNX_INT_STAT); */
/* /\* FIXME reinit interrupt mask *\/ */
/* reg = 0xc390bf9 & ~IRQ_TX_BEACON; */
/* reg &= ~IRQ_TX_DISABLE; */
/* iowrite32(reg, ctl + AGNX_INT_MASK); */
/* iowrite32(0x800, ctl + AGNX_CIR_BLKCTL); */
}
/* if (*reason & AGNX_STAT_X) {
reg = ioread32(ctl + AGNX_INT_STAT);
iowrite32(reg, ctl + AGNX_INT_STAT);
/* FIXME reinit interrupt mask *\/
reg = 0xc390bf9 & ~IRQ_TX_BEACON;
reg &= ~IRQ_TX_DISABLE;
iowrite32(reg, ctl + AGNX_INT_MASK);
iowrite32(0x800, ctl + AGNX_CIR_BLKCTL);
} */
} /* agnx_interrupt_ack */
static irqreturn_t agnx_interrupt_handler(int irq, void *dev_id)
@ -79,7 +79,7 @@ static irqreturn_t agnx_interrupt_handler(int irq, void *dev_id)
spin_lock(&priv->lock);
// printk(KERN_ERR PFX "Get a interrupt %s\n", __func__);
/* printk(KERN_ERR PFX "Get a interrupt %s\n", __func__); */
if (priv->init_status != AGNX_START)
goto out;
@ -92,7 +92,7 @@ static irqreturn_t agnx_interrupt_handler(int irq, void *dev_id)
ret = IRQ_HANDLED;
priv->irq_status = ioread32(ctl + AGNX_INT_STAT);
// printk(PFX "Interrupt reason is 0x%x\n", irq_reason);
/* printk(PFX "Interrupt reason is 0x%x\n", irq_reason); */
/* Make sure the txm and txd flags don't conflict with other unknown
interrupt flag, maybe is not necessary */
irq_reason &= 0xF;
@ -101,13 +101,13 @@ static irqreturn_t agnx_interrupt_handler(int irq, void *dev_id)
/* TODO Make sure the card finished initialized */
agnx_interrupt_ack(priv, &irq_reason);
if ( irq_reason & AGNX_STAT_RX )
if (irq_reason & AGNX_STAT_RX)
handle_rx_irq(priv);
if ( irq_reason & AGNX_STAT_TXD )
if (irq_reason & AGNX_STAT_TXD)
handle_txd_irq(priv);
if ( irq_reason & AGNX_STAT_TXM )
if (irq_reason & AGNX_STAT_TXM)
handle_txm_irq(priv);
if ( irq_reason & AGNX_STAT_X )
if (irq_reason & AGNX_STAT_X)
handle_other_irq(priv);
enable_rx_interrupt(priv);
@ -171,7 +171,7 @@ static int agnx_alloc_rings(struct agnx_priv *priv)
len = priv->rx.size + priv->txm.size + priv->txd.size;
// priv->rx.info = kzalloc(sizeof(struct agnx_info) * len, GFP_KERNEL);
/* priv->rx.info = kzalloc(sizeof(struct agnx_info) * len, GFP_KERNEL); */
priv->rx.info = kzalloc(sizeof(struct agnx_info) * len, GFP_ATOMIC);
if (!priv->rx.info)
return -ENOMEM;
@ -210,28 +210,27 @@ static void rings_free(struct agnx_priv *priv)
#if 0
static void agnx_periodic_work_handler(struct work_struct *work)
{
struct agnx_priv *priv = container_of(work, struct agnx_priv,
periodic_work.work);
// unsigned long flags;
struct agnx_priv *priv = container_of(work, struct agnx_priv, periodic_work.work);
/* unsigned long flags; */
unsigned long delay;
/* fixme: using mutex?? */
// spin_lock_irqsave(&priv->lock, flags);
/* spin_lock_irqsave(&priv->lock, flags); */
/* TODO Recalibrate*/
// calibrate_oscillator(priv);
// antenna_calibrate(priv);
// agnx_send_packet(priv, 997);
/* calibrate_oscillator(priv); */
/* antenna_calibrate(priv); */
/* agnx_send_packet(priv, 997); /
/* FIXME */
/* if (debug == 3) */
/* delay = msecs_to_jiffies(AGNX_PERIODIC_DELAY); */
/* else */
delay = msecs_to_jiffies(AGNX_PERIODIC_DELAY);
// delay = round_jiffies(HZ * 15);
/* delay = round_jiffies(HZ * 15); */
queue_delayed_work(priv->hw->workqueue, &priv->periodic_work, delay);
// spin_unlock_irqrestore(&priv->lock, flags);
/* spin_unlock_irqrestore(&priv->lock, flags); */
}
#endif
@ -255,12 +254,12 @@ static int agnx_start(struct ieee80211_hw *dev)
goto out;
}
// mdelay(500);
/* mdelay(500); */
might_sleep();
agnx_hw_init(priv);
// mdelay(500);
/* mdelay(500); */
might_sleep();
priv->init_status = AGNX_START;
@ -280,16 +279,16 @@ static void agnx_stop(struct ieee80211_hw *dev)
/* make sure hardware will not generate irq */
agnx_hw_reset(priv);
free_irq(priv->pdev->irq, dev);
flush_workqueue(priv->hw->workqueue);
// cancel_delayed_work_sync(&priv->periodic_work);
flush_workqueue(priv->hw->workqueue);
/* cancel_delayed_work_sync(&priv->periodic_work); */
unfill_rings(priv);
rings_free(priv);
}
static int agnx_config(struct ieee80211_hw *dev,
struct ieee80211_conf *conf)
static int agnx_config(struct ieee80211_hw *dev, u32 changed)
{
struct agnx_priv *priv = dev->priv;
struct ieee80211_conf *conf = &dev->conf;
int channel = ieee80211_frequency_to_channel(conf->channel->center_freq);
AGNX_TRACE;
@ -315,7 +314,6 @@ static int agnx_config_interface(struct ieee80211_hw *dev,
spin_lock(&priv->lock);
if (memcmp(conf->bssid, priv->bssid, ETH_ALEN)) {
// u32 reghi, reglo;
agnx_set_bssid(priv, conf->bssid);
memcpy(priv->bssid, conf->bssid, ETH_ALEN);
hash_write(priv, conf->bssid, BSSID_STAID);
@ -425,7 +423,7 @@ static struct ieee80211_ops agnx_ops = {
.remove_interface = agnx_remove_interface,
.config = agnx_config,
.config_interface = agnx_config_interface,
.configure_filter = agnx_configure_filter,
.configure_filter = agnx_configure_filter,
.get_stats = agnx_get_stats,
.get_tx_stats = agnx_get_tx_stats,
.get_tsf = agnx_get_tsft
@ -434,11 +432,12 @@ static struct ieee80211_ops agnx_ops = {
static void __devexit agnx_pci_remove(struct pci_dev *pdev)
{
struct ieee80211_hw *dev = pci_get_drvdata(pdev);
struct agnx_priv *priv = dev->priv;
struct agnx_priv *priv;
AGNX_TRACE;
if (!dev)
return;
priv = dev->priv;
ieee80211_unregister_hw(dev);
pci_iounmap(pdev, priv->ctl);
pci_iounmap(pdev, priv->data);
@ -504,7 +503,7 @@ static int __devinit agnx_pci_probe(struct pci_dev *pdev,
/* Map mem #1 and #2 */
priv->ctl = pci_iomap(pdev, 0, mem_len0);
// printk(KERN_DEBUG PFX"MEM1 mapped address is 0x%p\n", priv->ctl);
/* printk(KERN_DEBUG PFX"MEM1 mapped address is 0x%p\n", priv->ctl); */
if (!priv->ctl) {
printk(KERN_ERR PFX "Can't map device memory\n");
goto err_free_dev;

View file

@ -114,7 +114,7 @@ static void mac_address_set(struct agnx_priv *priv)
/* FIXME */
reg = (mac_addr[0] << 24) | (mac_addr[1] << 16) | mac_addr[2] << 8 | mac_addr[3];
iowrite32(reg, ctl + AGNX_RXM_MACHI);
reg = (mac_addr[4] << 8) | mac_addr[5];
reg = (mac_addr[4] << 8) | mac_addr[5];
iowrite32(reg, ctl + AGNX_RXM_MACLO);
}
@ -127,7 +127,7 @@ static void receiver_bssid_set(struct agnx_priv *priv, u8 *bssid)
/* FIXME */
reg = bssid[0] << 24 | (bssid[1] << 16) | (bssid[2] << 8) | bssid[3];
iowrite32(reg, ctl + AGNX_RXM_BSSIDHI);
reg = (bssid[4] << 8) | bssid[5];
reg = (bssid[4] << 8) | bssid[5];
iowrite32(reg, ctl + AGNX_RXM_BSSIDLO);
/* Enable the receiver */
@ -401,9 +401,9 @@ static void rx_management_init(struct agnx_priv *priv)
agnx_write32(ctl, 0x2074, 0x1f171710);
agnx_write32(ctl, 0x2078, 0x10100d0d);
agnx_write32(ctl, 0x207c, 0x11111010);
}
else
} else {
agnx_write32(ctl, AGNX_RXM_DELAY11, 0x0);
}
agnx_write32(ctl, AGNX_RXM_REQRATE, 0x8195e00);
}
@ -476,7 +476,7 @@ static void gain_ctlcnt_init(struct agnx_priv *priv)
/* It seemed if we set other bit to 1 the bit 0 will
be auto change to 0 */
agnx_write32(ctl, AGNX_BM_TXTOPEER, 0x2 | 0x1);
// agnx_write32(ctl, AGNX_BM_TXTOPEER, 0x1);
/* agnx_write32(ctl, AGNX_BM_TXTOPEER, 0x1); */
} /* gain_ctlcnt_init */
@ -490,7 +490,7 @@ static void phy_init(struct agnx_priv *priv)
/* Load InitialGainTable */
gain_table_init(priv);
agnx_write32(ctl, AGNX_CIR_ADDRWIN, 0x2000000);
agnx_write32(ctl, AGNX_CIR_ADDRWIN, 0x2000000);
/* Clear the following offsets in Memory Range #2: */
memset_io(data + 0x5040, 0, 0xa * 4);
@ -586,7 +586,7 @@ static void phy_init(struct agnx_priv *priv)
agnx_write32(ctl, AGNX_GCR_SIFST11B, 0x28);
agnx_write32(ctl, AGNX_GCR_CWDETEC, 0x0);
agnx_write32(ctl, AGNX_GCR_0X38, 0x1e);
// agnx_write32(ctl, AGNX_GCR_BOACT, 0x26);
/* agnx_write32(ctl, AGNX_GCR_BOACT, 0x26);*/
agnx_write32(ctl, AGNX_GCR_DISCOVMOD, 0x3);
agnx_write32(ctl, AGNX_GCR_THCAP11A, 0x32);
@ -810,10 +810,10 @@ static void card_interface_init(struct agnx_priv *priv)
}
print_hex_dump_bytes(PFX "EEPROM: ", DUMP_PREFIX_NONE, eeprom,
ARRAY_SIZE(eeprom));
} while(0);
} while (0);
spi_rc_write(ctl, RF_CHIP0, 0x26);
reg = agnx_read32(ctl, AGNX_SPI_RLSW);
reg = agnx_read32(ctl, AGNX_SPI_RLSW);
/* Initialize the system interface */
system_itf_init(priv);
@ -874,19 +874,19 @@ static void card_interface_init(struct agnx_priv *priv)
/* FIXME Enable the request */
/* Check packet length */
/* Set maximum packet length */
/* agnx_write32(ctl, AGNX_RXM_REQRATE, 0x88195e00); */
/* enable_receiver(priv); */
/* agnx_write32(ctl, AGNX_RXM_REQRATE, 0x88195e00); */
/* enable_receiver(priv); */
/* Set the Receiver BSSID */
receiver_bssid_set(priv, bssid);
/* FIXME Set to managed mode */
set_managed_mode(priv);
// set_promiscuous_mode(priv);
/* set_scan_mode(priv); */
/* set_learn_mode(priv); */
// set_promis_and_managed(priv);
// set_adhoc_mode(priv);
/* set_promiscuous_mode(priv); */
/* set_scan_mode(priv); */
/* set_learn_mode(priv); */
/* set_promis_and_managed(priv); */
/* set_adhoc_mode(priv); */
/* Set the recieve request rate */
/* Check packet length */

View file

@ -109,12 +109,12 @@ void rf_chips_init(struct agnx_priv *priv)
}
/* Set SPI clock speed to 200NS */
reg = agnx_read32(ctl, AGNX_SPI_CFG);
reg &= ~0xF;
reg |= 0x3;
agnx_write32(ctl, AGNX_SPI_CFG, reg);
reg = agnx_read32(ctl, AGNX_SPI_CFG);
reg &= ~0xF;
reg |= 0x3;
agnx_write32(ctl, AGNX_SPI_CFG, reg);
/* Set SPI clock speed to 50NS */
/* Set SPI clock speed to 50NS */
reg = agnx_read32(ctl, AGNX_SPI_CFG);
reg &= ~0xF;
reg |= 0x1;
@ -256,7 +256,7 @@ static void antenna_init(struct agnx_priv *priv, int num_antenna)
agnx_write32(ctl, AGNX_GCR_THD0BTFEST, 70);
agnx_write32(ctl, AGNX_GCR_SIGHTH, 100);
agnx_write32(ctl, AGNX_GCR_SIGLTH, 48);
// agnx_write32(ctl, AGNX_GCR_SIGLTH, 16);
/* agnx_write32(ctl, AGNX_GCR_SIGLTH, 16); */
break;
default:
printk(KERN_WARNING PFX "Unknow antenna number\n");
@ -275,8 +275,8 @@ static void chain_update(struct agnx_priv *priv, u32 chain)
if (reg == 0x4)
spi_rf_write(ctl, RF_CHIP0|RF_CHIP1, reg|0x1000);
else if (reg != 0x0)
spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, reg|0x1000);
else {
spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, reg|0x1000);
else {
if (chain == 3 || chain == 6) {
spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, reg|0x1000);
agnx_write32(ctl, AGNX_GCR_RXOVERIDE, 0x0);
@ -634,8 +634,7 @@ static void chain_calibrate(struct agnx_priv *priv, struct chains *chains,
}
} /* chain_calibrate */
static void inline get_calibrete_value(struct agnx_priv *priv, struct chains *chains,
static inline void get_calibrete_value(struct agnx_priv *priv, struct chains *chains,
unsigned int num)
{
void __iomem *ctl = priv->ctl;
@ -652,7 +651,7 @@ static void inline get_calibrete_value(struct agnx_priv *priv, struct chains *ch
}
if (num == 0 || num == 1 || num == 2) {
if ( 0 == chains[num].cali)
if (0 == chains[num].cali)
chains[num].cali = 0xff;
else
chains[num].cali--;
@ -669,7 +668,7 @@ static inline void calibra_delay(struct agnx_priv *priv)
unsigned int i = 100;
wmb();
while (i--) {
while (--i) {
reg = (ioread32(ctl + AGNX_ACI_STATUS));
if (reg == 0x4000)
break;

View file

@ -18,7 +18,7 @@ void hash_read(struct agnx_priv *priv, u32 reghi, u32 reglo, u8 sta_id)
iowrite32(reglo, ctl + AGNX_RXM_HASH_CMD_LOW);
reghi = ioread32(ctl + AGNX_RXM_HASH_CMD_HIGH);
reglo = ioread32(ctl + AGNX_RXM_HASH_CMD_LOW);
reglo = ioread32(ctl + AGNX_RXM_HASH_CMD_LOW);
printk(PFX "RX hash cmd are : %.8x%.8x\n", reghi, reglo);
}
@ -40,7 +40,7 @@ void hash_write(struct agnx_priv *priv, u8 *mac_addr, u8 sta_id)
iowrite32(reghi, ctl + AGNX_RXM_HASH_CMD_HIGH);
iowrite32(reglo, ctl + AGNX_RXM_HASH_CMD_LOW);
reglo = ioread32(ctl + AGNX_RXM_HASH_CMD_LOW);
reglo = ioread32(ctl + AGNX_RXM_HASH_CMD_LOW);
if (!(reglo & 0x80000000))
printk(KERN_WARNING PFX "Update hash table failed\n");
}
@ -59,7 +59,7 @@ void hash_delete(struct agnx_priv *priv, u32 reghi, u32 reglo, u8 sta_id)
iowrite32(reglo, ctl + AGNX_RXM_HASH_CMD_LOW);
reghi = ioread32(ctl + AGNX_RXM_HASH_CMD_HIGH);
reglo = ioread32(ctl + AGNX_RXM_HASH_CMD_LOW);
reglo = ioread32(ctl + AGNX_RXM_HASH_CMD_LOW);
printk(PFX "RX hash cmd are : %.8x%.8x\n", reghi, reglo);
}
@ -69,15 +69,14 @@ void hash_dump(struct agnx_priv *priv, u8 sta_id)
void __iomem *ctl = priv->ctl;
u32 reghi, reglo;
reglo = 0x0; /* dump command */
reglo|= 0x40000000; /* status bit */
reglo = 0x40000000; /* status bit */
iowrite32(reglo, ctl + AGNX_RXM_HASH_CMD_LOW);
iowrite32(sta_id << 16, ctl + AGNX_RXM_HASH_DUMP_DATA);
udelay(80);
reghi = ioread32(ctl + AGNX_RXM_HASH_CMD_HIGH);
reglo = ioread32(ctl + AGNX_RXM_HASH_CMD_LOW);
reglo = ioread32(ctl + AGNX_RXM_HASH_CMD_LOW);
printk(PFX "hash cmd are : %.8x%.8x\n", reghi, reglo);
reghi = ioread32(ctl + AGNX_RXM_HASH_CMD_FLAG);
printk(PFX "hash flag is : %.8x\n", reghi);
@ -91,7 +90,7 @@ void hash_dump(struct agnx_priv *priv, u8 sta_id)
void get_sta_power(struct agnx_priv *priv, struct agnx_sta_power *power, unsigned int sta_idx)
{
void __iomem *ctl = priv->ctl;
memcpy_fromio(power, ctl + AGNX_TXM_STAPOWTEMP + sizeof(*power) * sta_idx,
memcpy_fromio(power, ctl + AGNX_TXM_STAPOWTEMP + sizeof(*power) * sta_idx,
sizeof(*power));
}
@ -100,7 +99,7 @@ set_sta_power(struct agnx_priv *priv, struct agnx_sta_power *power, unsigned int
{
void __iomem *ctl = priv->ctl;
/* FIXME 2. Write Template to offset + station number */
memcpy_toio(ctl + AGNX_TXM_STAPOWTEMP + sizeof(*power) * sta_idx,
memcpy_toio(ctl + AGNX_TXM_STAPOWTEMP + sizeof(*power) * sta_idx,
power, sizeof(*power));
}
@ -135,7 +134,7 @@ inline void set_sta(struct agnx_priv *priv, struct agnx_sta *sta, unsigned int s
{
void __iomem *data = priv->data;
memcpy_toio(data + AGNX_PDUPOOL + sizeof(*sta) * sta_idx,
memcpy_toio(data + AGNX_PDUPOOL + sizeof(*sta) * sta_idx,
sta, sizeof(*sta));
}
@ -165,7 +164,7 @@ static void sta_tx_workqueue_init(struct agnx_priv *priv, unsigned int sta_idx)
reg = agnx_set_bits(WORK_QUEUE_VALID, WORK_QUEUE_VALID_SHIFT, 1);
reg |= agnx_set_bits(WORK_QUEUE_ACK_TYPE, WORK_QUEUE_ACK_TYPE_SHIFT, 1);
// reg |= agnx_set_bits(WORK_QUEUE_ACK_TYPE, WORK_QUEUE_ACK_TYPE_SHIFT, 0);
/* reg |= agnx_set_bits(WORK_QUEUE_ACK_TYPE, WORK_QUEUE_ACK_TYPE_SHIFT, 0); */
tx_wq.reg2 |= cpu_to_le32(reg);
/* Suppose all 8 traffic class are used */
@ -181,7 +180,7 @@ static void sta_traffic_init(struct agnx_sta_traffic *traffic)
reg = agnx_set_bits(NEW_PACKET, NEW_PACKET_SHIFT, 1);
reg |= agnx_set_bits(TRAFFIC_VALID, TRAFFIC_VALID_SHIFT, 1);
// reg |= agnx_set_bits(TRAFFIC_ACK_TYPE, TRAFFIC_ACK_TYPE_SHIFT, 1);
/* reg |= agnx_set_bits(TRAFFIC_ACK_TYPE, TRAFFIC_ACK_TYPE_SHIFT, 1); */
traffic->reg0 = cpu_to_le32(reg);
/* 3. setting RX Sequence Number to 4095 */

View file

@ -16,7 +16,7 @@ struct agnx_hash_cmd {
#define PASS 0x00000001
#define PASS_SHIFT 1
__be32 cmdlo;
}__attribute__((__packed__));
} __attribute__((__packed__));
/*

View file

@ -80,7 +80,7 @@ void routing_table_init(struct agnx_priv *priv)
disable_receiver(priv);
for ( type = 0; type < 0x3; type++ ) {
for (type = 0; type < 0x3; type++) {
for (subtype = 0; subtype < 0x10; subtype++) {
/* 1. Set Routing table to R/W and to Return status on Read */
reg = (type << ROUTAB_TYPE_SHIFT) |
@ -89,7 +89,7 @@ void routing_table_init(struct agnx_priv *priv)
if (type == ROUTAB_TYPE_DATA) {
/* NULL goes to RFP */
if (subtype == ROUTAB_SUBTYPE_NULL)
// reg |= ROUTAB_ROUTE_RFP;
/* reg |= ROUTAB_ROUTE_RFP; */
reg |= ROUTAB_ROUTE_CPU;
/* QOS NULL goes to CPU */
else if (subtype == ROUTAB_SUBTYPE_QOSNULL)
@ -104,7 +104,7 @@ void routing_table_init(struct agnx_priv *priv)
(subtype == ROUTAB_SUBTYPE_QOSDATAPOLL) ||
(subtype == ROUTAB_SUBTYPE_QOSDATAACKPOLL))
reg |= ROUTAB_ROUTE_ENCRY;
// reg |= ROUTAB_ROUTE_CPU;
/* reg |= ROUTAB_ROUTE_CPU; */
/*Drop NULL and QOS NULL ack, poll and poll ack*/
else if ((subtype == ROUTAB_SUBTYPE_NULLACK) ||
(subtype == ROUTAB_SUBTYPE_QOSNULLACK) ||
@ -112,11 +112,11 @@ void routing_table_init(struct agnx_priv *priv)
(subtype == ROUTAB_SUBTYPE_QOSNULLPOLL) ||
(subtype == ROUTAB_SUBTYPE_NULLPOLLACK) ||
(subtype == ROUTAB_SUBTYPE_QOSNULLPOLLACK))
// reg |= ROUTAB_ROUTE_DROP;
/* reg |= ROUTAB_ROUTE_DROP; */
reg |= ROUTAB_ROUTE_CPU;
}
else
} else {
reg |= (ROUTAB_ROUTE_CPU);
}
iowrite32(reg, ctl + AGNX_RXM_ROUTAB);
/* Check to verify that the status bit cleared */
routing_table_delay();

View file

@ -17,8 +17,8 @@
#include "debug.h"
#include "phy.h"
unsigned int rx_frame_cnt = 0;
//unsigned int local_tx_sent_cnt = 0;
unsigned int rx_frame_cnt;
/* unsigned int local_tx_sent_cnt = 0; */
static inline void disable_rx_engine(struct agnx_priv *priv)
{
@ -242,15 +242,15 @@ static void get_rx_stats(struct agnx_priv *priv, struct agnx_hdr *hdr,
memset(stat, 0, sizeof(*stat));
/* RSSI */
rssi = (u8 *)&hdr->phy_stats_lo;
// stat->ssi = (rssi[0] + rssi[1] + rssi[2]) / 3;
/* stat->ssi = (rssi[0] + rssi[1] + rssi[2]) / 3; */
/* Noise */
noise = ioread32(ctl + AGNX_GCR_NOISE0);
noise += ioread32(ctl + AGNX_GCR_NOISE1);
noise += ioread32(ctl + AGNX_GCR_NOISE2);
stat->noise = noise / 3;
/* Signal quality */
//snr = stat->ssi - stat->noise;
if (snr >=0 && snr < 40)
/* snr = stat->ssi - stat->noise; */
if (snr >= 0 && snr < 40)
stat->signal = 5 * snr / 2;
else if (snr >= 40)
stat->signal = 100;
@ -269,10 +269,9 @@ static void get_rx_stats(struct agnx_priv *priv, struct agnx_hdr *hdr,
stat->band = IEEE80211_BAND_2GHZ;
stat->freq = agnx_channels[priv->channel - 1].center_freq;
// stat->antenna = 3;
// stat->mactime = be32_to_cpu(hdr->time_stamp);
// stat->channel = priv->channel;
/* stat->antenna = 3;
stat->mactime = be32_to_cpu(hdr->time_stamp);
stat->channel = priv->channel; */
}
static inline void combine_hdr_frag(struct ieee80211_hdr *ieeehdr,
@ -296,7 +295,7 @@ static inline void combine_hdr_frag(struct ieee80211_hdr *ieeehdr,
static inline int agnx_packet_check(struct agnx_priv *priv, struct agnx_hdr *agnxhdr,
unsigned packet_len)
{
if (agnx_get_bits(CRC_FAIL, CRC_FAIL_SHIFT, be32_to_cpu(agnxhdr->reg1)) == 1){
if (agnx_get_bits(CRC_FAIL, CRC_FAIL_SHIFT, be32_to_cpu(agnxhdr->reg1)) == 1) {
printk(PFX "RX: CRC check fail\n");
goto drop;
}
@ -320,7 +319,7 @@ void handle_rx_irq(struct agnx_priv *priv)
{
struct ieee80211_rx_status status;
unsigned int len;
// AGNX_TRACE;
/* AGNX_TRACE; */
do {
struct agnx_desc *desc;
@ -341,54 +340,54 @@ void handle_rx_irq(struct agnx_priv *priv)
len = (frag & PACKET_LEN) >> PACKET_LEN_SHIFT;
if (agnx_packet_check(priv, hdr, len) == -1) {
rx_desc_reusing(priv, i);
rx_desc_reusing(priv, i);
continue;
}
skb_put(skb, len);
do {
u16 fctl;
u16 fctl;
fctl = le16_to_cpu(((struct ieee80211_hdr *)hdr->mac_hdr)->frame_control);
if ((fctl & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_BEACON)// && !(fctl & IEEE80211_STYPE_BEACON))
if ((fctl & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_BEACON)/* && !(fctl & IEEE80211_STYPE_BEACON)) */
dump_ieee80211_hdr((struct ieee80211_hdr *)hdr->mac_hdr, "RX");
} while (0);
if (hdr->_11b0 && !hdr->_11g0) {
/* int j; */
/* u16 fctl = le16_to_cpu(((struct ieee80211_hdr *)hdr->mac_hdr) */
/* ->frame_control); */
/* if ( (fctl & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) { */
/* agnx_print_rx_hdr(hdr); */
// agnx_print_sta(priv, BSSID_STAID);
/* for (j = 0; j < 8; j++) */
/* agnx_print_sta_tx_wq(priv, BSSID_STAID, j); */
/* } */
/* int j;
u16 fctl = le16_to_cpu(((struct ieee80211_hdr *)hdr->mac_hdr)
->frame_control);
if ( (fctl & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) {
agnx_print_rx_hdr(hdr);
agnx_print_sta(priv, BSSID_STAID);
for (j = 0; j < 8; j++)
agnx_print_sta_tx_wq(priv, BSSID_STAID, j);
} */
get_rx_stats(priv, hdr, &status);
skb_pull(skb, sizeof(*hdr));
combine_hdr_frag((struct ieee80211_hdr *)hdr->mac_hdr, skb);
} else if (!hdr->_11b0 && hdr->_11g0) {
// int j;
/* int j; */
agnx_print_rx_hdr(hdr);
agnx_print_sta(priv, BSSID_STAID);
// for (j = 0; j < 8; j++)
/* for (j = 0; j < 8; j++) */
agnx_print_sta_tx_wq(priv, BSSID_STAID, 0);
print_hex_dump_bytes("agnx: RX_PACKET: ", DUMP_PREFIX_NONE,
skb->data, skb->len + 8);
// if (agnx_plcp_get_bitrate_ofdm(&hdr->_11g0) == 0)
/* if (agnx_plcp_get_bitrate_ofdm(&hdr->_11g0) == 0) */
get_rx_stats(priv, hdr, &status);
skb_pull(skb, sizeof(*hdr));
combine_hdr_frag((struct ieee80211_hdr *)
((void *)&hdr->mac_hdr), skb);
// dump_ieee80211_hdr((struct ieee80211_hdr *)skb->data, "RX G");
/* dump_ieee80211_hdr((struct ieee80211_hdr *)skb->data, "RX G"); */
} else
agnx_bug("Unknown packets type");
ieee80211_rx_irqsafe(priv->hw, skb, &status);
rx_desc_reinit(priv, i);
} while ( priv->rx.idx++ );
} while (priv->rx.idx++);
} /* handle_rx_irq */
static inline void handle_tx_irq(struct agnx_priv *priv, struct agnx_ring *ring)
@ -415,40 +414,40 @@ static inline void handle_tx_irq(struct agnx_priv *priv, struct agnx_ring *ring)
pci_unmap_single(priv->pdev, info->mapping, info->dma_len, PCI_DMA_TODEVICE);
do {
// int j;
/* int j; */
size_t len;
len = info->skb->len - sizeof(struct agnx_hdr) + info->hdr_len;
// if (len == 614) {
// agnx_print_desc(desc);
/* if (len == 614) { */
/* agnx_print_desc(desc); */
if (info->type == PACKET) {
// agnx_print_tx_hdr((struct agnx_hdr *)info->skb->data);
/* agnx_print_sta_power(priv, LOCAL_STAID); */
/* agnx_print_sta(priv, LOCAL_STAID); */
/* // for (j = 0; j < 8; j++) */
/* agnx_print_sta_tx_wq(priv, LOCAL_STAID, 0); */
// agnx_print_sta_power(priv, BSSID_STAID);
// agnx_print_sta(priv, BSSID_STAID);
// for (j = 0; j < 8; j++)
// agnx_print_sta_tx_wq(priv, BSSID_STAID, 0);
/* agnx_print_tx_hdr((struct agnx_hdr *)info->skb->data); */
/* agnx_print_sta_power(priv, LOCAL_STAID); */
/* agnx_print_sta(priv, LOCAL_STAID); */
/* for (j = 0; j < 8; j++) */
/* agnx_print_sta_tx_wq(priv, LOCAL_STAID, 0); */
/* agnx_print_sta_power(priv, BSSID_STAID); */
/* agnx_print_sta(priv, BSSID_STAID); */
/* for (j = 0; j < 8; j++) */
/* agnx_print_sta_tx_wq(priv, BSSID_STAID, 0); */
}
// }
/* } */
} while (0);
if (info->type == PACKET) {
// dump_txm_registers(priv);
// dump_rxm_registers(priv);
// dump_bm_registers(priv);
// dump_cir_registers(priv);
/* dump_txm_registers(priv);
dump_rxm_registers(priv);
dump_bm_registers(priv);
dump_cir_registers(priv); */
}
if (info->type == PACKET) {
// struct ieee80211_hdr *hdr;
/* struct ieee80211_hdr *hdr; */
struct ieee80211_tx_info *txi = IEEE80211_SKB_CB(info->skb);
skb_pull(info->skb, sizeof(struct agnx_hdr));
memcpy(skb_push(info->skb, info->hdr_len), &info->hdr, info->hdr_len);
// dump_ieee80211_hdr((struct ieee80211_hdr *)info->skb->data, "TX_HANDLE");
/* dump_ieee80211_hdr((struct ieee80211_hdr *)info->skb->data, "TX_HANDLE"); */
/* print_hex_dump_bytes("agnx: TX_HANDLE: ", DUMP_PREFIX_NONE, */
/* info->skb->data, info->skb->len); */
@ -462,7 +461,7 @@ static inline void handle_tx_irq(struct agnx_priv *priv, struct agnx_ring *ring)
/* ieee80211_tx_status_irqsafe(priv->hw, info->skb, &(info->tx_status)); */
/* } else */
/* dev_kfree_skb_irq(info->skb); */
}
}
memset(desc, 0, sizeof(*desc));
memset(info, 0, sizeof(*info));
}
@ -485,7 +484,7 @@ void handle_txd_irq(struct agnx_priv *priv)
void handle_other_irq(struct agnx_priv *priv)
{
// void __iomem *ctl = priv->ctl;
/* void __iomem *ctl = priv->ctl; */
u32 status = priv->irq_status;
void __iomem *ctl = priv->ctl;
u32 reg;
@ -526,11 +525,11 @@ void handle_other_irq(struct agnx_priv *priv)
iowrite32(reg, ctl + AGNX_INT_MASK);
iowrite32(IRQ_RX_FRAME, ctl + AGNX_INT_STAT);
printk(PFX "IRQ: RX Frame\n");
rx_frame_cnt++;
rx_frame_cnt++;
}
if (status & IRQ_ERR_INT) {
iowrite32(IRQ_ERR_INT, ctl + AGNX_INT_STAT);
// agnx_hw_reset(priv);
/* agnx_hw_reset(priv); */
printk(PFX "IRQ: Error Interrupt\n");
}
if (status & IRQ_TX_QUE_FULL)
@ -558,14 +557,14 @@ void handle_other_irq(struct agnx_priv *priv)
static inline void route_flag_set(struct agnx_hdr *txhdr)
{
// u32 reg = 0;
/* u32 reg = 0; */
/* FIXME */
/* reg = (0x7 << ROUTE_COMPRESSION_SHIFT) & ROUTE_COMPRESSION; */
/* txhdr->reg5 = cpu_to_be32(reg); */
txhdr->reg5 = (0xa << 0x0) | (0x7 << 0x18);
// txhdr->reg5 = cpu_to_be32((0xa << 0x0) | (0x7 << 0x18));
// txhdr->reg5 = cpu_to_be32(0x7 << 0x0);
/* reg = (0x7 << ROUTE_COMPRESSION_SHIFT) & ROUTE_COMPRESSION; */
/* txhdr->reg5 = cpu_to_be32(reg); */
txhdr->reg5 = (0xa << 0x0) | (0x7 << 0x18);
/* txhdr->reg5 = cpu_to_be32((0xa << 0x0) | (0x7 << 0x18)); */
/* txhdr->reg5 = cpu_to_be32(0x7 << 0x0); */
}
/* Return 0 if no match */
@ -579,12 +578,29 @@ static inline unsigned int get_power_level(unsigned int rate, unsigned int anten
case 55:
case 60:
case 90:
case 120: power_level = 22; break;
case 180: power_level = 19; break;
case 240: power_level = 18; break;
case 360: power_level = 16; break;
case 480: power_level = 15; break;
case 540: power_level = 14; break;
case 120:
power_level = 22;
break;
case 180:
power_level = 19;
break;
case 240:
power_level = 18;
break;
case 360:
power_level = 16;
break;
case 480:
power_level = 15;
break;
case 540:
power_level = 14;
break;
default:
agnx_bug("Error rate setting\n");
}
@ -604,30 +620,30 @@ static inline void fill_agnx_hdr(struct agnx_priv *priv, struct agnx_info *tx_in
memset(txhdr, 0, sizeof(*txhdr));
// reg = agnx_set_bits(STATION_ID, STATION_ID_SHIFT, LOCAL_STAID);
/* reg = agnx_set_bits(STATION_ID, STATION_ID_SHIFT, LOCAL_STAID); */
reg = agnx_set_bits(STATION_ID, STATION_ID_SHIFT, BSSID_STAID);
reg |= agnx_set_bits(WORKQUEUE_ID, WORKQUEUE_ID_SHIFT, 0);
txhdr->reg4 = cpu_to_be32(reg);
/* Set the Hardware Sequence Number to 1? */
reg = agnx_set_bits(SEQUENCE_NUMBER, SEQUENCE_NUMBER_SHIFT, 0);
// reg = agnx_set_bits(SEQUENCE_NUMBER, SEQUENCE_NUMBER_SHIFT, 1);
/* reg = agnx_set_bits(SEQUENCE_NUMBER, SEQUENCE_NUMBER_SHIFT, 1); */
reg |= agnx_set_bits(MAC_HDR_LEN, MAC_HDR_LEN_SHIFT, tx_info->hdr_len);
txhdr->reg1 = cpu_to_be32(reg);
/* Set the agnx_hdr's MAC header */
memcpy(txhdr->mac_hdr, &tx_info->hdr, tx_info->hdr_len);
reg = agnx_set_bits(ACK, ACK_SHIFT, 1);
// reg = agnx_set_bits(ACK, ACK_SHIFT, 0);
/* reg = agnx_set_bits(ACK, ACK_SHIFT, 0); */
reg |= agnx_set_bits(MULTICAST, MULTICAST_SHIFT, 0);
// reg |= agnx_set_bits(MULTICAST, MULTICAST_SHIFT, 1);
/* reg |= agnx_set_bits(MULTICAST, MULTICAST_SHIFT, 1); */
reg |= agnx_set_bits(RELAY, RELAY_SHIFT, 0);
reg |= agnx_set_bits(TM, TM_SHIFT, 0);
txhdr->reg0 = cpu_to_be32(reg);
/* Set the long and short retry limits */
txhdr->tx.short_retry_limit = tx_info->txi->control.rates[0].count;
txhdr->tx.long_retry_limit = tx_info->txi->control.rates[0].count;
txhdr->tx.short_retry_limit = tx_info->txi->control.rates[0].count;
txhdr->tx.long_retry_limit = tx_info->txi->control.rates[0].count;
/* FIXME */
len = tx_info->skb->len - sizeof(*txhdr) + tx_info->hdr_len + FCS_LEN;
@ -652,23 +668,23 @@ static void txm_power_set(struct agnx_priv *priv,
if (txi->control.rates[0].idx < 0) {
/* For B mode Short Preamble */
reg = agnx_set_bits(PHY_MODE, PHY_MODE_SHIFT, AGNX_MODE_80211B_SHORT);
// control->tx_rate = -control->tx_rate;
/* control->tx_rate = -control->tx_rate; */
} else
reg = agnx_set_bits(PHY_MODE, PHY_MODE_SHIFT, AGNX_MODE_80211G);
// reg = agnx_set_bits(PHY_MODE, PHY_MODE_SHIFT, AGNX_MODE_80211B_LONG);
/* reg = agnx_set_bits(PHY_MODE, PHY_MODE_SHIFT, AGNX_MODE_80211B_LONG); */
reg |= agnx_set_bits(SIGNAL, SIGNAL_SHIFT, 0xB);
reg |= agnx_set_bits(RATE, RATE_SHIFT, 0xB);
// reg |= agnx_set_bits(POWER_LEVEL, POWER_LEVEL_SHIFT, 15);
/* reg |= agnx_set_bits(POWER_LEVEL, POWER_LEVEL_SHIFT, 15); */
reg |= agnx_set_bits(POWER_LEVEL, POWER_LEVEL_SHIFT, 20);
/* if rate < 11M set it to 0 */
reg |= agnx_set_bits(NUM_TRANSMITTERS, NUM_TRANSMITTERS_SHIFT, 1);
// reg |= agnx_set_bits(EDCF, EDCF_SHIFT, 1);
// reg |= agnx_set_bits(TIFS, TIFS_SHIFT, 1);
/* reg |= agnx_set_bits(EDCF, EDCF_SHIFT, 1); */
/* reg |= agnx_set_bits(TIFS, TIFS_SHIFT, 1); */
power.reg = reg;
// power.reg = cpu_to_le32(reg);
/* power.reg = cpu_to_le32(reg); */
// set_sta_power(priv, &power, LOCAL_STAID);
/* set_sta_power(priv, &power, LOCAL_STAID); */
set_sta_power(priv, &power, BSSID_STAID);
}
@ -759,24 +775,24 @@ static int __agnx_tx(struct agnx_priv *priv, struct sk_buff *skb,
txm_power_set(priv, txi);
/* do { */
/* int j; */
/* size_t len; */
/* len = skb->len - hdr_info->dma_len + hdr_info->hdr_len; */
/* // if (len == 614) { */
/* agnx_print_desc(hdr_desc); */
/* agnx_print_desc(frag_desc); */
/* agnx_print_tx_hdr((struct agnx_hdr *)skb->data); */
/* agnx_print_sta_power(priv, LOCAL_STAID); */
/* agnx_print_sta(priv, LOCAL_STAID); */
/* for (j = 0; j < 8; j++) */
/* agnx_print_sta_tx_wq(priv, LOCAL_STAID, j); */
/* agnx_print_sta_power(priv, BSSID_STAID); */
/* agnx_print_sta(priv, BSSID_STAID); */
/* for (j = 0; j < 8; j++) */
/* agnx_print_sta_tx_wq(priv, BSSID_STAID, j); */
/* // } */
/* } while (0); */
/* do { */
/* int j; */
/* size_t len; */
/* len = skb->len - hdr_info->dma_len + hdr_info->hdr_len; */
/* if (len == 614) { */
/* agnx_print_desc(hdr_desc); */
/* agnx_print_desc(frag_desc); */
/* agnx_print_tx_hdr((struct agnx_hdr *)skb->data); */
/* agnx_print_sta_power(priv, LOCAL_STAID); */
/* agnx_print_sta(priv, LOCAL_STAID); */
/* for (j = 0; j < 8; j++) */
/* agnx_print_sta_tx_wq(priv, LOCAL_STAID, j); */
/* agnx_print_sta_power(priv, BSSID_STAID); */
/* agnx_print_sta(priv, BSSID_STAID); */
/* for (j = 0; j < 8; j++) */
/* agnx_print_sta_tx_wq(priv, BSSID_STAID, j); */
/* } */
/* } while (0); */
spin_unlock_irqrestore(&priv->lock, flags);
@ -787,7 +803,7 @@ static int __agnx_tx(struct agnx_priv *priv, struct sk_buff *skb,
reg = (ioread32(priv->ctl + AGNX_CIR_TXMCTL));
reg |= 0x8;
iowrite32((reg), priv->ctl + AGNX_CIR_TXMCTL);
}while (0);
} while (0);
/* Trigger TXD */
do {
@ -795,7 +811,7 @@ static int __agnx_tx(struct agnx_priv *priv, struct sk_buff *skb,
reg = (ioread32(priv->ctl + AGNX_CIR_TXDCTL));
reg |= 0x8;
iowrite32((reg), priv->ctl + AGNX_CIR_TXDCTL);
}while (0);
} while (0);
return 0;
}
@ -807,12 +823,12 @@ int _agnx_tx(struct agnx_priv *priv, struct sk_buff *skb)
if (tx_packet_check(skb))
return 0;
/* print_hex_dump_bytes("agnx: TX_PACKET: ", DUMP_PREFIX_NONE, */
/* skb->data, skb->len); */
/* print_hex_dump_bytes("agnx: TX_PACKET: ", DUMP_PREFIX_NONE, */
/* skb->data, skb->len); */
fctl = le16_to_cpu(*((__le16 *)skb->data));
fctl = le16_to_cpu(*((__le16 *)skb->data));
if ( (fctl & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA )
if ((fctl & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA)
return __agnx_tx(priv, skb, &priv->txd);
else
return __agnx_tx(priv, skb, &priv->txm);

View file

@ -46,7 +46,6 @@
#include <linux/cdev.h>
#include <linux/delay.h>
#include <linux/dma-mapping.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/io.h>
@ -313,15 +312,16 @@ static int __devinit map_bars(struct ape_dev *ape, struct pci_dev *dev)
continue;
/* do not map BARs with address 0 */
if (!bar_start || !bar_end) {
printk(KERN_DEBUG "BAR #%d is not present?!\n", i);
printk(KERN_DEBUG "BAR #%d is not present?!\n", i);
rc = -1;
goto fail;
}
bar_length = bar_end - bar_start + 1;
/* BAR length is less than driver requires? */
if (bar_length < bar_min_len[i]) {
printk(KERN_DEBUG "BAR #%d length = %lu bytes but driver "
"requires at least %lu bytes\n", i, bar_length, bar_min_len[i]);
printk(KERN_DEBUG "BAR #%d length = %lu bytes but driver "
"requires at least %lu bytes\n",
i, bar_length, bar_min_len[i]);
rc = -1;
goto fail;
}
@ -333,8 +333,8 @@ static int __devinit map_bars(struct ape_dev *ape, struct pci_dev *dev)
rc = -1;
goto fail;
}
printk(KERN_DEBUG "BAR[%d] mapped at 0x%p with length %lu(/%lu).\n", i,
ape->bar[i], bar_min_len[i], bar_length);
printk(KERN_DEBUG "BAR[%d] mapped at 0x%p with length %lu(/%lu).\n", i,
ape->bar[i], bar_min_len[i], bar_length);
}
/* succesfully mapped all required BAR regions */
rc = 0;
@ -427,11 +427,13 @@ static int ape_sg_to_chdma_table(struct scatterlist *sgl, int nents, int first,
dma_addr_t next = sg_dma_address(&sgl[i + 1]);
/* length of this entry i */
len = sg_dma_len(&sgl[i]);
printk(KERN_DEBUG "%04d: addr=0x%08x length=0x%08x\n", i, addr, len);
printk(KERN_DEBUG "%04d: addr=0x%Lx length=0x%08x\n", i,
(unsigned long long)addr, len);
/* entry i + 1 is non-contiguous with entry i? */
if (next != addr + len) {
/* TODO create entry here (we could overwrite i) */
printk(KERN_DEBUG "%4d: cont_addr=0x%08x cont_len=0x%08x\n", j, cont_addr, cont_len);
printk(KERN_DEBUG "%4d: cont_addr=0x%Lx cont_len=0x%08x\n", j,
(unsigned long long)cont_addr, cont_len);
/* set descriptor for contiguous transfer */
ape_chdma_desc_set(&desc[j], cont_addr, ep_addr, cont_len);
/* next end point memory address */
@ -447,8 +449,10 @@ static int ape_sg_to_chdma_table(struct scatterlist *sgl, int nents, int first,
addr = next;
}
/* TODO create entry here (we could overwrite i) */
printk(KERN_DEBUG "%04d: addr=0x%08x length=0x%08x\n", i, addr, len);
printk(KERN_DEBUG "%4d: cont_addr=0x%08x length=0x%08x\n", j, cont_addr, cont_len);
printk(KERN_DEBUG "%04d: addr=0x%Lx length=0x%08x\n", i,
(unsigned long long)addr, len);
printk(KERN_DEBUG "%4d: cont_addr=0x%Lx length=0x%08x\n", j,
(unsigned long long)cont_addr, cont_len);
j++;
return j;
}
@ -467,15 +471,14 @@ static inline int compare(u32 *p, u32 *q, int len)
} else {
fail++;
/* show the first few miscompares */
if (fail < 10) {
printk(KERN_DEBUG "[%p] = 0x%08x != [%p] = 0x%08x ?!\n", p, *p, q, *q);
/* but stop after a while */
} else if (fail == 10) {
printk(KERN_DEBUG "---more errors follow! not printed---\n");
} else {
if (fail < 10)
printk(KERN_DEBUG "[%p] = 0x%08x != [%p] = 0x%08x ?!\n", p, *p, q, *q);
/* but stop after a while */
else if (fail == 10)
printk(KERN_DEBUG "---more errors follow! not printed---\n");
else
/* stop compare after this many errors */
break;
}
break;
}
p++;
q++;
@ -528,7 +531,7 @@ static int __devinit dma_test(struct ape_dev *ape, struct pci_dev *dev)
printk(KERN_DEBUG "ape->table_virt = 0x%p.\n", ape->table_virt);
if (!write_header || !read_header || !ape->table_virt)
goto fail;
goto fail;
/* allocate and map coherently-cached memory for a DMA-able buffer */
/* @see Documentation/PCI/PCI-DMA-mapping.txt, near line 318 */
@ -565,9 +568,8 @@ static int __devinit dma_test(struct ape_dev *ape, struct pci_dev *dev)
/* read 8192 bytes from RC buffer to EP address 4096 */
ape_chdma_desc_set(&ape->table_virt->desc[n], buffer_bus, 4096, 2 * PAGE_SIZE);
#if 1
for (i = 0; i < 255; i++) {
for (i = 0; i < 255; i++)
ape_chdma_desc_set(&ape->table_virt->desc[i], buffer_bus, 4096, 2 * PAGE_SIZE);
}
/* index of last descriptor */
n = i - 1;
#endif
@ -647,7 +649,7 @@ static int __devinit dma_test(struct ape_dev *ape, struct pci_dev *dev)
printk(KERN_DEBUG "EPLAST = %u, n = %d\n", eplast, n);
if (eplast == n) {
printk(KERN_DEBUG "DONE\n");
/* print IRQ count before the transfer */
/* print IRQ count before the transfer */
printk(KERN_DEBUG "#IRQs during transfer: %d\n", ape->irq_count - irq_count);
break;
}
@ -661,9 +663,9 @@ static int __devinit dma_test(struct ape_dev *ape, struct pci_dev *dev)
n = 0;
ape_chdma_desc_set(&ape->table_virt->desc[n], buffer_bus + 8192, 4096, 2 * PAGE_SIZE);
#if 1
for (i = 0; i < 255; i++) {
for (i = 0; i < 255; i++)
ape_chdma_desc_set(&ape->table_virt->desc[i], buffer_bus + 8192, 4096, 2 * PAGE_SIZE);
}
/* index of last descriptor */
n = i - 1;
#endif
@ -691,7 +693,7 @@ static int __devinit dma_test(struct ape_dev *ape, struct pci_dev *dev)
w = (u32)(n + 1);
/* enable updates of eplast for each descriptor completion */
w |= (u32)(1UL << 18)/*global EPLAST_EN*/;
#if 0 // test variable, make a module option later
#if 0 /* test variable, make a module option later */
/* enable MSI for each descriptor completion */
if (ape->msi_enabled)
w |= (1UL << 17)/*global MSI*/;
@ -715,7 +717,7 @@ static int __devinit dma_test(struct ape_dev *ape, struct pci_dev *dev)
/** memory write barrier */
wmb();
/** dummy read to flush posted writes */
//(void)ioread32();
/* (void) ioread32(); */
printk(KERN_DEBUG "POLL FOR WRITE:\n");
/* poll for completion, 1000 times 1 millisecond */
@ -844,7 +846,7 @@ static int __devinit probe(struct pci_dev *dev, const struct pci_device_id *id)
}
ape->got_regions = 1;
#if 1 // @todo For now, disable 64-bit, because I do not understand the implications (DAC!)
#if 1 /* @todo For now, disable 64-bit, because I do not understand the implications (DAC!) */
/* query for DMA transfer */
/* @see Documentation/PCI/PCI-DMA-mapping.txt */
if (!pci_set_dma_mask(dev, DMA_64BIT_MASK)) {
@ -947,7 +949,8 @@ static void __devexit remove(struct pci_dev *dev)
struct ape_dev *ape;
printk(KERN_DEBUG "remove(0x%p)\n", dev);
if ((dev == 0) || (dev->dev.driver_data == 0)) {
printk(KERN_DEBUG "remove(dev = 0x%p) dev->dev.driver_data = 0x%p\n", dev, dev->dev.driver_data);
printk(KERN_DEBUG "remove(dev = 0x%p) dev->dev.driver_data = 0x%p\n",
dev, (dev? dev->dev.driver_data: NULL));
return;
}
ape = (struct ape_dev *)dev->dev.driver_data;
@ -1048,10 +1051,9 @@ static ssize_t sg_write(struct file *file, const char __user *buf, size_t count,
printk(KERN_DEBUG DRV_NAME "_write(buf=0x%p, count=%lld, pos=%llu)\n",
buf, (s64)count, (u64)*pos);
/* TODO transfer boundaries at PAGE_SIZE granularity */
while (remaining > 0)
{
while (remaining > 0) {
/* limit DMA transfer size */
transfer_len = (remaining < APE_CHDMA_MAX_TRANSFER_LEN)? remaining:
transfer_len = (remaining < APE_CHDMA_MAX_TRANSFER_LEN) ? remaining :
APE_CHDMA_MAX_TRANSFER_LEN;
/* get all user space buffer pages and create a scattergather list */
sgm_map_user_pages(ape->sgm, transfer_addr, transfer_len, 0/*read from userspace*/);
@ -1085,12 +1087,12 @@ static ssize_t sg_write(struct file *file, const char __user *buf, size_t count,
/*
* character device file operations
*/
static struct file_operations sg_fops = {
.owner = THIS_MODULE,
.open = sg_open,
.release = sg_close,
.read = sg_read,
.write = sg_write,
static const struct file_operations sg_fops = {
.owner = THIS_MODULE,
.open = sg_open,
.release = sg_close,
.read = sg_read,
.write = sg_write,
};
/* sg_init() - Initialize character device
@ -1158,12 +1160,12 @@ static struct pci_driver pci_driver = {
*/
static int __init alterapciechdma_init(void)
{
int rc = 0;
int rc = 0;
printk(KERN_DEBUG DRV_NAME " init(), built at " __DATE__ " " __TIME__ "\n");
/* register this driver with the PCI bus driver */
rc = pci_register_driver(&pci_driver);
if (rc < 0)
return rc;
return rc;
return 0;
}

View file

@ -2649,14 +2649,22 @@ static void binder_vma_open(struct vm_area_struct *vma)
{
struct binder_proc *proc = vma->vm_private_data;
if (binder_debug_mask & BINDER_DEBUG_OPEN_CLOSE)
printk(KERN_INFO "binder: %d open vm area %lx-%lx (%ld K) vma %lx pagep %lx\n", proc->pid, vma->vm_start, vma->vm_end, (vma->vm_end - vma->vm_start) / SZ_1K, vma->vm_flags, pgprot_val(vma->vm_page_prot));
printk(KERN_INFO
"binder: %d open vm area %lx-%lx (%ld K) vma %lx pagep %lx\n",
proc->pid, vma->vm_start, vma->vm_end,
(vma->vm_end - vma->vm_start) / SZ_1K, vma->vm_flags,
(unsigned long)pgprot_val(vma->vm_page_prot));
dump_stack();
}
static void binder_vma_close(struct vm_area_struct *vma)
{
struct binder_proc *proc = vma->vm_private_data;
if (binder_debug_mask & BINDER_DEBUG_OPEN_CLOSE)
printk(KERN_INFO "binder: %d close vm area %lx-%lx (%ld K) vma %lx pagep %lx\n", proc->pid, vma->vm_start, vma->vm_end, (vma->vm_end - vma->vm_start) / SZ_1K, vma->vm_flags, pgprot_val(vma->vm_page_prot));
printk(KERN_INFO
"binder: %d close vm area %lx-%lx (%ld K) vma %lx pagep %lx\n",
proc->pid, vma->vm_start, vma->vm_end,
(vma->vm_end - vma->vm_start) / SZ_1K, vma->vm_flags,
(unsigned long)pgprot_val(vma->vm_page_prot));
proc->vma = NULL;
}
@ -2677,7 +2685,11 @@ static int binder_mmap(struct file *filp, struct vm_area_struct *vma)
vma->vm_end = vma->vm_start + SZ_4M;
if (binder_debug_mask & BINDER_DEBUG_OPEN_CLOSE)
printk(KERN_INFO "binder_mmap: %d %lx-%lx (%ld K) vma %lx pagep %lx\n", proc->pid, vma->vm_start, vma->vm_end, (vma->vm_end - vma->vm_start) / SZ_1K, vma->vm_flags, pgprot_val(vma->vm_page_prot));
printk(KERN_INFO
"binder_mmap: %d %lx-%lx (%ld K) vma %lx pagep %lx\n",
proc->pid, vma->vm_start, vma->vm_end,
(vma->vm_end - vma->vm_start) / SZ_1K, vma->vm_flags,
(unsigned long)pgprot_val(vma->vm_page_prot));
if (vma->vm_flags & FORBIDDEN_MMAP_FLAGS) {
ret = -EPERM;

View file

@ -225,7 +225,7 @@ static int __init ram_console_init(struct ram_console_buffer *buffer,
buffer_size - sizeof(struct ram_console_buffer);
if (ram_console_buffer_size > buffer_size) {
pr_err("ram_console: buffer %p, invalid size %d, datasize %d\n",
pr_err("ram_console: buffer %p, invalid size %zu, datasize %zu\n",
buffer, buffer_size, ram_console_buffer_size);
return 0;
}
@ -235,8 +235,8 @@ static int __init ram_console_init(struct ram_console_buffer *buffer,
ECC_BLOCK_SIZE) + 1) * ECC_SIZE;
if (ram_console_buffer_size > buffer_size) {
pr_err("ram_console: buffer %p, invalid size %d, "
"non-ecc datasize %d\n",
pr_err("ram_console: buffer %p, invalid size %zu, "
"non-ecc datasize %zu\n",
buffer, buffer_size, ram_console_buffer_size);
return 0;
}
@ -322,7 +322,7 @@ static int ram_console_driver_probe(struct platform_device *pdev)
}
buffer_size = res->end - res->start + 1;
start = res->start;
printk(KERN_INFO "ram_console: got buffer at %x, size %x\n",
printk(KERN_INFO "ram_console: got buffer at %zx, size %zx\n",
start, buffer_size);
buffer = ioremap(res->start, buffer_size);
if (buffer == NULL) {

View file

@ -56,10 +56,10 @@ MODULE_AUTHOR("Jakub Schmidtke, sjakub@gmail.com");
MODULE_DESCRIPTION("Asus OLED Driver v" ASUS_OLED_VERSION);
MODULE_LICENSE("GPL");
static struct class *oled_class = 0;
static int oled_num = 0;
static struct class *oled_class;
static int oled_num;
static uint start_off = 0;
static uint start_off;
module_param(start_off, uint, 0644);
@ -80,20 +80,20 @@ struct oled_dev_desc_str {
};
/* table of devices that work with this driver */
static struct usb_device_id id_table [] = {
static struct usb_device_id id_table[] = {
{ USB_DEVICE(0x0b05, 0x1726) }, // Asus G1/G2 (and variants)
{ USB_DEVICE(0x0b05, 0x175b) }, // Asus G50V (and possibly others - G70? G71?)
{ },
};
/* parameters of specific devices */
static struct oled_dev_desc_str oled_dev_desc_table [] = {
static struct oled_dev_desc_str oled_dev_desc_table[] = {
{ 0x0b05, 0x1726, 128, PACK_MODE_G1, "G1/G2" },
{ 0x0b05, 0x175b, 256, PACK_MODE_G50, "G50" },
{ },
};
MODULE_DEVICE_TABLE (usb, id_table);
MODULE_DEVICE_TABLE(usb, id_table);
#define SETUP_PACKET_HEADER(packet, val1, val2, val3, val4, val5, val6, val7) \
do { \
@ -107,7 +107,7 @@ MODULE_DEVICE_TABLE (usb, id_table);
packet->header.value6 = val5; \
packet->header.value7 = val6; \
packet->header.value8 = val7; \
} while(0);
} while (0);
struct asus_oled_header {
uint8_t magic1;
@ -160,10 +160,12 @@ static void enable_oled(struct asus_oled_dev *odev, uint8_t enabl)
SETUP_PACKET_HEADER(packet, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00);
if (enabl) packet->bitmap[0] = 0xaf;
else packet->bitmap[0] = 0xae;
if (enabl)
packet->bitmap[0] = 0xaf;
else
packet->bitmap[0] = 0xae;
for (a=0; a<1; a++) {
for (a = 0; a < 1; a++) {
retval = usb_bulk_msg(odev->udev,
usb_sndbulkpipe(odev->udev, 2),
packet,
@ -252,7 +254,7 @@ static void send_packets(struct usb_device *udev, struct asus_oled_packet *packe
}
}
static void send_packet(struct usb_device *udev, struct asus_oled_packet *packet, size_t offset, size_t len, char *buf, uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5, uint8_t b6){
static void send_packet(struct usb_device *udev, struct asus_oled_packet *packet, size_t offset, size_t len, char *buf, uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5, uint8_t b6) {
int retval;
int act_len;
@ -294,7 +296,7 @@ static void send_data(struct asus_oled_dev *odev)
return;
}
if (odev->pack_mode==PACK_MODE_G1){
if (odev->pack_mode == PACK_MODE_G1) {
// When sending roll-mode data the display updated only first packet.
// I have no idea why, but when static picture is send just before
// rolling picture - everything works fine.
@ -308,7 +310,7 @@ static void send_data(struct asus_oled_dev *odev)
send_packets(odev->udev, packet, odev->buf, odev->pic_mode, packet_num);
}
else
if (odev->pack_mode==PACK_MODE_G50){
if (odev->pack_mode == PACK_MODE_G50) {
send_packets_g50(odev->udev, packet, odev->buf);
}
@ -326,7 +328,7 @@ static int append_values(struct asus_oled_dev *odev, uint8_t val, size_t count)
x += odev->x_shift;
y += odev->y_shift;
switch(odev->pack_mode)
switch (odev->pack_mode)
{
case PACK_MODE_G1:
// i = (x/128)*640 + 127 - x + (y/8)*128;
@ -377,30 +379,32 @@ static ssize_t odev_set_picture(struct asus_oled_dev *odev, const char *buf, siz
{
size_t offs = 0, max_offs;
if (count < 1) return 0;
if (count < 1)
return 0;
if (tolower(buf[0]) == 'b'){
if (tolower(buf[0]) == 'b') {
// binary mode, set the entire memory
size_t i;
odev->buf_size = (odev->dev_width * ASUS_OLED_DISP_HEIGHT) / 8;
if (odev->buf) kfree(odev->buf);
if (odev->buf)
kfree(odev->buf);
odev->buf = kmalloc(odev->buf_size, GFP_KERNEL);
memset(odev->buf, 0xff, odev->buf_size);
for (i=1; i < count && i<=32*32; i++){
for (i = 1; i < count && i <= 32 * 32; i++) {
odev->buf[i-1] = buf[i];
odev->buf_offs = i-1;
}
odev->width=odev->dev_width / 8;
odev->height=ASUS_OLED_DISP_HEIGHT;
odev->x_shift=0;
odev->y_shift=0;
odev->last_val=0;
odev->width = odev->dev_width / 8;
odev->height = ASUS_OLED_DISP_HEIGHT;
odev->x_shift = 0;
odev->y_shift = 0;
odev->last_val = 0;
send_data(odev);
@ -416,7 +420,7 @@ static ssize_t odev_set_picture(struct asus_oled_dev *odev, const char *buf, siz
goto error_header;
}
switch(tolower(buf[1])) {
switch (tolower(buf[1])) {
case ASUS_OLED_STATIC:
case ASUS_OLED_ROLL:
case ASUS_OLED_FLASH:
@ -432,27 +436,36 @@ static ssize_t odev_set_picture(struct asus_oled_dev *odev, const char *buf, siz
if (buf[i] >= '0' && buf[i] <= '9') {
w = 10*w + (buf[i] - '0');
if (w > ASUS_OLED_MAX_WIDTH) goto error_width;
if (w > ASUS_OLED_MAX_WIDTH)
goto error_width;
}
else if (tolower(buf[i]) == 'x') break;
else goto error_width;
else if (tolower(buf[i]) == 'x')
break;
else
goto error_width;
}
for (++i; i < count; ++i) {
if (buf[i] >= '0' && buf[i] <= '9') {
h = 10*h + (buf[i] - '0');
if (h > ASUS_OLED_DISP_HEIGHT) goto error_height;
if (h > ASUS_OLED_DISP_HEIGHT)
goto error_height;
}
else if (tolower(buf[i]) == '>') break;
else goto error_height;
else if (tolower(buf[i]) == '>')
break;
else
goto error_height;
}
if (w < 1 || w > ASUS_OLED_MAX_WIDTH) goto error_width;
if (w < 1 || w > ASUS_OLED_MAX_WIDTH)
goto error_width;
if (h < 1 || h > ASUS_OLED_DISP_HEIGHT) goto error_height;
if (h < 1 || h > ASUS_OLED_DISP_HEIGHT)
goto error_height;
if (i >= count || buf[i] != '>') goto error_header;
if (i >= count || buf[i] != '>')
goto error_header;
offs = i+1;
@ -468,7 +481,8 @@ static ssize_t odev_set_picture(struct asus_oled_dev *odev, const char *buf, siz
odev->buf_size = w_mem * h_mem / 8;
if (odev->buf) kfree(odev->buf);
if (odev->buf)
kfree(odev->buf);
odev->buf = kmalloc(odev->buf_size, GFP_KERNEL);
if (odev->buf == NULL) {
@ -505,23 +519,30 @@ static ssize_t odev_set_picture(struct asus_oled_dev *odev, const char *buf, siz
int ret;
if (buf[offs] == '1' || buf[offs] == '#') {
if ( (ret = append_values(odev, 1, 1)) < 0) return ret;
ret = append_values(odev, 1, 1);
if (ret < 0)
return ret;
}
else if (buf[offs] == '0' || buf[offs] == ' ') {
if ( (ret = append_values(odev, 0, 1)) < 0) return ret;
ret = append_values(odev, 0, 1);
if (ret < 0)
return ret;
}
else if (buf[offs] == '\n') {
// New line detected. Lets assume, that all characters till the end of the
// line were equal to the last character in this line.
if (odev->buf_offs % odev->width != 0)
if ( (ret = append_values(odev, odev->last_val,
odev->width - (odev->buf_offs % odev->width))) < 0) return ret;
ret = append_values(odev, odev->last_val,
odev->width - (odev->buf_offs % odev->width));
if (ret < 0)
return ret;
}
offs++;
}
if (odev->buf_offs >= max_offs) send_data(odev);
if (odev->buf_offs >= max_offs)
send_data(odev);
return count;
@ -566,9 +587,9 @@ static int asus_oled_probe(struct usb_interface *interface, const struct usb_dev
uint16_t dev_width = 0;
oled_pack_mode_t pack_mode = PACK_MODE_LAST;
const struct oled_dev_desc_str * dev_desc = oled_dev_desc_table;
const char *desc = 0;
const char *desc = NULL;
if (id == 0) {
if (!id) {
// Even possible? Just to make sure...
dev_err(&interface->dev, "No usb_device_id provided!\n");
return -ENODEV;
@ -586,7 +607,7 @@ static int asus_oled_probe(struct usb_interface *interface, const struct usb_dev
}
}
if ( !desc || dev_width < 1 || pack_mode == PACK_MODE_LAST) {
if (!desc || dev_width < 1 || pack_mode == PACK_MODE_LAST) {
dev_err(&interface->dev, "Missing or incomplete device description!\n");
return -ENODEV;
}
@ -611,20 +632,20 @@ static int asus_oled_probe(struct usb_interface *interface, const struct usb_dev
odev->last_val = 0;
odev->buf = NULL;
odev->enabled = 1;
odev->dev = 0;
odev->dev = NULL;
usb_set_intfdata (interface, odev);
usb_set_intfdata(interface, odev);
if ((retval = device_create_file(&interface->dev, &ASUS_OLED_DEVICE_ATTR(enabled)))) {
retval = device_create_file(&interface->dev, &ASUS_OLED_DEVICE_ATTR(enabled));
if (retval)
goto err_files;
}
if ((retval = device_create_file(&interface->dev, &ASUS_OLED_DEVICE_ATTR(picture)))) {
retval = device_create_file(&interface->dev, &ASUS_OLED_DEVICE_ATTR(picture));
if (retval)
goto err_files;
}
odev->dev = device_create(oled_class, &interface->dev, MKDEV(0,0),
NULL,"oled_%d", ++oled_num);
odev->dev = device_create(oled_class, &interface->dev, MKDEV(0, 0),
NULL, "oled_%d", ++oled_num);
if (IS_ERR(odev->dev)) {
retval = PTR_ERR(odev->dev);
@ -633,13 +654,13 @@ static int asus_oled_probe(struct usb_interface *interface, const struct usb_dev
dev_set_drvdata(odev->dev, odev);
if ( (retval = device_create_file(odev->dev, &dev_attr_enabled))) {
retval = device_create_file(odev->dev, &dev_attr_enabled);
if (retval)
goto err_class_enabled;
}
if ( (retval = device_create_file(odev->dev, &dev_attr_picture))) {
retval = device_create_file(odev->dev, &dev_attr_picture);
if (retval)
goto err_class_picture;
}
dev_info(&interface->dev, "Attached Asus OLED device: %s [width %u, pack_mode %d]\n", desc, odev->dev_width, odev->pack_mode);
@ -659,7 +680,7 @@ static int asus_oled_probe(struct usb_interface *interface, const struct usb_dev
device_remove_file(&interface->dev, &ASUS_OLED_DEVICE_ATTR(enabled));
device_remove_file(&interface->dev, &ASUS_OLED_DEVICE_ATTR(picture));
usb_set_intfdata (interface, NULL);
usb_set_intfdata(interface, NULL);
usb_put_dev(odev->udev);
kfree(odev);
@ -670,19 +691,20 @@ static void asus_oled_disconnect(struct usb_interface *interface)
{
struct asus_oled_dev *odev;
odev = usb_get_intfdata (interface);
usb_set_intfdata (interface, NULL);
odev = usb_get_intfdata(interface);
usb_set_intfdata(interface, NULL);
device_remove_file(odev->dev, &dev_attr_picture);
device_remove_file(odev->dev, &dev_attr_enabled);
device_unregister(odev->dev);
device_remove_file(&interface->dev, & ASUS_OLED_DEVICE_ATTR(picture));
device_remove_file(&interface->dev, & ASUS_OLED_DEVICE_ATTR(enabled));
device_remove_file(&interface->dev, &ASUS_OLED_DEVICE_ATTR(picture));
device_remove_file(&interface->dev, &ASUS_OLED_DEVICE_ATTR(enabled));
usb_put_dev(odev->udev);
if (odev->buf) kfree(odev->buf);
if (odev->buf)
kfree(odev->buf);
kfree(odev);
@ -713,7 +735,8 @@ static int __init asus_oled_init(void)
return PTR_ERR(oled_class);
}
if ((retval = class_create_file(oled_class, &class_attr_version))) {
retval = class_create_file(oled_class, &class_attr_version);
if (retval) {
err("Error creating class version file");
goto error;
}
@ -740,6 +763,6 @@ static void __exit asus_oled_exit(void)
usb_deregister(&oled_driver);
}
module_init (asus_oled_init);
module_exit (asus_oled_exit);
module_init(asus_oled_init);
module_exit(asus_oled_exit);

View file

@ -1,2 +1,7 @@
rewrite the driver to use the proper in-kernel wireless stack
instead of using its own.
Fix the mac80211 port of at76_usb (the proper in-kernel wireless
stack) and get it included to the mainline. Patches available here:
http://git.kernel.org/?p=linux/kernel/git/linville/wireless-legacy.git;a=shortlog;h=at76
Contact Kalle Valo <kalle.valo@iki.fi> and linux-wireless list
<linux-wireless@vger.kernel.org> for more information.

View file

@ -36,7 +36,7 @@
#include <net/ieee80211_radiotap.h>
#include <linux/firmware.h>
#include <linux/leds.h>
#include <net/ieee80211.h>
#include <linux/ieee80211.h>
#include "at76_usb.h"
@ -1727,12 +1727,12 @@ static int at76_assoc_req(struct at76_priv *priv, struct bss_info *bss)
/* write TLV data elements */
ie->id = MFIE_TYPE_SSID;
ie->id = WLAN_EID_SSID;
ie->len = bss->ssid_len;
memcpy(ie->data, bss->ssid, bss->ssid_len);
next_ie(&ie);
ie->id = MFIE_TYPE_RATES;
ie->id = WLAN_EID_SUPP_RATES;
ie->len = sizeof(hw_rates);
memcpy(ie->data, hw_rates, sizeof(hw_rates));
next_ie(&ie); /* ie points behind the supp_rates field */
@ -4397,7 +4397,7 @@ static void at76_rx_mgmt_beacon(struct at76_priv *priv,
switch (ie->id) {
case MFIE_TYPE_SSID:
case WLAN_EID_SSID:
if (have_ssid)
break;
@ -4420,7 +4420,7 @@ static void at76_rx_mgmt_beacon(struct at76_priv *priv,
have_ssid = 1;
break;
case MFIE_TYPE_RATES:
case WLAN_EID_SUPP_RATES:
if (have_rates)
break;
@ -4433,7 +4433,7 @@ static void at76_rx_mgmt_beacon(struct at76_priv *priv,
hex2str(ie->data, ie->len));
break;
case MFIE_TYPE_DS_SET:
case WLAN_EID_DS_PARAMS:
if (have_channel)
break;
@ -4443,9 +4443,9 @@ static void at76_rx_mgmt_beacon(struct at76_priv *priv,
priv->netdev->name, match->channel);
break;
case MFIE_TYPE_CF_SET:
case MFIE_TYPE_TIM:
case MFIE_TYPE_IBSS_SET:
case WLAN_EID_CF_PARAMS:
case WLAN_EID_TIM:
case WLAN_EID_IBSS_PARAMS:
default:
at76_dbg(DBG_RX_BEACON, "%s: beacon IE id %d len %d %s",
priv->netdev->name, ie->id, ie->len,
@ -5370,8 +5370,7 @@ static void at76_delete_device(struct at76_priv *priv)
at76_dbg(DBG_PROC_ENTRY, "%s: unlinked urbs", __func__);
if (priv->rx_skb)
kfree_skb(priv->rx_skb);
kfree_skb(priv->rx_skb);
at76_free_bss_list(priv);
del_timer_sync(&priv->bss_list_timer);

View file

@ -22,6 +22,93 @@
#ifndef _AT76_USB_H
#define _AT76_USB_H
/*
* ieee80211 definitions copied from net/ieee80211.h
*/
#define WEP_KEY_LEN 13
#define WEP_KEYS 4
#define IEEE80211_DATA_LEN 2304
/* Maximum size for the MA-UNITDATA primitive, 802.11 standard section
6.2.1.1.2.
The figure in section 7.1.2 suggests a body size of up to 2312
bytes is allowed, which is a bit confusing, I suspect this
represents the 2304 bytes of real data, plus a possible 8 bytes of
WEP IV and ICV. (this interpretation suggested by Ramiro Barreiro) */
#define IEEE80211_1ADDR_LEN 10
#define IEEE80211_2ADDR_LEN 16
#define IEEE80211_3ADDR_LEN 24
#define IEEE80211_4ADDR_LEN 30
#define IEEE80211_FCS_LEN 4
#define IEEE80211_HLEN (IEEE80211_4ADDR_LEN)
#define IEEE80211_FRAME_LEN (IEEE80211_DATA_LEN + IEEE80211_HLEN)
#define MIN_FRAG_THRESHOLD 256U
#define MAX_FRAG_THRESHOLD 2346U
struct ieee80211_info_element {
u8 id;
u8 len;
u8 data[0];
} __attribute__ ((packed));
struct ieee80211_hdr_3addr {
__le16 frame_ctl;
__le16 duration_id;
u8 addr1[ETH_ALEN];
u8 addr2[ETH_ALEN];
u8 addr3[ETH_ALEN];
__le16 seq_ctl;
u8 payload[0];
} __attribute__ ((packed));
struct ieee80211_auth {
struct ieee80211_hdr_3addr header;
__le16 algorithm;
__le16 transaction;
__le16 status;
/* challenge */
struct ieee80211_info_element info_element[0];
} __attribute__ ((packed));
struct ieee80211_assoc_request {
struct ieee80211_hdr_3addr header;
__le16 capability;
__le16 listen_interval;
/* SSID, supported rates, RSN */
struct ieee80211_info_element info_element[0];
} __attribute__ ((packed));
struct ieee80211_probe_response {
struct ieee80211_hdr_3addr header;
__le32 time_stamp[2];
__le16 beacon_interval;
__le16 capability;
/* SSID, supported rates, FH params, DS params,
* CF params, IBSS params, TIM (if beacon), RSN */
struct ieee80211_info_element info_element[0];
} __attribute__ ((packed));
/* Alias beacon for probe_response */
#define ieee80211_beacon ieee80211_probe_response
struct ieee80211_assoc_response {
struct ieee80211_hdr_3addr header;
__le16 capability;
__le16 status;
__le16 aid;
/* supported rates */
struct ieee80211_info_element info_element[0];
} __attribute__ ((packed));
struct ieee80211_disassoc {
struct ieee80211_hdr_3addr header;
__le16 reason;
} __attribute__ ((packed));
/* Board types */
enum board_type {
BOARD_503_ISL3861 = 1,

View file

@ -0,0 +1,9 @@
config B3DFG
tristate "Brontes 3d Frame Framegrabber"
default n
---help---
This driver provides support for the Brontes 3d Framegrabber
PCI card.
To compile this driver as a module, choose M here. The module
will be called b3dfg.

View file

@ -0,0 +1 @@
obj-$(CONFIG_B3DFG) += b3dfg.o

View file

@ -0,0 +1,4 @@
- queue/wait buffer presents filltime results for each frame?
- counting of dropped frames
- review endianness

File diff suppressed because it is too large Load diff

View file

@ -6,6 +6,13 @@ config COMEDI
Enable support a wide range of data acquisition devices
for Linux.
config COMEDI_DEBUG
bool "Comedi debugging"
depends on COMEDI != n
help
This is an option for use by developers; most people should
say N here. This enables comedi core and driver debugging.
config COMEDI_RT
tristate "Comedi Real-time support"
depends on COMEDI && RT
@ -20,6 +27,13 @@ config COMEDI_PCI_DRIVERS
---help---
Enable lots of comedi PCI drivers to be built
config COMEDI_PCMCIA_DRIVERS
tristate "Comedi PCMCIA drivers"
depends on COMEDI && PCMCIAI
default N
---help---
Enable lots of comedi PCMCIA drivers to be built
config COMEDI_USB_DRIVERS
tristate "Comedi USB drivers"
depends on COMEDI && USB

View file

@ -57,9 +57,6 @@ extern "C" {
/* max length of device and driver names */
#define COMEDI_NAMELEN 20
typedef unsigned int lsampl_t;
typedef unsigned short sampl_t;
/* packs and unpacks a channel/range number */
#define CR_PACK(chan, rng, aref) ((((aref)&0x3)<<24) | (((rng)&0xff)<<16) | (chan))
@ -261,10 +258,11 @@ enum configuration_ids {
INSN_CONFIG_GET_CLOCK_SRC = 2004, /* Get master clock source */
INSN_CONFIG_SET_OTHER_SRC = 2005, /* Set other source */
/* INSN_CONFIG_GET_OTHER_SRC = 2006,*/ /* Get other source */
INSN_CONFIG_GET_HARDWARE_BUFFER_SIZE, /* Get size in bytes of
subdevice's on-board fifos
used during streaming
input/output */
INSN_CONFIG_GET_HARDWARE_BUFFER_SIZE = 2006, /* Get size in bytes of
subdevice's on-board
fifos used during
streaming
input/output */
INSN_CONFIG_SET_COUNTER_MODE = 4097,
INSN_CONFIG_8254_SET_MODE = INSN_CONFIG_SET_COUNTER_MODE, /* deprecated */
INSN_CONFIG_8254_READ_STATUS = 4098,
@ -293,45 +291,32 @@ enum comedi_support_level {
/* ioctls */
#define CIO 'd'
#define COMEDI_DEVCONFIG _IOW(CIO, 0, comedi_devconfig)
#define COMEDI_DEVINFO _IOR(CIO, 1, comedi_devinfo)
#define COMEDI_SUBDINFO _IOR(CIO, 2, comedi_subdinfo)
#define COMEDI_CHANINFO _IOR(CIO, 3, comedi_chaninfo)
#define COMEDI_DEVCONFIG _IOW(CIO, 0, struct comedi_devconfig)
#define COMEDI_DEVINFO _IOR(CIO, 1, struct comedi_devinfo)
#define COMEDI_SUBDINFO _IOR(CIO, 2, struct comedi_subdinfo)
#define COMEDI_CHANINFO _IOR(CIO, 3, struct comedi_chaninfo)
#define COMEDI_TRIG _IOWR(CIO, 4, comedi_trig)
#define COMEDI_LOCK _IO(CIO, 5)
#define COMEDI_UNLOCK _IO(CIO, 6)
#define COMEDI_CANCEL _IO(CIO, 7)
#define COMEDI_RANGEINFO _IOR(CIO, 8, comedi_rangeinfo)
#define COMEDI_CMD _IOR(CIO, 9, comedi_cmd)
#define COMEDI_CMDTEST _IOR(CIO, 10, comedi_cmd)
#define COMEDI_INSNLIST _IOR(CIO, 11, comedi_insnlist)
#define COMEDI_INSN _IOR(CIO, 12, comedi_insn)
#define COMEDI_BUFCONFIG _IOR(CIO, 13, comedi_bufconfig)
#define COMEDI_BUFINFO _IOWR(CIO, 14, comedi_bufinfo)
#define COMEDI_RANGEINFO _IOR(CIO, 8, struct comedi_rangeinfo)
#define COMEDI_CMD _IOR(CIO, 9, struct comedi_cmd)
#define COMEDI_CMDTEST _IOR(CIO, 10, struct comedi_cmd)
#define COMEDI_INSNLIST _IOR(CIO, 11, struct comedi_insnlist)
#define COMEDI_INSN _IOR(CIO, 12, struct comedi_insn)
#define COMEDI_BUFCONFIG _IOR(CIO, 13, struct comedi_bufconfig)
#define COMEDI_BUFINFO _IOWR(CIO, 14, struct comedi_bufinfo)
#define COMEDI_POLL _IO(CIO, 15)
/* structures */
typedef struct comedi_trig_struct comedi_trig;
typedef struct comedi_cmd_struct comedi_cmd;
typedef struct comedi_insn_struct comedi_insn;
typedef struct comedi_insnlist_struct comedi_insnlist;
typedef struct comedi_chaninfo_struct comedi_chaninfo;
typedef struct comedi_subdinfo_struct comedi_subdinfo;
typedef struct comedi_devinfo_struct comedi_devinfo;
typedef struct comedi_devconfig_struct comedi_devconfig;
typedef struct comedi_rangeinfo_struct comedi_rangeinfo;
typedef struct comedi_krange_struct comedi_krange;
typedef struct comedi_bufconfig_struct comedi_bufconfig;
typedef struct comedi_bufinfo_struct comedi_bufinfo;
struct comedi_trig_struct {
struct comedi_trig {
unsigned int subdev; /* subdevice */
unsigned int mode; /* mode */
unsigned int flags;
unsigned int n_chan; /* number of channels */
unsigned int *chanlist; /* channel/range list */
sampl_t *data; /* data list, size depends on subd flags */
short *data; /* data list, size depends on subd flags */
unsigned int n; /* number of scans */
unsigned int trigsrc;
unsigned int trigvar;
@ -340,21 +325,21 @@ struct comedi_trig_struct {
unsigned int unused[3];
};
struct comedi_insn_struct {
struct comedi_insn {
unsigned int insn;
unsigned int n;
lsampl_t *data;
unsigned int *data;
unsigned int subdev;
unsigned int chanspec;
unsigned int unused[3];
};
struct comedi_insnlist_struct {
struct comedi_insnlist {
unsigned int n_insns;
comedi_insn *insns;
struct comedi_insn *insns;
};
struct comedi_cmd_struct {
struct comedi_cmd {
unsigned int subdev;
unsigned int flags;
@ -376,37 +361,37 @@ struct comedi_cmd_struct {
unsigned int *chanlist; /* channel/range list */
unsigned int chanlist_len;
sampl_t *data; /* data list, size depends on subd flags */
short *data; /* data list, size depends on subd flags */
unsigned int data_len;
};
struct comedi_chaninfo_struct {
struct comedi_chaninfo {
unsigned int subdev;
lsampl_t *maxdata_list;
unsigned int *maxdata_list;
unsigned int *flaglist;
unsigned int *rangelist;
unsigned int unused[4];
};
struct comedi_rangeinfo_struct {
struct comedi_rangeinfo {
unsigned int range_type;
void *range_ptr;
};
struct comedi_krange_struct {
struct comedi_krange {
int min; /* fixed point, multiply by 1e-6 */
int max; /* fixed point, multiply by 1e-6 */
unsigned int flags;
};
struct comedi_subdinfo_struct {
struct comedi_subdinfo {
unsigned int type;
unsigned int n_chan;
unsigned int subd_flags;
unsigned int timer_type;
unsigned int len_chanlist;
lsampl_t maxdata;
unsigned int maxdata;
unsigned int flags; /* channel flags */
unsigned int range_type; /* lookup in kernel */
unsigned int settling_time_0;
@ -414,7 +399,7 @@ struct comedi_subdinfo_struct {
unsigned int unused[8];
};
struct comedi_devinfo_struct {
struct comedi_devinfo {
unsigned int version_code;
unsigned int n_subdevs;
char driver_name[COMEDI_NAMELEN];
@ -424,12 +409,12 @@ struct comedi_devinfo_struct {
int unused[30];
};
struct comedi_devconfig_struct {
struct comedi_devconfig {
char board_name[COMEDI_NAMELEN];
int options[COMEDI_NDEVCONFOPTS];
};
struct comedi_bufconfig_struct {
struct comedi_bufconfig {
unsigned int subdevice;
unsigned int flags;
@ -439,7 +424,7 @@ struct comedi_bufconfig_struct {
unsigned int unused[4];
};
struct comedi_bufinfo_struct {
struct comedi_bufinfo {
unsigned int subdevice;
unsigned int bytes_read;

View file

@ -37,31 +37,31 @@
#include <linux/ioctl32.h> /* for (un)register_ioctl32_conversion */
#endif
#define COMEDI32_CHANINFO _IOR(CIO,3,comedi32_chaninfo)
#define COMEDI32_RANGEINFO _IOR(CIO,8,comedi32_rangeinfo)
#define COMEDI32_CHANINFO _IOR(CIO, 3, struct comedi32_chaninfo_struct)
#define COMEDI32_RANGEINFO _IOR(CIO, 8, struct comedi32_rangeinfo_struct)
/* N.B. COMEDI32_CMD and COMEDI_CMD ought to use _IOWR, not _IOR.
* It's too late to change it now, but it only affects the command number. */
#define COMEDI32_CMD _IOR(CIO,9,comedi32_cmd)
#define COMEDI32_CMD _IOR(CIO, 9, struct comedi32_cmd_struct)
/* N.B. COMEDI32_CMDTEST and COMEDI_CMDTEST ought to use _IOWR, not _IOR.
* It's too late to change it now, but it only affects the command number. */
#define COMEDI32_CMDTEST _IOR(CIO,10,comedi32_cmd)
#define COMEDI32_INSNLIST _IOR(CIO,11,comedi32_insnlist)
#define COMEDI32_INSN _IOR(CIO,12,comedi32_insn)
#define COMEDI32_CMDTEST _IOR(CIO, 10, struct comedi32_cmd_struct)
#define COMEDI32_INSNLIST _IOR(CIO, 11, struct comedi32_insnlist_struct)
#define COMEDI32_INSN _IOR(CIO, 12, struct comedi32_insn_struct)
typedef struct comedi32_chaninfo_struct {
struct comedi32_chaninfo_struct {
unsigned int subdev;
compat_uptr_t maxdata_list; /* 32-bit 'lsampl_t *' */
compat_uptr_t maxdata_list; /* 32-bit 'unsigned int *' */
compat_uptr_t flaglist; /* 32-bit 'unsigned int *' */
compat_uptr_t rangelist; /* 32-bit 'unsigned int *' */
unsigned int unused[4];
} comedi32_chaninfo;
};
typedef struct comedi32_rangeinfo_struct {
struct comedi32_rangeinfo_struct {
unsigned int range_type;
compat_uptr_t range_ptr; /* 32-bit 'void *' */
} comedi32_rangeinfo;
};
typedef struct comedi32_cmd_struct {
struct comedi32_cmd_struct {
unsigned int subdev;
unsigned int flags;
unsigned int start_src;
@ -76,37 +76,36 @@ typedef struct comedi32_cmd_struct {
unsigned int stop_arg;
compat_uptr_t chanlist; /* 32-bit 'unsigned int *' */
unsigned int chanlist_len;
compat_uptr_t data; /* 32-bit 'sampl_t *' */
compat_uptr_t data; /* 32-bit 'short *' */
unsigned int data_len;
} comedi32_cmd;
};
typedef struct comedi32_insn_struct {
struct comedi32_insn_struct {
unsigned int insn;
unsigned int n;
compat_uptr_t data; /* 32-bit 'lsampl_t *' */
compat_uptr_t data; /* 32-bit 'unsigned int *' */
unsigned int subdev;
unsigned int chanspec;
unsigned int unused[3];
} comedi32_insn;
};
typedef struct comedi32_insnlist_struct {
struct comedi32_insnlist_struct {
unsigned int n_insns;
compat_uptr_t insns; /* 32-bit 'comedi_insn *' */
} comedi32_insnlist;
compat_uptr_t insns; /* 32-bit 'struct comedi_insn *' */
};
/* Handle translated ioctl. */
static int translated_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
if (!file->f_op) {
if (!file->f_op)
return -ENOTTY;
}
#ifdef HAVE_UNLOCKED_IOCTL
if (file->f_op->unlocked_ioctl) {
int rc = (int)(*file->f_op->unlocked_ioctl)(file, cmd, arg);
if (rc == -ENOIOCTLCMD) {
if (rc == -ENOIOCTLCMD)
rc = -ENOTTY;
}
return rc;
}
#endif
@ -124,8 +123,8 @@ static int translated_ioctl(struct file *file, unsigned int cmd,
/* Handle 32-bit COMEDI_CHANINFO ioctl. */
static int compat_chaninfo(struct file *file, unsigned long arg)
{
comedi_chaninfo __user *chaninfo;
comedi32_chaninfo __user *chaninfo32;
struct comedi_chaninfo __user *chaninfo;
struct comedi32_chaninfo_struct __user *chaninfo32;
int err;
union {
unsigned int uint;
@ -150,9 +149,8 @@ static int compat_chaninfo(struct file *file, unsigned long arg)
err |= __put_user(compat_ptr(temp.uptr), &chaninfo->flaglist);
err |= __get_user(temp.uptr, &chaninfo32->rangelist);
err |= __put_user(compat_ptr(temp.uptr), &chaninfo->rangelist);
if (err) {
if (err)
return -EFAULT;
}
return translated_ioctl(file, COMEDI_CHANINFO, (unsigned long)chaninfo);
}
@ -160,8 +158,8 @@ static int compat_chaninfo(struct file *file, unsigned long arg)
/* Handle 32-bit COMEDI_RANGEINFO ioctl. */
static int compat_rangeinfo(struct file *file, unsigned long arg)
{
comedi_rangeinfo __user *rangeinfo;
comedi32_rangeinfo __user *rangeinfo32;
struct comedi_rangeinfo __user *rangeinfo;
struct comedi32_rangeinfo_struct __user *rangeinfo32;
int err;
union {
unsigned int uint;
@ -182,17 +180,16 @@ static int compat_rangeinfo(struct file *file, unsigned long arg)
err |= __put_user(temp.uint, &rangeinfo->range_type);
err |= __get_user(temp.uptr, &rangeinfo32->range_ptr);
err |= __put_user(compat_ptr(temp.uptr), &rangeinfo->range_ptr);
if (err) {
if (err)
return -EFAULT;
}
return translated_ioctl(file, COMEDI_RANGEINFO,
(unsigned long)rangeinfo);
}
/* Copy 32-bit cmd structure to native cmd structure. */
static int get_compat_cmd(comedi_cmd __user *cmd,
comedi32_cmd __user *cmd32)
static int get_compat_cmd(struct comedi_cmd __user *cmd,
struct comedi32_cmd_struct __user *cmd32)
{
int err;
union {
@ -242,7 +239,7 @@ static int get_compat_cmd(comedi_cmd __user *cmd,
}
/* Copy native cmd structure to 32-bit cmd structure. */
static int put_compat_cmd(comedi32_cmd __user *cmd32, comedi_cmd __user *cmd)
static int put_compat_cmd(struct comedi32_cmd_struct __user *cmd32, struct comedi_cmd __user *cmd)
{
int err;
unsigned int temp;
@ -292,17 +289,16 @@ static int put_compat_cmd(comedi32_cmd __user *cmd32, comedi_cmd __user *cmd)
/* Handle 32-bit COMEDI_CMD ioctl. */
static int compat_cmd(struct file *file, unsigned long arg)
{
comedi_cmd __user *cmd;
comedi32_cmd __user *cmd32;
struct comedi_cmd __user *cmd;
struct comedi32_cmd_struct __user *cmd32;
int rc;
cmd32 = compat_ptr(arg);
cmd = compat_alloc_user_space(sizeof(*cmd));
rc = get_compat_cmd(cmd, cmd32);
if (rc) {
if (rc)
return rc;
}
return translated_ioctl(file, COMEDI_CMD, (unsigned long)cmd);
}
@ -310,33 +306,31 @@ static int compat_cmd(struct file *file, unsigned long arg)
/* Handle 32-bit COMEDI_CMDTEST ioctl. */
static int compat_cmdtest(struct file *file, unsigned long arg)
{
comedi_cmd __user *cmd;
comedi32_cmd __user *cmd32;
struct comedi_cmd __user *cmd;
struct comedi32_cmd_struct __user *cmd32;
int rc, err;
cmd32 = compat_ptr(arg);
cmd = compat_alloc_user_space(sizeof(*cmd));
rc = get_compat_cmd(cmd, cmd32);
if (rc) {
if (rc)
return rc;
}
rc = translated_ioctl(file, COMEDI_CMDTEST, (unsigned long)cmd);
if (rc < 0) {
if (rc < 0)
return rc;
}
err = put_compat_cmd(cmd32, cmd);
if (err) {
if (err)
rc = err;
}
return rc;
}
/* Copy 32-bit insn structure to native insn structure. */
static int get_compat_insn(comedi_insn __user *insn,
comedi32_insn __user *insn32)
static int get_compat_insn(struct comedi_insn __user *insn,
struct comedi32_insn_struct __user *insn32)
{
int err;
union {
@ -347,9 +341,9 @@ static int get_compat_insn(comedi_insn __user *insn,
/* Copy insn structure. Ignore the unused members. */
err = 0;
if (!access_ok(VERIFY_READ, insn32, sizeof(*insn32))
|| !access_ok(VERIFY_WRITE, insn, sizeof(*insn))) {
|| !access_ok(VERIFY_WRITE, insn, sizeof(*insn)))
return -EFAULT;
}
err |= __get_user(temp.uint, &insn32->insn);
err |= __put_user(temp.uint, &insn->insn);
err |= __get_user(temp.uint, &insn32->n);
@ -367,11 +361,11 @@ static int get_compat_insn(comedi_insn __user *insn,
static int compat_insnlist(struct file *file, unsigned long arg)
{
struct combined_insnlist {
comedi_insnlist insnlist;
comedi_insn insn[1];
struct comedi_insnlist insnlist;
struct comedi_insn insn[1];
} __user *s;
comedi32_insnlist __user *insnlist32;
comedi32_insn __user *insn32;
struct comedi32_insnlist_struct __user *insnlist32;
struct comedi32_insn_struct __user *insn32;
compat_uptr_t uptr;
unsigned int n_insns, n;
int err, rc;
@ -386,9 +380,8 @@ static int compat_insnlist(struct file *file, unsigned long arg)
err |= __get_user(n_insns, &insnlist32->n_insns);
err |= __get_user(uptr, &insnlist32->insns);
insn32 = compat_ptr(uptr);
if (err) {
if (err)
return -EFAULT;
}
/* Allocate user memory to copy insnlist and insns into. */
s = compat_alloc_user_space(offsetof(struct combined_insnlist,
@ -400,16 +393,14 @@ static int compat_insnlist(struct file *file, unsigned long arg)
}
err |= __put_user(n_insns, &s->insnlist.n_insns);
err |= __put_user(&s->insn[0], &s->insnlist.insns);
if (err) {
if (err)
return -EFAULT;
}
/* Copy insn structures. */
for (n = 0; n < n_insns; n++) {
rc = get_compat_insn(&s->insn[n], &insn32[n]);
if (rc) {
if (rc)
return rc;
}
}
return translated_ioctl(file, COMEDI_INSNLIST,
@ -419,17 +410,16 @@ static int compat_insnlist(struct file *file, unsigned long arg)
/* Handle 32-bit COMEDI_INSN ioctl. */
static int compat_insn(struct file *file, unsigned long arg)
{
comedi_insn __user *insn;
comedi32_insn __user *insn32;
struct comedi_insn __user *insn;
struct comedi32_insn_struct __user *insn32;
int rc;
insn32 = compat_ptr(arg);
insn = compat_alloc_user_space(sizeof(*insn));
rc = get_compat_insn(insn, insn32);
if (rc) {
if (rc)
return rc;
}
return translated_ioctl(file, COMEDI_INSN, (unsigned long)insn);
}
@ -512,14 +502,14 @@ static int mapped_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg,
int rc;
/* Make sure we are dealing with a Comedi device. */
if (imajor(file->f_dentry->d_inode) != COMEDI_MAJOR) {
if (imajor(file->f_dentry->d_inode) != COMEDI_MAJOR)
return -ENOTTY;
}
rc = raw_ioctl(file, cmd, arg);
/* Do not return -ENOIOCTLCMD. */
if (rc == -ENOIOCTLCMD) {
if (rc == -ENOIOCTLCMD)
rc = -ENOTTY;
}
return rc;
}

View file

@ -59,33 +59,39 @@ int comedi_debug;
module_param(comedi_debug, int, 0644);
#endif
int comedi_autoconfig = 1;
module_param(comedi_autoconfig, bool, 0444);
int comedi_num_legacy_minors = 0;
module_param(comedi_num_legacy_minors, int, 0444);
static DEFINE_SPINLOCK(comedi_file_info_table_lock);
static struct comedi_device_file_info
*comedi_file_info_table[COMEDI_NUM_MINORS];
static int do_devconfig_ioctl(comedi_device *dev, comedi_devconfig *arg);
static int do_bufconfig_ioctl(comedi_device *dev, void *arg);
static int do_devinfo_ioctl(comedi_device *dev, comedi_devinfo *arg,
static int do_devconfig_ioctl(struct comedi_device *dev, struct comedi_devconfig *arg);
static int do_bufconfig_ioctl(struct comedi_device *dev, void *arg);
static int do_devinfo_ioctl(struct comedi_device *dev, struct comedi_devinfo *arg,
struct file *file);
static int do_subdinfo_ioctl(comedi_device *dev, comedi_subdinfo *arg,
static int do_subdinfo_ioctl(struct comedi_device *dev, struct comedi_subdinfo *arg,
void *file);
static int do_chaninfo_ioctl(comedi_device *dev, comedi_chaninfo *arg);
static int do_bufinfo_ioctl(comedi_device *dev, void *arg);
static int do_cmd_ioctl(comedi_device *dev, void *arg, void *file);
static int do_lock_ioctl(comedi_device *dev, unsigned int arg, void *file);
static int do_unlock_ioctl(comedi_device *dev, unsigned int arg, void *file);
static int do_cancel_ioctl(comedi_device *dev, unsigned int arg, void *file);
static int do_cmdtest_ioctl(comedi_device *dev, void *arg, void *file);
static int do_insnlist_ioctl(comedi_device *dev, void *arg, void *file);
static int do_insn_ioctl(comedi_device *dev, void *arg, void *file);
static int do_poll_ioctl(comedi_device *dev, unsigned int subd, void *file);
static int do_chaninfo_ioctl(struct comedi_device *dev, struct comedi_chaninfo *arg);
static int do_bufinfo_ioctl(struct comedi_device *dev, void *arg);
static int do_cmd_ioctl(struct comedi_device *dev, void *arg, void *file);
static int do_lock_ioctl(struct comedi_device *dev, unsigned int arg, void *file);
static int do_unlock_ioctl(struct comedi_device *dev, unsigned int arg, void *file);
static int do_cancel_ioctl(struct comedi_device *dev, unsigned int arg, void *file);
static int do_cmdtest_ioctl(struct comedi_device *dev, void *arg, void *file);
static int do_insnlist_ioctl(struct comedi_device *dev, void *arg, void *file);
static int do_insn_ioctl(struct comedi_device *dev, void *arg, void *file);
static int do_poll_ioctl(struct comedi_device *dev, unsigned int subd, void *file);
extern void do_become_nonbusy(comedi_device *dev, comedi_subdevice *s);
static int do_cancel(comedi_device *dev, comedi_subdevice *s);
extern void do_become_nonbusy(struct comedi_device *dev, struct comedi_subdevice *s);
static int do_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
static int comedi_fasync(int fd, struct file *file, int on);
static int is_device_busy(comedi_device *dev);
static int is_device_busy(struct comedi_device *dev);
#ifdef HAVE_UNLOCKED_IOCTL
static long comedi_unlocked_ioctl(struct file *file, unsigned int cmd,
@ -98,9 +104,13 @@ static int comedi_ioctl(struct inode *inode, struct file *file,
const unsigned minor = iminor(file->f_dentry->d_inode);
struct comedi_device_file_info *dev_file_info =
comedi_get_device_file_info(minor);
comedi_device *dev = dev_file_info->device;
struct comedi_device *dev;
int rc;
if (dev_file_info == NULL || dev_file_info->device == NULL)
return -ENODEV;
dev = dev_file_info->device;
mutex_lock(&dev->mutex);
/* Device config is special, because it must work on
@ -182,9 +192,9 @@ static int comedi_ioctl(struct inode *inode, struct file *file,
writes:
none
*/
static int do_devconfig_ioctl(comedi_device *dev, comedi_devconfig *arg)
static int do_devconfig_ioctl(struct comedi_device *dev, struct comedi_devconfig *arg)
{
comedi_devconfig it;
struct comedi_devconfig it;
int ret;
unsigned char *aux_data = NULL;
int aux_len;
@ -203,7 +213,7 @@ static int do_devconfig_ioctl(comedi_device *dev, comedi_devconfig *arg)
return 0;
}
if (copy_from_user(&it, arg, sizeof(comedi_devconfig)))
if (copy_from_user(&it, arg, sizeof(struct comedi_devconfig)))
return -EFAULT;
it.board_name[COMEDI_NAMELEN - 1] = 0;
@ -262,14 +272,14 @@ static int do_devconfig_ioctl(comedi_device *dev, comedi_devconfig *arg)
modified bufconfig at arg
*/
static int do_bufconfig_ioctl(comedi_device *dev, void *arg)
static int do_bufconfig_ioctl(struct comedi_device *dev, void *arg)
{
comedi_bufconfig bc;
comedi_async *async;
comedi_subdevice *s;
struct comedi_bufconfig bc;
struct comedi_async *async;
struct comedi_subdevice *s;
int ret = 0;
if (copy_from_user(&bc, arg, sizeof(comedi_bufconfig)))
if (copy_from_user(&bc, arg, sizeof(struct comedi_bufconfig)))
return -EFAULT;
if (bc.subdevice >= dev->n_subdevices || bc.subdevice < 0)
@ -330,7 +340,7 @@ static int do_bufconfig_ioctl(comedi_device *dev, void *arg)
bc.maximum_size = async->max_bufsize;
copyback:
if (copy_to_user(arg, &bc, sizeof(comedi_bufconfig)))
if (copy_to_user(arg, &bc, sizeof(struct comedi_bufconfig)))
return -EFAULT;
return 0;
@ -350,16 +360,16 @@ static int do_bufconfig_ioctl(comedi_device *dev, void *arg)
devinfo structure
*/
static int do_devinfo_ioctl(comedi_device *dev, comedi_devinfo *arg,
static int do_devinfo_ioctl(struct comedi_device *dev, struct comedi_devinfo *arg,
struct file *file)
{
comedi_devinfo devinfo;
struct comedi_devinfo devinfo;
const unsigned minor = iminor(file->f_dentry->d_inode);
struct comedi_device_file_info *dev_file_info =
comedi_get_device_file_info(minor);
comedi_subdevice *read_subdev =
struct comedi_subdevice *read_subdev =
comedi_get_read_subdevice(dev_file_info);
comedi_subdevice *write_subdev =
struct comedi_subdevice *write_subdev =
comedi_get_write_subdevice(dev_file_info);
memset(&devinfo, 0, sizeof(devinfo));
@ -380,7 +390,7 @@ static int do_devinfo_ioctl(comedi_device *dev, comedi_devinfo *arg,
else
devinfo.write_subdevice = -1;
if (copy_to_user(arg, &devinfo, sizeof(comedi_devinfo)))
if (copy_to_user(arg, &devinfo, sizeof(struct comedi_devinfo)))
return -EFAULT;
return 0;
@ -400,14 +410,14 @@ static int do_devinfo_ioctl(comedi_device *dev, comedi_devinfo *arg,
array of subdevice info structures at arg
*/
static int do_subdinfo_ioctl(comedi_device *dev, comedi_subdinfo *arg,
static int do_subdinfo_ioctl(struct comedi_device *dev, struct comedi_subdinfo *arg,
void *file)
{
int ret, i;
comedi_subdinfo *tmp, *us;
comedi_subdevice *s;
struct comedi_subdinfo *tmp, *us;
struct comedi_subdevice *s;
tmp = kcalloc(dev->n_subdevices, sizeof(comedi_subdinfo), GFP_KERNEL);
tmp = kcalloc(dev->n_subdevices, sizeof(struct comedi_subdinfo), GFP_KERNEL);
if (!tmp)
return -ENOMEM;
@ -459,7 +469,7 @@ static int do_subdinfo_ioctl(comedi_device *dev, comedi_subdinfo *arg,
}
ret = copy_to_user(arg, tmp,
dev->n_subdevices * sizeof(comedi_subdinfo));
dev->n_subdevices * sizeof(struct comedi_subdinfo));
kfree(tmp);
@ -480,12 +490,12 @@ static int do_subdinfo_ioctl(comedi_device *dev, comedi_subdinfo *arg,
arrays at elements of chaninfo structure
*/
static int do_chaninfo_ioctl(comedi_device *dev, comedi_chaninfo *arg)
static int do_chaninfo_ioctl(struct comedi_device *dev, struct comedi_chaninfo *arg)
{
comedi_subdevice *s;
comedi_chaninfo it;
struct comedi_subdevice *s;
struct comedi_chaninfo it;
if (copy_from_user(&it, arg, sizeof(comedi_chaninfo)))
if (copy_from_user(&it, arg, sizeof(struct comedi_chaninfo)))
return -EFAULT;
if (it.subdev >= dev->n_subdevices)
@ -496,7 +506,7 @@ static int do_chaninfo_ioctl(comedi_device *dev, comedi_chaninfo *arg)
if (s->maxdata || !s->maxdata_list)
return -EINVAL;
if (copy_to_user(it.maxdata_list, s->maxdata_list,
s->n_chan * sizeof(lsampl_t)))
s->n_chan * sizeof(unsigned int)))
return -EFAULT;
}
@ -544,13 +554,13 @@ static int do_chaninfo_ioctl(comedi_device *dev, comedi_chaninfo *arg)
modified bufinfo at arg
*/
static int do_bufinfo_ioctl(comedi_device *dev, void *arg)
static int do_bufinfo_ioctl(struct comedi_device *dev, void *arg)
{
comedi_bufinfo bi;
comedi_subdevice *s;
comedi_async *async;
struct comedi_bufinfo bi;
struct comedi_subdevice *s;
struct comedi_async *async;
if (copy_from_user(&bi, arg, sizeof(comedi_bufinfo)))
if (copy_from_user(&bi, arg, sizeof(struct comedi_bufinfo)))
return -EFAULT;
if (bi.subdevice >= dev->n_subdevices || bi.subdevice < 0)
@ -591,13 +601,13 @@ static int do_bufinfo_ioctl(comedi_device *dev, void *arg)
bi.buf_read_ptr = async->buf_read_ptr;
copyback:
if (copy_to_user(arg, &bi, sizeof(comedi_bufinfo)))
if (copy_to_user(arg, &bi, sizeof(struct comedi_bufinfo)))
return -EFAULT;
return 0;
}
static int parse_insn(comedi_device *dev, comedi_insn *insn, lsampl_t *data,
static int parse_insn(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data,
void *file);
/*
* COMEDI_INSNLIST
@ -616,25 +626,25 @@ static int parse_insn(comedi_device *dev, comedi_insn *insn, lsampl_t *data,
*/
/* arbitrary limits */
#define MAX_SAMPLES 256
static int do_insnlist_ioctl(comedi_device *dev, void *arg, void *file)
static int do_insnlist_ioctl(struct comedi_device *dev, void *arg, void *file)
{
comedi_insnlist insnlist;
comedi_insn *insns = NULL;
lsampl_t *data = NULL;
struct comedi_insnlist insnlist;
struct comedi_insn *insns = NULL;
unsigned int *data = NULL;
int i = 0;
int ret = 0;
if (copy_from_user(&insnlist, arg, sizeof(comedi_insnlist)))
if (copy_from_user(&insnlist, arg, sizeof(struct comedi_insnlist)))
return -EFAULT;
data = kmalloc(sizeof(lsampl_t) * MAX_SAMPLES, GFP_KERNEL);
data = kmalloc(sizeof(unsigned int) * MAX_SAMPLES, GFP_KERNEL);
if (!data) {
DPRINTK("kmalloc failed\n");
ret = -ENOMEM;
goto error;
}
insns = kmalloc(sizeof(comedi_insn) * insnlist.n_insns, GFP_KERNEL);
insns = kmalloc(sizeof(struct comedi_insn) * insnlist.n_insns, GFP_KERNEL);
if (!insns) {
DPRINTK("kmalloc failed\n");
ret = -ENOMEM;
@ -642,7 +652,7 @@ static int do_insnlist_ioctl(comedi_device *dev, void *arg, void *file)
}
if (copy_from_user(insns, insnlist.insns,
sizeof(comedi_insn) * insnlist.n_insns)) {
sizeof(struct comedi_insn) * insnlist.n_insns)) {
DPRINTK("copy_from_user failed\n");
ret = -EFAULT;
goto error;
@ -656,7 +666,7 @@ static int do_insnlist_ioctl(comedi_device *dev, void *arg, void *file)
}
if (insns[i].insn & INSN_MASK_WRITE) {
if (copy_from_user(data, insns[i].data,
insns[i].n * sizeof(lsampl_t))) {
insns[i].n * sizeof(unsigned int))) {
DPRINTK("copy_from_user failed\n");
ret = -EFAULT;
goto error;
@ -667,7 +677,7 @@ static int do_insnlist_ioctl(comedi_device *dev, void *arg, void *file)
goto error;
if (insns[i].insn & INSN_MASK_READ) {
if (copy_to_user(insns[i].data, data,
insns[i].n * sizeof(lsampl_t))) {
insns[i].n * sizeof(unsigned int))) {
DPRINTK("copy_to_user failed\n");
ret = -EFAULT;
goto error;
@ -686,7 +696,7 @@ static int do_insnlist_ioctl(comedi_device *dev, void *arg, void *file)
return i;
}
static int check_insn_config_length(comedi_insn *insn, lsampl_t *data)
static int check_insn_config_length(struct comedi_insn *insn, unsigned int *data)
{
if (insn->n < 1)
return -EINVAL;
@ -747,10 +757,10 @@ static int check_insn_config_length(comedi_insn *insn, lsampl_t *data)
return -EINVAL;
}
static int parse_insn(comedi_device *dev, comedi_insn *insn, lsampl_t *data,
static int parse_insn(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data,
void *file)
{
comedi_subdevice *s;
struct comedi_subdevice *s;
int ret = 0;
int i;
@ -815,7 +825,7 @@ static int parse_insn(comedi_device *dev, comedi_insn *insn, lsampl_t *data,
}
} else {
/* a subdevice instruction */
lsampl_t maxdata;
unsigned int maxdata;
if (insn->subdev >= dev->n_subdevices) {
DPRINTK("subdevice %d out of range\n", insn->subdev);
@ -901,25 +911,25 @@ static int parse_insn(comedi_device *dev, comedi_insn *insn, lsampl_t *data,
* pointer to insn
*
* reads:
* comedi_insn struct at arg
* struct comedi_insn struct at arg
* data (for writes)
*
* writes:
* data (for reads)
*/
static int do_insn_ioctl(comedi_device *dev, void *arg, void *file)
static int do_insn_ioctl(struct comedi_device *dev, void *arg, void *file)
{
comedi_insn insn;
lsampl_t *data = NULL;
struct comedi_insn insn;
unsigned int *data = NULL;
int ret = 0;
data = kmalloc(sizeof(lsampl_t) * MAX_SAMPLES, GFP_KERNEL);
data = kmalloc(sizeof(unsigned int) * MAX_SAMPLES, GFP_KERNEL);
if (!data) {
ret = -ENOMEM;
goto error;
}
if (copy_from_user(&insn, arg, sizeof(comedi_insn))) {
if (copy_from_user(&insn, arg, sizeof(struct comedi_insn))) {
ret = -EFAULT;
goto error;
}
@ -928,7 +938,7 @@ static int do_insn_ioctl(comedi_device *dev, void *arg, void *file)
if (insn.n > MAX_SAMPLES)
insn.n = MAX_SAMPLES;
if (insn.insn & INSN_MASK_WRITE) {
if (copy_from_user(data, insn.data, insn.n * sizeof(lsampl_t))) {
if (copy_from_user(data, insn.data, insn.n * sizeof(unsigned int))) {
ret = -EFAULT;
goto error;
}
@ -937,7 +947,7 @@ static int do_insn_ioctl(comedi_device *dev, void *arg, void *file)
if (ret < 0)
goto error;
if (insn.insn & INSN_MASK_READ) {
if (copy_to_user(insn.data, data, insn.n * sizeof(lsampl_t))) {
if (copy_to_user(insn.data, data, insn.n * sizeof(unsigned int))) {
ret = -EFAULT;
goto error;
}
@ -965,15 +975,15 @@ static int do_insn_ioctl(comedi_device *dev, void *arg, void *file)
modified cmd structure at arg
*/
static int do_cmd_ioctl(comedi_device *dev, void *arg, void *file)
static int do_cmd_ioctl(struct comedi_device *dev, void *arg, void *file)
{
comedi_cmd user_cmd;
comedi_subdevice *s;
comedi_async *async;
struct comedi_cmd user_cmd;
struct comedi_subdevice *s;
struct comedi_async *async;
int ret = 0;
unsigned int *chanlist_saver = NULL;
if (copy_from_user(&user_cmd, arg, sizeof(comedi_cmd))) {
if (copy_from_user(&user_cmd, arg, sizeof(struct comedi_cmd))) {
DPRINTK("bad cmd address\n");
return -EFAULT;
}
@ -1062,7 +1072,7 @@ static int do_cmd_ioctl(comedi_device *dev, void *arg, void *file)
/* restore chanlist pointer before copying back */
user_cmd.chanlist = chanlist_saver;
user_cmd.data = NULL;
if (copy_to_user(arg, &user_cmd, sizeof(comedi_cmd))) {
if (copy_to_user(arg, &user_cmd, sizeof(struct comedi_cmd))) {
DPRINTK("fault writing cmd\n");
ret = -EFAULT;
goto cleanup;
@ -1119,15 +1129,15 @@ static int do_cmd_ioctl(comedi_device *dev, void *arg, void *file)
modified cmd structure at arg
*/
static int do_cmdtest_ioctl(comedi_device *dev, void *arg, void *file)
static int do_cmdtest_ioctl(struct comedi_device *dev, void *arg, void *file)
{
comedi_cmd user_cmd;
comedi_subdevice *s;
struct comedi_cmd user_cmd;
struct comedi_subdevice *s;
int ret = 0;
unsigned int *chanlist = NULL;
unsigned int *chanlist_saver = NULL;
if (copy_from_user(&user_cmd, arg, sizeof(comedi_cmd))) {
if (copy_from_user(&user_cmd, arg, sizeof(struct comedi_cmd))) {
DPRINTK("bad cmd address\n");
return -EFAULT;
}
@ -1191,7 +1201,7 @@ static int do_cmdtest_ioctl(comedi_device *dev, void *arg, void *file)
/* restore chanlist pointer before copying back */
user_cmd.chanlist = chanlist_saver;
if (copy_to_user(arg, &user_cmd, sizeof(comedi_cmd))) {
if (copy_to_user(arg, &user_cmd, sizeof(struct comedi_cmd))) {
DPRINTK("bad cmd address\n");
ret = -EFAULT;
goto cleanup;
@ -1217,11 +1227,11 @@ static int do_cmdtest_ioctl(comedi_device *dev, void *arg, void *file)
*/
static int do_lock_ioctl(comedi_device *dev, unsigned int arg, void *file)
static int do_lock_ioctl(struct comedi_device *dev, unsigned int arg, void *file)
{
int ret = 0;
unsigned long flags;
comedi_subdevice *s;
struct comedi_subdevice *s;
if (arg >= dev->n_subdevices)
return -EINVAL;
@ -1261,9 +1271,9 @@ static int do_lock_ioctl(comedi_device *dev, unsigned int arg, void *file)
This function isn't protected by the semaphore, since
we already own the lock.
*/
static int do_unlock_ioctl(comedi_device *dev, unsigned int arg, void *file)
static int do_unlock_ioctl(struct comedi_device *dev, unsigned int arg, void *file)
{
comedi_subdevice *s;
struct comedi_subdevice *s;
if (arg >= dev->n_subdevices)
return -EINVAL;
@ -1301,9 +1311,9 @@ static int do_unlock_ioctl(comedi_device *dev, unsigned int arg, void *file)
nothing
*/
static int do_cancel_ioctl(comedi_device *dev, unsigned int arg, void *file)
static int do_cancel_ioctl(struct comedi_device *dev, unsigned int arg, void *file)
{
comedi_subdevice *s;
struct comedi_subdevice *s;
if (arg >= dev->n_subdevices)
return -EINVAL;
@ -1337,9 +1347,9 @@ static int do_cancel_ioctl(comedi_device *dev, unsigned int arg, void *file)
nothing
*/
static int do_poll_ioctl(comedi_device *dev, unsigned int arg, void *file)
static int do_poll_ioctl(struct comedi_device *dev, unsigned int arg, void *file)
{
comedi_subdevice *s;
struct comedi_subdevice *s;
if (arg >= dev->n_subdevices)
return -EINVAL;
@ -1360,7 +1370,7 @@ static int do_poll_ioctl(comedi_device *dev, unsigned int arg, void *file)
return -EINVAL;
}
static int do_cancel(comedi_device *dev, comedi_subdevice *s)
static int do_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
{
int ret = 0;
@ -1374,8 +1384,8 @@ static int do_cancel(comedi_device *dev, comedi_subdevice *s)
void comedi_unmap(struct vm_area_struct *area)
{
comedi_async *async;
comedi_device *dev;
struct comedi_async *async;
struct comedi_device *dev;
async = area->vm_private_data;
dev = async->subdevice->device;
@ -1394,14 +1404,14 @@ static int comedi_mmap(struct file *file, struct vm_area_struct *vma)
const unsigned minor = iminor(file->f_dentry->d_inode);
struct comedi_device_file_info *dev_file_info =
comedi_get_device_file_info(minor);
comedi_device *dev = dev_file_info->device;
comedi_async *async = NULL;
struct comedi_device *dev = dev_file_info->device;
struct comedi_async *async = NULL;
unsigned long start = vma->vm_start;
unsigned long size;
int n_pages;
int i;
int retval;
comedi_subdevice *s;
struct comedi_subdevice *s;
mutex_lock(&dev->mutex);
if (!dev->attached) {
@ -1470,9 +1480,9 @@ static unsigned int comedi_poll(struct file *file, poll_table *wait)
const unsigned minor = iminor(file->f_dentry->d_inode);
struct comedi_device_file_info *dev_file_info =
comedi_get_device_file_info(minor);
comedi_device *dev = dev_file_info->device;
comedi_subdevice *read_subdev;
comedi_subdevice *write_subdev;
struct comedi_device *dev = dev_file_info->device;
struct comedi_subdevice *read_subdev;
struct comedi_subdevice *write_subdev;
mutex_lock(&dev->mutex);
if (!dev->attached) {
@ -1513,14 +1523,14 @@ static unsigned int comedi_poll(struct file *file, poll_table *wait)
static ssize_t comedi_write(struct file *file, const char *buf, size_t nbytes,
loff_t *offset)
{
comedi_subdevice *s;
comedi_async *async;
struct comedi_subdevice *s;
struct comedi_async *async;
int n, m, count = 0, retval = 0;
DECLARE_WAITQUEUE(wait, current);
const unsigned minor = iminor(file->f_dentry->d_inode);
struct comedi_device_file_info *dev_file_info =
comedi_get_device_file_info(minor);
comedi_device *dev = dev_file_info->device;
struct comedi_device *dev = dev_file_info->device;
if (!dev->attached) {
DPRINTK("no driver configured on comedi%i\n", dev->minor);
@ -1615,14 +1625,14 @@ static ssize_t comedi_write(struct file *file, const char *buf, size_t nbytes,
static ssize_t comedi_read(struct file *file, char *buf, size_t nbytes,
loff_t *offset)
{
comedi_subdevice *s;
comedi_async *async;
struct comedi_subdevice *s;
struct comedi_async *async;
int n, m, count = 0, retval = 0;
DECLARE_WAITQUEUE(wait, current);
const unsigned minor = iminor(file->f_dentry->d_inode);
struct comedi_device_file_info *dev_file_info =
comedi_get_device_file_info(minor);
comedi_device *dev = dev_file_info->device;
struct comedi_device *dev = dev_file_info->device;
if (!dev->attached) {
DPRINTK("no driver configured on comedi%i\n", dev->minor);
@ -1723,9 +1733,9 @@ static ssize_t comedi_read(struct file *file, char *buf, size_t nbytes,
/*
This function restores a subdevice to an idle state.
*/
void do_become_nonbusy(comedi_device *dev, comedi_subdevice *s)
void do_become_nonbusy(struct comedi_device *dev, struct comedi_subdevice *s)
{
comedi_async *async = s->async;
struct comedi_async *async = s->async;
comedi_set_subdevice_runflags(s, SRF_RUNNING, 0);
#ifdef CONFIG_COMEDI_RT
@ -1747,11 +1757,11 @@ void do_become_nonbusy(comedi_device *dev, comedi_subdevice *s)
static int comedi_open(struct inode *inode, struct file *file)
{
char mod[32];
const unsigned minor = iminor(inode);
struct comedi_device_file_info *dev_file_info =
comedi_get_device_file_info(minor);
comedi_device *dev = dev_file_info->device;
struct comedi_device *dev = dev_file_info ? dev_file_info->device : NULL;
if (dev == NULL) {
DPRINTK("invalid minor number\n");
return -ENODEV;
@ -1783,10 +1793,9 @@ static int comedi_open(struct inode *inode, struct file *file)
dev->in_request_module = 1;
sprintf(mod, "char-major-%i-%i", COMEDI_MAJOR, dev->minor);
#ifdef CONFIG_KMOD
mutex_unlock(&dev->mutex);
request_module(mod);
request_module("char-major-%i-%i", COMEDI_MAJOR, dev->minor);
mutex_lock(&dev->mutex);
#endif
@ -1823,8 +1832,8 @@ static int comedi_close(struct inode *inode, struct file *file)
const unsigned minor = iminor(inode);
struct comedi_device_file_info *dev_file_info =
comedi_get_device_file_info(minor);
comedi_device *dev = dev_file_info->device;
comedi_subdevice *s = NULL;
struct comedi_device *dev = dev_file_info->device;
struct comedi_subdevice *s = NULL;
int i;
mutex_lock(&dev->mutex);
@ -1862,7 +1871,7 @@ static int comedi_fasync(int fd, struct file *file, int on)
struct comedi_device_file_info *dev_file_info =
comedi_get_device_file_info(minor);
comedi_device *dev = dev_file_info->device;
struct comedi_device *dev = dev_file_info->device;
return fasync_helper(fd, file, on, &dev->async_queue);
}
@ -1893,7 +1902,7 @@ static void comedi_cleanup_legacy_minors(void)
{
unsigned i;
for (i = 0; i < COMEDI_NUM_LEGACY_MINORS; i++)
for (i = 0; i < comedi_num_legacy_minors; i++)
comedi_free_board_minor(i);
}
@ -1905,6 +1914,22 @@ static int __init comedi_init(void)
printk(KERN_INFO "comedi: version " COMEDI_RELEASE
" - http://www.comedi.org\n");
if (comedi_num_legacy_minors < 0 ||
comedi_num_legacy_minors > COMEDI_NUM_BOARD_MINORS) {
printk(KERN_ERR "comedi: error: invalid value for module "
"parameter \"comedi_num_legacy_minors\". Valid values "
"are 0 through %i.\n", COMEDI_NUM_BOARD_MINORS);
return -EINVAL;
}
/*
* comedi is unusable if both comedi_autoconfig and
* comedi_num_legacy_minors are zero, so we might as well adjust the
* defaults in that case
*/
if (comedi_autoconfig == 0 && comedi_num_legacy_minors == 0)
comedi_num_legacy_minors = 16;
memset(comedi_file_info_table, 0,
sizeof(struct comedi_device_file_info *) * COMEDI_NUM_MINORS);
@ -1933,7 +1958,7 @@ static int __init comedi_init(void)
comedi_proc_init();
/* create devices files for legacy/manual use */
for (i = 0; i < COMEDI_NUM_LEGACY_MINORS; i++) {
for (i = 0; i < comedi_num_legacy_minors; i++) {
int minor;
minor = comedi_alloc_board_minor(NULL);
if (minor < 0) {
@ -1975,15 +2000,15 @@ static void __exit comedi_cleanup(void)
module_init(comedi_init);
module_exit(comedi_cleanup);
void comedi_error(const comedi_device *dev, const char *s)
void comedi_error(const struct comedi_device *dev, const char *s)
{
rt_printk("comedi%d: %s: %s\n", dev->minor, dev->driver->driver_name,
s);
}
void comedi_event(comedi_device *dev, comedi_subdevice *s)
void comedi_event(struct comedi_device *dev, struct comedi_subdevice *s)
{
comedi_async *async = s->async;
struct comedi_async *async = s->async;
unsigned runflags = 0;
unsigned runflags_mask = 0;
@ -2042,7 +2067,7 @@ void comedi_event(comedi_device *dev, comedi_subdevice *s)
s->async->events = 0;
}
void comedi_set_subdevice_runflags(comedi_subdevice *s, unsigned mask,
void comedi_set_subdevice_runflags(struct comedi_subdevice *s, unsigned mask,
unsigned bits)
{
unsigned long flags;
@ -2053,7 +2078,7 @@ void comedi_set_subdevice_runflags(comedi_subdevice *s, unsigned mask,
comedi_spin_unlock_irqrestore(&s->spin_lock, flags);
}
unsigned comedi_get_subdevice_runflags(comedi_subdevice *s)
unsigned comedi_get_subdevice_runflags(struct comedi_subdevice *s)
{
unsigned long flags;
unsigned runflags;
@ -2064,9 +2089,9 @@ unsigned comedi_get_subdevice_runflags(comedi_subdevice *s)
return runflags;
}
static int is_device_busy(comedi_device *dev)
static int is_device_busy(struct comedi_device *dev)
{
comedi_subdevice *s;
struct comedi_subdevice *s;
int i;
if (!dev->attached)
@ -2083,15 +2108,15 @@ static int is_device_busy(comedi_device *dev)
return 0;
}
void comedi_device_init(comedi_device *dev)
void comedi_device_init(struct comedi_device *dev)
{
memset(dev, 0, sizeof(comedi_device));
memset(dev, 0, sizeof(struct comedi_device));
spin_lock_init(&dev->spinlock);
mutex_init(&dev->mutex);
dev->minor = -1;
}
void comedi_device_cleanup(comedi_device *dev)
void comedi_device_cleanup(struct comedi_device *dev)
{
if (dev == NULL)
return;
@ -2105,13 +2130,13 @@ int comedi_alloc_board_minor(struct device *hardware_device)
{
unsigned long flags;
struct comedi_device_file_info *info;
device_create_result_type *csdev;
struct device *csdev;
unsigned i;
info = kzalloc(sizeof(struct comedi_device_file_info), GFP_KERNEL);
if (info == NULL)
return -ENOMEM;
info->device = kzalloc(sizeof(comedi_device), GFP_KERNEL);
info->device = kzalloc(sizeof(struct comedi_device), GFP_KERNEL);
if (info->device == NULL) {
kfree(info);
return -ENOMEM;
@ -2155,7 +2180,7 @@ void comedi_free_board_minor(unsigned minor)
comedi_spin_unlock_irqrestore(&comedi_file_info_table_lock, flags);
if (info) {
comedi_device *dev = info->device;
struct comedi_device *dev = info->device;
if (dev) {
if (dev->class_dev) {
device_destroy(comedi_class,
@ -2168,11 +2193,11 @@ void comedi_free_board_minor(unsigned minor)
}
}
int comedi_alloc_subdevice_minor(comedi_device *dev, comedi_subdevice *s)
int comedi_alloc_subdevice_minor(struct comedi_device *dev, struct comedi_subdevice *s)
{
unsigned long flags;
struct comedi_device_file_info *info;
device_create_result_type *csdev;
struct device *csdev;
unsigned i;
info = kmalloc(sizeof(struct comedi_device_file_info), GFP_KERNEL);
@ -2182,7 +2207,7 @@ int comedi_alloc_subdevice_minor(comedi_device *dev, comedi_subdevice *s)
info->read_subdevice = s;
info->write_subdevice = s;
comedi_spin_lock_irqsave(&comedi_file_info_table_lock, flags);
for (i = COMEDI_FIRST_SUBDEVICE_MINOR; i < COMEDI_NUM_BOARD_MINORS; ++i) {
for (i = COMEDI_FIRST_SUBDEVICE_MINOR; i < COMEDI_NUM_MINORS; ++i) {
if (comedi_file_info_table[i] == NULL) {
comedi_file_info_table[i] = info;
break;
@ -2206,7 +2231,7 @@ int comedi_alloc_subdevice_minor(comedi_device *dev, comedi_subdevice *s)
return i;
}
void comedi_free_subdevice_minor(comedi_subdevice *s)
void comedi_free_subdevice_minor(struct comedi_subdevice *s)
{
unsigned long flags;
struct comedi_device_file_info *info;

View file

@ -4,5 +4,6 @@
extern struct class *comedi_class;
extern const struct file_operations comedi_fops;
extern int comedi_autoconfig;
#endif /* _COMEDI_FOPS_H */

View file

@ -31,12 +31,12 @@
/* for drivers */
EXPORT_SYMBOL(comedi_driver_register);
EXPORT_SYMBOL(comedi_driver_unregister);
//EXPORT_SYMBOL(comedi_bufcheck);
//EXPORT_SYMBOL(comedi_done);
//EXPORT_SYMBOL(comedi_error_done);
/* EXPORT_SYMBOL(comedi_bufcheck); */
/* EXPORT_SYMBOL(comedi_done); */
/* EXPORT_SYMBOL(comedi_error_done); */
EXPORT_SYMBOL(comedi_error);
//EXPORT_SYMBOL(comedi_eobuf);
//EXPORT_SYMBOL(comedi_eos);
/* EXPORT_SYMBOL(comedi_eobuf); */
/* EXPORT_SYMBOL(comedi_eos); */
EXPORT_SYMBOL(comedi_event);
EXPORT_SYMBOL(comedi_get_subdevice_runflags);
EXPORT_SYMBOL(comedi_set_subdevice_runflags);
@ -60,6 +60,8 @@ EXPORT_SYMBOL_GPL(comedi_alloc_board_minor);
EXPORT_SYMBOL_GPL(comedi_free_board_minor);
EXPORT_SYMBOL_GPL(comedi_pci_auto_config);
EXPORT_SYMBOL_GPL(comedi_pci_auto_unconfig);
EXPORT_SYMBOL_GPL(comedi_usb_auto_config);
EXPORT_SYMBOL_GPL(comedi_usb_auto_unconfig);
/* for kcomedilib */
EXPORT_SYMBOL(check_chanlist);

View file

@ -28,7 +28,6 @@
#error comedi_rt.h should only be included by comedidev.h
#endif
#include <linux/version.h>
#include <linux/kdev_t.h>
#include <linux/slab.h>
#include <linux/errno.h>
@ -59,12 +58,12 @@
int comedi_request_irq(unsigned int irq, irqreturn_t(*handler) (int,
void *PT_REGS_ARG), unsigned long flags, const char *device,
comedi_device *dev_id);
void comedi_free_irq(unsigned int irq, comedi_device *dev_id);
struct comedi_device *dev_id);
void comedi_free_irq(unsigned int irq, struct comedi_device *dev_id);
void comedi_rt_init(void);
void comedi_rt_cleanup(void);
int comedi_switch_to_rt(comedi_device *dev);
void comedi_switch_to_non_rt(comedi_device *dev);
int comedi_switch_to_rt(struct comedi_device *dev);
void comedi_switch_to_non_rt(struct comedi_device *dev);
void comedi_rt_pend_wakeup(wait_queue_head_t *q);
extern int rt_pend_call(void (*func) (int arg1, void *arg2), int arg1,
void *arg2);

View file

@ -26,7 +26,6 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/version.h>
#include <linux/kdev_t.h>
#include <linux/slab.h>
#include <linux/errno.h>
@ -36,7 +35,6 @@
#include <linux/mm.h>
#include <linux/init.h>
#include <linux/vmalloc.h>
#include <linux/mm.h>
#include "interrupt.h"
#include <linux/dma-mapping.h>
#include <linux/uaccess.h>
@ -55,9 +53,9 @@
#define COMEDI_INITCLEANUP_NOMODULE(x) \
static int __init x ## _init_module(void) \
{return comedi_driver_register(&(x));} \
{return comedi_driver_register(&(x)); } \
static void __exit x ## _cleanup_module(void) \
{comedi_driver_unregister(&(x));} \
{comedi_driver_unregister(&(x)); } \
module_init(x ## _init_module); \
module_exit(x ## _cleanup_module); \
@ -120,23 +118,14 @@
#define PCI_VENDOR_ID_MEILHAUS 0x1402
#define COMEDI_NUM_MINORS 0x100
#define COMEDI_NUM_LEGACY_MINORS 0x10
#define COMEDI_NUM_BOARD_MINORS 0x30
#define COMEDI_FIRST_SUBDEVICE_MINOR COMEDI_NUM_BOARD_MINORS
typedef struct comedi_device_struct comedi_device;
typedef struct comedi_subdevice_struct comedi_subdevice;
typedef struct comedi_async_struct comedi_async;
typedef struct comedi_driver_struct comedi_driver;
typedef struct comedi_lrange_struct comedi_lrange;
typedef struct device device_create_result_type;
#define COMEDI_DEVICE_CREATE(cs, parent, devt, drvdata, device, fmt...) \
device_create(cs, ((parent) ? (parent) : (device)), devt, drvdata, fmt)
struct comedi_subdevice_struct {
comedi_device *device;
struct comedi_subdevice {
struct comedi_device *device;
int type;
int n_chan;
volatile int subdev_flags;
@ -144,7 +133,7 @@ struct comedi_subdevice_struct {
void *private;
comedi_async *async;
struct comedi_async *async;
void *lock;
void *busy;
@ -153,46 +142,46 @@ struct comedi_subdevice_struct {
int io_bits;
lsampl_t maxdata; /* if maxdata==0, use list */
const lsampl_t *maxdata_list; /* list is channel specific */
unsigned int maxdata; /* if maxdata==0, use list */
const unsigned int *maxdata_list; /* list is channel specific */
unsigned int flags;
const unsigned int *flaglist;
unsigned int settling_time_0;
const comedi_lrange *range_table;
const comedi_lrange *const *range_table_list;
const struct comedi_lrange *range_table;
const struct comedi_lrange *const *range_table_list;
unsigned int *chanlist; /* driver-owned chanlist (not used) */
int (*insn_read) (comedi_device *, comedi_subdevice *, comedi_insn *,
lsampl_t *);
int (*insn_write) (comedi_device *, comedi_subdevice *, comedi_insn *,
lsampl_t *);
int (*insn_bits) (comedi_device *, comedi_subdevice *, comedi_insn *,
lsampl_t *);
int (*insn_config) (comedi_device *, comedi_subdevice *, comedi_insn *,
lsampl_t *);
int (*insn_read) (struct comedi_device *, struct comedi_subdevice *, struct comedi_insn *,
unsigned int *);
int (*insn_write) (struct comedi_device *, struct comedi_subdevice *, struct comedi_insn *,
unsigned int *);
int (*insn_bits) (struct comedi_device *, struct comedi_subdevice *, struct comedi_insn *,
unsigned int *);
int (*insn_config) (struct comedi_device *, struct comedi_subdevice *, struct comedi_insn *,
unsigned int *);
int (*do_cmd) (comedi_device *, comedi_subdevice *);
int (*do_cmdtest) (comedi_device *, comedi_subdevice *, comedi_cmd *);
int (*poll) (comedi_device *, comedi_subdevice *);
int (*cancel) (comedi_device *, comedi_subdevice *);
/* int (*do_lock)(comedi_device *,comedi_subdevice *); */
/* int (*do_unlock)(comedi_device *,comedi_subdevice *); */
int (*do_cmd) (struct comedi_device *, struct comedi_subdevice *);
int (*do_cmdtest) (struct comedi_device *, struct comedi_subdevice *, struct comedi_cmd *);
int (*poll) (struct comedi_device *, struct comedi_subdevice *);
int (*cancel) (struct comedi_device *, struct comedi_subdevice *);
/* int (*do_lock)(struct comedi_device *,struct comedi_subdevice *); */
/* int (*do_unlock)(struct comedi_device *,struct comedi_subdevice *); */
/* called when the buffer changes */
int (*buf_change) (comedi_device *dev, comedi_subdevice *s,
int (*buf_change) (struct comedi_device *dev, struct comedi_subdevice *s,
unsigned long new_size);
void (*munge) (comedi_device *dev, comedi_subdevice *s, void *data,
void (*munge) (struct comedi_device *dev, struct comedi_subdevice *s, void *data,
unsigned int num_bytes, unsigned int start_chan_index);
enum dma_data_direction async_dma_dir;
unsigned int state;
device_create_result_type *class_dev;
struct device *class_dev;
int minor;
};
@ -201,8 +190,8 @@ struct comedi_buf_page {
dma_addr_t dma_addr;
};
struct comedi_async_struct {
comedi_subdevice *subdevice;
struct comedi_async {
struct comedi_subdevice *subdevice;
void *prealloc_buf; /* pre-allocated buffer */
unsigned int prealloc_bufsz; /* buffer size, in bytes */
@ -232,7 +221,7 @@ struct comedi_async_struct {
unsigned int events; /* events that have occurred */
comedi_cmd cmd;
struct comedi_cmd cmd;
wait_queue_head_t wait_head;
@ -241,17 +230,17 @@ struct comedi_async_struct {
int (*cb_func) (unsigned int flags, void *);
void *cb_arg;
int (*inttrig) (comedi_device *dev, comedi_subdevice *s,
int (*inttrig) (struct comedi_device *dev, struct comedi_subdevice *s,
unsigned int x);
};
struct comedi_driver_struct {
struct comedi_driver_struct *next;
struct comedi_driver {
struct comedi_driver *next;
const char *driver_name;
struct module *module;
int (*attach) (comedi_device *, comedi_devconfig *);
int (*detach) (comedi_device *);
int (*attach) (struct comedi_device *, struct comedi_devconfig *);
int (*detach) (struct comedi_device *);
/* number of elements in board_name and board_id arrays */
unsigned int num_names;
@ -260,12 +249,12 @@ struct comedi_driver_struct {
int offset;
};
struct comedi_device_struct {
struct comedi_device {
int use_count;
comedi_driver *driver;
struct comedi_driver *driver;
void *private;
device_create_result_type *class_dev;
struct device *class_dev;
int minor;
/* hw_dev is passed to dma_alloc_coherent when allocating async buffers
* for subdevices that have async_dma_dir set to something other than
@ -281,25 +270,25 @@ struct comedi_device_struct {
int in_request_module;
int n_subdevices;
comedi_subdevice *subdevices;
struct comedi_subdevice *subdevices;
/* dumb */
unsigned long iobase;
unsigned int irq;
comedi_subdevice *read_subdev;
comedi_subdevice *write_subdev;
struct comedi_subdevice *read_subdev;
struct comedi_subdevice *write_subdev;
struct fasync_struct *async_queue;
void (*open) (comedi_device *dev);
void (*close) (comedi_device *dev);
void (*open) (struct comedi_device *dev);
void (*close) (struct comedi_device *dev);
};
struct comedi_device_file_info {
comedi_device *device;
comedi_subdevice *read_subdevice;
comedi_subdevice *write_subdevice;
struct comedi_device *device;
struct comedi_subdevice *read_subdevice;
struct comedi_subdevice *write_subdevice;
};
#ifdef CONFIG_COMEDI_DEBUG
@ -312,8 +301,8 @@ static const int comedi_debug;
* function prototypes
*/
void comedi_event(comedi_device *dev, comedi_subdevice *s);
void comedi_error(const comedi_device *dev, const char *s);
void comedi_event(struct comedi_device *dev, struct comedi_subdevice *s);
void comedi_error(const struct comedi_device *dev, const char *s);
/* we can expand the number of bits used to encode devices/subdevices into
the minor number soon, after more distros support > 8 bit minor numbers
@ -327,7 +316,7 @@ static const unsigned COMEDI_SUBDEVICE_MINOR_OFFSET = 1;
struct comedi_device_file_info *comedi_get_device_file_info(unsigned minor);
static inline comedi_subdevice *comedi_get_read_subdevice(
static inline struct comedi_subdevice *comedi_get_read_subdevice(
const struct comedi_device_file_info *info)
{
if (info->read_subdevice)
@ -337,7 +326,7 @@ static inline comedi_subdevice *comedi_get_read_subdevice(
return info->device->read_subdev;
}
static inline comedi_subdevice *comedi_get_write_subdevice(
static inline struct comedi_subdevice *comedi_get_write_subdevice(
const struct comedi_device_file_info *info)
{
if (info->write_subdevice)
@ -347,17 +336,17 @@ static inline comedi_subdevice *comedi_get_write_subdevice(
return info->device->write_subdev;
}
void comedi_device_detach(comedi_device *dev);
int comedi_device_attach(comedi_device *dev, comedi_devconfig *it);
int comedi_driver_register(comedi_driver *);
int comedi_driver_unregister(comedi_driver *);
void comedi_device_detach(struct comedi_device *dev);
int comedi_device_attach(struct comedi_device *dev, struct comedi_devconfig *it);
int comedi_driver_register(struct comedi_driver *);
int comedi_driver_unregister(struct comedi_driver *);
void init_polling(void);
void cleanup_polling(void);
void start_polling(comedi_device *);
void stop_polling(comedi_device *);
void start_polling(struct comedi_device *);
void stop_polling(struct comedi_device *);
int comedi_buf_alloc(comedi_device *dev, comedi_subdevice *s, unsigned long
int comedi_buf_alloc(struct comedi_device *dev, struct comedi_subdevice *s, unsigned long
new_size);
#ifdef CONFIG_PROC_FS
@ -386,13 +375,13 @@ enum subdevice_runflags {
various internal comedi functions
*/
int do_rangeinfo_ioctl(comedi_device *dev, comedi_rangeinfo *arg);
int check_chanlist(comedi_subdevice *s, int n, unsigned int *chanlist);
void comedi_set_subdevice_runflags(comedi_subdevice *s, unsigned mask,
int do_rangeinfo_ioctl(struct comedi_device *dev, struct comedi_rangeinfo *arg);
int check_chanlist(struct comedi_subdevice *s, int n, unsigned int *chanlist);
void comedi_set_subdevice_runflags(struct comedi_subdevice *s, unsigned mask,
unsigned bits);
unsigned comedi_get_subdevice_runflags(comedi_subdevice *s);
int insn_inval(comedi_device *dev, comedi_subdevice *s,
comedi_insn *insn, lsampl_t *data);
unsigned comedi_get_subdevice_runflags(struct comedi_subdevice *s);
int insn_inval(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
/* range stuff */
@ -403,12 +392,12 @@ int insn_inval(comedi_device *dev, comedi_subdevice *s,
#define BIP_RANGE(a) {-(a)*1e6, (a)*1e6, 0}
#define UNI_RANGE(a) {0, (a)*1e6, 0}
extern const comedi_lrange range_bipolar10;
extern const comedi_lrange range_bipolar5;
extern const comedi_lrange range_bipolar2_5;
extern const comedi_lrange range_unipolar10;
extern const comedi_lrange range_unipolar5;
extern const comedi_lrange range_unknown;
extern const struct comedi_lrange range_bipolar10;
extern const struct comedi_lrange range_bipolar5;
extern const struct comedi_lrange range_bipolar2_5;
extern const struct comedi_lrange range_unipolar10;
extern const struct comedi_lrange range_unipolar5;
extern const struct comedi_lrange range_unknown;
#define range_digital range_unipolar5
@ -418,21 +407,21 @@ extern const comedi_lrange range_unknown;
#define GCC_ZERO_LENGTH_ARRAY 0
#endif
struct comedi_lrange_struct {
struct comedi_lrange {
int length;
comedi_krange range[GCC_ZERO_LENGTH_ARRAY];
struct comedi_krange range[GCC_ZERO_LENGTH_ARRAY];
};
/* some silly little inline functions */
static inline int alloc_subdevices(comedi_device *dev,
static inline int alloc_subdevices(struct comedi_device *dev,
unsigned int num_subdevices)
{
unsigned i;
dev->n_subdevices = num_subdevices;
dev->subdevices =
kcalloc(num_subdevices, sizeof(comedi_subdevice), GFP_KERNEL);
kcalloc(num_subdevices, sizeof(struct comedi_subdevice), GFP_KERNEL);
if (!dev->subdevices)
return -ENOMEM;
for (i = 0; i < num_subdevices; ++i) {
@ -444,7 +433,7 @@ static inline int alloc_subdevices(comedi_device *dev,
return 0;
}
static inline int alloc_private(comedi_device *dev, int size)
static inline int alloc_private(struct comedi_device *dev, int size)
{
dev->private = kzalloc(size, GFP_KERNEL);
if (!dev->private)
@ -452,17 +441,17 @@ static inline int alloc_private(comedi_device *dev, int size)
return 0;
}
static inline unsigned int bytes_per_sample(const comedi_subdevice *subd)
static inline unsigned int bytes_per_sample(const struct comedi_subdevice *subd)
{
if (subd->subdev_flags & SDF_LSAMPL)
return sizeof(lsampl_t);
return sizeof(unsigned int);
else
return sizeof(sampl_t);
return sizeof(short);
}
/* must be used in attach to set dev->hw_dev if you wish to dma directly
into comedi's buffer */
static inline void comedi_set_hw_dev(comedi_device *dev, struct device *hw_dev)
static inline void comedi_set_hw_dev(struct comedi_device *dev, struct device *hw_dev)
{
if (dev->hw_dev)
put_device(dev->hw_dev);
@ -474,31 +463,31 @@ static inline void comedi_set_hw_dev(comedi_device *dev, struct device *hw_dev)
}
}
int comedi_buf_put(comedi_async *async, sampl_t x);
int comedi_buf_get(comedi_async *async, sampl_t *x);
int comedi_buf_put(struct comedi_async *async, short x);
int comedi_buf_get(struct comedi_async *async, short *x);
unsigned int comedi_buf_write_n_available(comedi_async *async);
unsigned int comedi_buf_write_alloc(comedi_async *async, unsigned int nbytes);
unsigned int comedi_buf_write_alloc_strict(comedi_async *async,
unsigned int comedi_buf_write_n_available(struct comedi_async *async);
unsigned int comedi_buf_write_alloc(struct comedi_async *async, unsigned int nbytes);
unsigned int comedi_buf_write_alloc_strict(struct comedi_async *async,
unsigned int nbytes);
unsigned comedi_buf_write_free(comedi_async *async, unsigned int nbytes);
unsigned comedi_buf_read_alloc(comedi_async *async, unsigned nbytes);
unsigned comedi_buf_read_free(comedi_async *async, unsigned int nbytes);
unsigned int comedi_buf_read_n_available(comedi_async *async);
void comedi_buf_memcpy_to(comedi_async *async, unsigned int offset,
unsigned comedi_buf_write_free(struct comedi_async *async, unsigned int nbytes);
unsigned comedi_buf_read_alloc(struct comedi_async *async, unsigned nbytes);
unsigned comedi_buf_read_free(struct comedi_async *async, unsigned int nbytes);
unsigned int comedi_buf_read_n_available(struct comedi_async *async);
void comedi_buf_memcpy_to(struct comedi_async *async, unsigned int offset,
const void *source, unsigned int num_bytes);
void comedi_buf_memcpy_from(comedi_async *async, unsigned int offset,
void comedi_buf_memcpy_from(struct comedi_async *async, unsigned int offset,
void *destination, unsigned int num_bytes);
static inline unsigned comedi_buf_write_n_allocated(comedi_async *async)
static inline unsigned comedi_buf_write_n_allocated(struct comedi_async *async)
{
return async->buf_write_alloc_count - async->buf_write_count;
}
static inline unsigned comedi_buf_read_n_allocated(comedi_async *async)
static inline unsigned comedi_buf_read_n_allocated(struct comedi_async *async)
{
return async->buf_read_alloc_count - async->buf_read_count;
}
void comedi_reset_async_buf(comedi_async *async);
void comedi_reset_async_buf(struct comedi_async *async);
static inline void *comedi_aux_data(int options[], int n)
{
@ -527,10 +516,13 @@ static inline void *comedi_aux_data(int options[], int n)
int comedi_alloc_board_minor(struct device *hardware_device);
void comedi_free_board_minor(unsigned minor);
int comedi_alloc_subdevice_minor(comedi_device *dev, comedi_subdevice *s);
void comedi_free_subdevice_minor(comedi_subdevice *s);
int comedi_alloc_subdevice_minor(struct comedi_device *dev, struct comedi_subdevice *s);
void comedi_free_subdevice_minor(struct comedi_subdevice *s);
int comedi_pci_auto_config(struct pci_dev *pcidev, const char *board_name);
void comedi_pci_auto_unconfig(struct pci_dev *pcidev);
struct usb_device; /* forward declaration */
int comedi_usb_auto_config(struct usb_device *usbdev, const char *board_name);
void comedi_usb_auto_unconfig(struct usb_device *usbdev);
#include "comedi_rt.h"

View file

@ -36,18 +36,16 @@
#ifndef KCOMEDILIB_DEPRECATED
typedef void comedi_t;
/* these functions may not be called at real-time priority */
comedi_t *comedi_open(const char *path);
int comedi_close(comedi_t *dev);
void *comedi_open(const char *path);
int comedi_close(void *dev);
/* these functions may be called at any priority, but may fail at
real-time priority */
int comedi_lock(comedi_t *dev, unsigned int subdev);
int comedi_unlock(comedi_t *dev, unsigned int subdev);
int comedi_lock(void *dev, unsigned int subdev);
int comedi_unlock(void *dev, unsigned int subdev);
/* these functions may be called at any priority, but you must hold
the lock for the subdevice */
@ -56,68 +54,68 @@ int comedi_loglevel(int loglevel);
void comedi_perror(const char *s);
char *comedi_strerror(int errnum);
int comedi_errno(void);
int comedi_fileno(comedi_t *dev);
int comedi_fileno(void *dev);
int comedi_cancel(comedi_t *dev, unsigned int subdev);
int comedi_register_callback(comedi_t *dev, unsigned int subdev,
int comedi_cancel(void *dev, unsigned int subdev);
int comedi_register_callback(void *dev, unsigned int subdev,
unsigned int mask, int (*cb) (unsigned int, void *), void *arg);
int comedi_command(comedi_t *dev, comedi_cmd *cmd);
int comedi_command_test(comedi_t *dev, comedi_cmd *cmd);
int comedi_trigger(comedi_t *dev, unsigned int subdev, comedi_trig *it);
int __comedi_trigger(comedi_t *dev, unsigned int subdev, comedi_trig *it);
int comedi_data_write(comedi_t *dev, unsigned int subdev, unsigned int chan,
unsigned int range, unsigned int aref, lsampl_t data);
int comedi_data_read(comedi_t *dev, unsigned int subdev, unsigned int chan,
unsigned int range, unsigned int aref, lsampl_t *data);
int comedi_data_read_hint(comedi_t *dev, unsigned int subdev,
int comedi_command(void *dev, struct comedi_cmd *cmd);
int comedi_command_test(void *dev, struct comedi_cmd *cmd);
int comedi_trigger(void *dev, unsigned int subdev, struct comedi_trig *it);
int __comedi_trigger(void *dev, unsigned int subdev, struct comedi_trig *it);
int comedi_data_write(void *dev, unsigned int subdev, unsigned int chan,
unsigned int range, unsigned int aref, unsigned int data);
int comedi_data_read(void *dev, unsigned int subdev, unsigned int chan,
unsigned int range, unsigned int aref, unsigned int *data);
int comedi_data_read_hint(void *dev, unsigned int subdev,
unsigned int chan, unsigned int range, unsigned int aref);
int comedi_data_read_delayed(comedi_t *dev, unsigned int subdev,
int comedi_data_read_delayed(void *dev, unsigned int subdev,
unsigned int chan, unsigned int range, unsigned int aref,
lsampl_t *data, unsigned int nano_sec);
int comedi_dio_config(comedi_t *dev, unsigned int subdev, unsigned int chan,
unsigned int *data, unsigned int nano_sec);
int comedi_dio_config(void *dev, unsigned int subdev, unsigned int chan,
unsigned int io);
int comedi_dio_read(comedi_t *dev, unsigned int subdev, unsigned int chan,
int comedi_dio_read(void *dev, unsigned int subdev, unsigned int chan,
unsigned int *val);
int comedi_dio_write(comedi_t *dev, unsigned int subdev, unsigned int chan,
int comedi_dio_write(void *dev, unsigned int subdev, unsigned int chan,
unsigned int val);
int comedi_dio_bitfield(comedi_t *dev, unsigned int subdev, unsigned int mask,
int comedi_dio_bitfield(void *dev, unsigned int subdev, unsigned int mask,
unsigned int *bits);
int comedi_get_n_subdevices(comedi_t *dev);
int comedi_get_version_code(comedi_t *dev);
const char *comedi_get_driver_name(comedi_t *dev);
const char *comedi_get_board_name(comedi_t *dev);
int comedi_get_subdevice_type(comedi_t *dev, unsigned int subdevice);
int comedi_find_subdevice_by_type(comedi_t *dev, int type, unsigned int subd);
int comedi_get_n_channels(comedi_t *dev, unsigned int subdevice);
lsampl_t comedi_get_maxdata(comedi_t *dev, unsigned int subdevice, unsigned
int comedi_get_n_subdevices(void *dev);
int comedi_get_version_code(void *dev);
const char *comedi_get_driver_name(void *dev);
const char *comedi_get_board_name(void *dev);
int comedi_get_subdevice_type(void *dev, unsigned int subdevice);
int comedi_find_subdevice_by_type(void *dev, int type, unsigned int subd);
int comedi_get_n_channels(void *dev, unsigned int subdevice);
unsigned int comedi_get_maxdata(void *dev, unsigned int subdevice, unsigned
int chan);
int comedi_get_n_ranges(comedi_t *dev, unsigned int subdevice, unsigned int
int comedi_get_n_ranges(void *dev, unsigned int subdevice, unsigned int
chan);
int comedi_do_insn(comedi_t *dev, comedi_insn *insn);
int comedi_poll(comedi_t *dev, unsigned int subdev);
int comedi_do_insn(void *dev, struct comedi_insn *insn);
int comedi_poll(void *dev, unsigned int subdev);
/* DEPRECATED functions */
int comedi_get_rangetype(comedi_t *dev, unsigned int subdevice,
int comedi_get_rangetype(void *dev, unsigned int subdevice,
unsigned int chan);
/* ALPHA functions */
unsigned int comedi_get_subdevice_flags(comedi_t *dev, unsigned int subdevice);
int comedi_get_len_chanlist(comedi_t *dev, unsigned int subdevice);
int comedi_get_krange(comedi_t *dev, unsigned int subdevice, unsigned int
chan, unsigned int range, comedi_krange *krange);
unsigned int comedi_get_buf_head_pos(comedi_t *dev, unsigned int subdevice);
int comedi_set_user_int_count(comedi_t *dev, unsigned int subdevice,
unsigned int comedi_get_subdevice_flags(void *dev, unsigned int subdevice);
int comedi_get_len_chanlist(void *dev, unsigned int subdevice);
int comedi_get_krange(void *dev, unsigned int subdevice, unsigned int
chan, unsigned int range, struct comedi_krange *krange);
unsigned int comedi_get_buf_head_pos(void *dev, unsigned int subdevice);
int comedi_set_user_int_count(void *dev, unsigned int subdevice,
unsigned int buf_user_count);
int comedi_map(comedi_t *dev, unsigned int subdev, void *ptr);
int comedi_unmap(comedi_t *dev, unsigned int subdev);
int comedi_get_buffer_size(comedi_t *dev, unsigned int subdev);
int comedi_mark_buffer_read(comedi_t *dev, unsigned int subdevice,
int comedi_map(void *dev, unsigned int subdev, void *ptr);
int comedi_unmap(void *dev, unsigned int subdev);
int comedi_get_buffer_size(void *dev, unsigned int subdev);
int comedi_mark_buffer_read(void *dev, unsigned int subdevice,
unsigned int num_bytes);
int comedi_mark_buffer_written(comedi_t *d, unsigned int subdevice,
int comedi_mark_buffer_written(void *d, unsigned int subdevice,
unsigned int num_bytes);
int comedi_get_buffer_contents(comedi_t *dev, unsigned int subdevice);
int comedi_get_buffer_offset(comedi_t *dev, unsigned int subdevice);
int comedi_get_buffer_contents(void *dev, unsigned int subdevice);
int comedi_get_buffer_offset(void *dev, unsigned int subdevice);
#else
@ -139,14 +137,14 @@ int comedi_cancel(unsigned int minor, unsigned int subdev);
int comedi_register_callback(unsigned int minor, unsigned int subdev,
unsigned int mask, int (*cb) (unsigned int, void *), void *arg);
int comedi_command(unsigned int minor, comedi_cmd *cmd);
int comedi_command_test(unsigned int minor, comedi_cmd *cmd);
int comedi_trigger(unsigned int minor, unsigned int subdev, comedi_trig *it);
int __comedi_trigger(unsigned int minor, unsigned int subdev, comedi_trig *it);
int comedi_command(unsigned int minor, struct comedi_cmd *cmd);
int comedi_command_test(unsigned int minor, struct comedi_cmd *cmd);
int comedi_trigger(unsigned int minor, unsigned int subdev, struct comedi_trig *it);
int __comedi_trigger(unsigned int minor, unsigned int subdev, struct comedi_trig *it);
int comedi_data_write(unsigned int dev, unsigned int subdev, unsigned int chan,
unsigned int range, unsigned int aref, lsampl_t data);
unsigned int range, unsigned int aref, unsigned int data);
int comedi_data_read(unsigned int dev, unsigned int subdev, unsigned int chan,
unsigned int range, unsigned int aref, lsampl_t *data);
unsigned int range, unsigned int aref, unsigned int *data);
int comedi_dio_config(unsigned int dev, unsigned int subdev, unsigned int chan,
unsigned int io);
int comedi_dio_read(unsigned int dev, unsigned int subdev, unsigned int chan,
@ -163,11 +161,11 @@ int comedi_get_subdevice_type(unsigned int minor, unsigned int subdevice);
int comedi_find_subdevice_by_type(unsigned int minor, int type,
unsigned int subd);
int comedi_get_n_channels(unsigned int minor, unsigned int subdevice);
lsampl_t comedi_get_maxdata(unsigned int minor, unsigned int subdevice, unsigned
unsigned int comedi_get_maxdata(unsigned int minor, unsigned int subdevice, unsigned
int chan);
int comedi_get_n_ranges(unsigned int minor, unsigned int subdevice, unsigned int
chan);
int comedi_do_insn(unsigned int minor, comedi_insn *insn);
int comedi_do_insn(unsigned int minor, struct comedi_insn *insn);
int comedi_poll(unsigned int minor, unsigned int subdev);
/* DEPRECATED functions */
@ -179,7 +177,7 @@ unsigned int comedi_get_subdevice_flags(unsigned int minor, unsigned int
subdevice);
int comedi_get_len_chanlist(unsigned int minor, unsigned int subdevice);
int comedi_get_krange(unsigned int minor, unsigned int subdevice, unsigned int
chan, unsigned int range, comedi_krange *krange);
chan, unsigned int range, struct comedi_krange *krange);
unsigned int comedi_get_buf_head_pos(unsigned int minor, unsigned int
subdevice);
int comedi_set_user_int_count(unsigned int minor, unsigned int subdevice,

View file

@ -28,6 +28,7 @@
#include <linux/device.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/usb.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/sched.h>
@ -46,26 +47,26 @@
#include <asm/io.h>
#include <asm/system.h>
static int postconfig(comedi_device * dev);
static int insn_rw_emulate_bits(comedi_device * dev, comedi_subdevice * s,
comedi_insn * insn, lsampl_t * data);
static void *comedi_recognize(comedi_driver * driv, const char *name);
static void comedi_report_boards(comedi_driver * driv);
static int poll_invalid(comedi_device * dev, comedi_subdevice * s);
int comedi_buf_alloc(comedi_device * dev, comedi_subdevice * s,
static int postconfig(struct comedi_device *dev);
static int insn_rw_emulate_bits(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
static void *comedi_recognize(struct comedi_driver * driv, const char *name);
static void comedi_report_boards(struct comedi_driver *driv);
static int poll_invalid(struct comedi_device *dev, struct comedi_subdevice *s);
int comedi_buf_alloc(struct comedi_device *dev, struct comedi_subdevice *s,
unsigned long new_size);
comedi_driver *comedi_drivers;
struct comedi_driver *comedi_drivers;
int comedi_modprobe(int minor)
{
return -EINVAL;
}
static void cleanup_device(comedi_device * dev)
static void cleanup_device(struct comedi_device *dev)
{
int i;
comedi_subdevice *s;
struct comedi_subdevice *s;
if (dev->subdevices) {
for (i = 0; i < dev->n_subdevices; i++) {
@ -80,10 +81,8 @@ static void cleanup_device(comedi_device * dev)
dev->subdevices = NULL;
dev->n_subdevices = 0;
}
if (dev->private) {
kfree(dev->private);
dev->private = NULL;
}
kfree(dev->private);
dev->private = NULL;
dev->driver = 0;
dev->board_name = NULL;
dev->board_ptr = NULL;
@ -96,7 +95,7 @@ static void cleanup_device(comedi_device * dev)
comedi_set_hw_dev(dev, NULL);
}
static void __comedi_device_detach(comedi_device * dev)
static void __comedi_device_detach(struct comedi_device *dev)
{
dev->attached = 0;
if (dev->driver) {
@ -107,16 +106,16 @@ static void __comedi_device_detach(comedi_device * dev)
cleanup_device(dev);
}
void comedi_device_detach(comedi_device * dev)
void comedi_device_detach(struct comedi_device *dev)
{
if (!dev->attached)
return;
__comedi_device_detach(dev);
}
int comedi_device_attach(comedi_device * dev, comedi_devconfig * it)
int comedi_device_attach(struct comedi_device *dev, struct comedi_devconfig *it)
{
comedi_driver *driv;
struct comedi_driver *driv;
int ret;
if (dev->attached)
@ -139,7 +138,7 @@ int comedi_device_attach(comedi_device * dev, comedi_devconfig * it)
continue;
}
}
//initialize dev->driver here so comedi_error() can be called from attach
/* initialize dev->driver here so comedi_error() can be called from attach */
dev->driver = driv;
ret = driv->attach(dev, it);
if (ret < 0) {
@ -150,8 +149,8 @@ int comedi_device_attach(comedi_device * dev, comedi_devconfig * it)
goto attached;
}
// recognize has failed if we get here
// report valid board names before returning error
/* recognize has failed if we get here */
/* report valid board names before returning error */
for (driv = comedi_drivers; driv; driv = driv->next) {
if (!try_module_get(driv->module)) {
printk("comedi: failed to increment module count\n");
@ -181,7 +180,7 @@ int comedi_device_attach(comedi_device * dev, comedi_devconfig * it)
return 0;
}
int comedi_driver_register(comedi_driver * driver)
int comedi_driver_register(struct comedi_driver *driver)
{
driver->next = comedi_drivers;
comedi_drivers = driver;
@ -189,15 +188,15 @@ int comedi_driver_register(comedi_driver * driver)
return 0;
}
int comedi_driver_unregister(comedi_driver * driver)
int comedi_driver_unregister(struct comedi_driver *driver)
{
comedi_driver *prev;
struct comedi_driver *prev;
int i;
/* check for devices using this driver */
for (i = 0; i < COMEDI_NUM_BOARD_MINORS; i++) {
struct comedi_device_file_info *dev_file_info = comedi_get_device_file_info(i);
comedi_device *dev;
struct comedi_device *dev;
if(dev_file_info == NULL) continue;
dev = dev_file_info->device;
@ -225,11 +224,11 @@ int comedi_driver_unregister(comedi_driver * driver)
return -EINVAL;
}
static int postconfig(comedi_device * dev)
static int postconfig(struct comedi_device *dev)
{
int i;
comedi_subdevice *s;
comedi_async *async = NULL;
struct comedi_subdevice *s;
struct comedi_async *async = NULL;
int ret;
for (i = 0; i < dev->n_subdevices; i++) {
@ -246,7 +245,7 @@ static int postconfig(comedi_device * dev)
SDF_CMD_WRITE)) == 0);
BUG_ON(!s->do_cmdtest);
async = kzalloc(sizeof(comedi_async), GFP_KERNEL);
async = kzalloc(sizeof(struct comedi_async), GFP_KERNEL);
if (async == NULL) {
printk("failed to allocate async struct\n");
return -ENOMEM;
@ -298,8 +297,8 @@ static int postconfig(comedi_device * dev)
return 0;
}
// generic recognize function for drivers that register their supported board names
void *comedi_recognize(comedi_driver * driv, const char *name)
/* generic recognize function for drivers that register their supported board names */
void *comedi_recognize(struct comedi_driver * driv, const char *name)
{
unsigned i;
const char *const *name_ptr = driv->board_name;
@ -314,7 +313,7 @@ void *comedi_recognize(comedi_driver * driv, const char *name)
return NULL;
}
void comedi_report_boards(comedi_driver * driv)
void comedi_report_boards(struct comedi_driver *driv)
{
unsigned int i;
const char *const *name_ptr;
@ -332,28 +331,28 @@ void comedi_report_boards(comedi_driver * driv)
printk(" %s\n", driv->driver_name);
}
static int poll_invalid(comedi_device * dev, comedi_subdevice * s)
static int poll_invalid(struct comedi_device *dev, struct comedi_subdevice *s)
{
return -EINVAL;
}
int insn_inval(comedi_device * dev, comedi_subdevice * s,
comedi_insn * insn, lsampl_t * data)
int insn_inval(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
return -EINVAL;
}
static int insn_rw_emulate_bits(comedi_device * dev, comedi_subdevice * s,
comedi_insn * insn, lsampl_t * data)
static int insn_rw_emulate_bits(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
comedi_insn new_insn;
struct comedi_insn new_insn;
int ret;
static const unsigned channels_per_bitfield = 32;
unsigned chan = CR_CHAN(insn->chanspec);
const unsigned base_bitfield_channel =
(chan < channels_per_bitfield) ? 0 : chan;
lsampl_t new_data[2];
unsigned int new_data[2];
memset(new_data, 0, sizeof(new_data));
memset(&new_insn, 0, sizeof(new_insn));
new_insn.insn = INSN_BITS;
@ -380,7 +379,7 @@ static int insn_rw_emulate_bits(comedi_device * dev, comedi_subdevice * s,
return 1;
}
static inline unsigned long uvirt_to_kva(pgd_t * pgd, unsigned long adr)
static inline unsigned long uvirt_to_kva(pgd_t *pgd, unsigned long adr)
{
unsigned long ret = 0UL;
pmd_t *pmd;
@ -413,10 +412,10 @@ static inline unsigned long kvirt_to_kva(unsigned long adr)
return kva;
}
int comedi_buf_alloc(comedi_device * dev, comedi_subdevice * s,
int comedi_buf_alloc(struct comedi_device *dev, struct comedi_subdevice *s,
unsigned long new_size)
{
comedi_async *async = s->async;
struct comedi_async *async = s->async;
/* Round up new_size to multiple of PAGE_SIZE */
new_size = (new_size + PAGE_SIZE - 1) & PAGE_MASK;
@ -425,7 +424,7 @@ int comedi_buf_alloc(comedi_device * dev, comedi_subdevice * s,
if (async->prealloc_buf && async->prealloc_bufsz == new_size) {
return 0;
}
// deallocate old buffer
/* deallocate old buffer */
if (async->prealloc_buf) {
vunmap(async->prealloc_buf);
async->prealloc_buf = NULL;
@ -454,7 +453,7 @@ int comedi_buf_alloc(comedi_device * dev, comedi_subdevice * s,
async->buf_page_list = NULL;
async->n_buf_pages = 0;
}
// allocate new buffer
/* allocate new buffer */
if (new_size) {
unsigned i = 0;
unsigned n_pages = new_size >> PAGE_SHIFT;
@ -537,16 +536,15 @@ int comedi_buf_alloc(comedi_device * dev, comedi_subdevice * s,
/* munging is applied to data by core as it passes between user
* and kernel space */
unsigned int comedi_buf_munge(comedi_async * async, unsigned int num_bytes)
unsigned int comedi_buf_munge(struct comedi_async *async, unsigned int num_bytes)
{
comedi_subdevice *s = async->subdevice;
struct comedi_subdevice *s = async->subdevice;
unsigned int count = 0;
const unsigned num_sample_bytes = bytes_per_sample(s);
if (s->munge == NULL || (async->cmd.flags & CMDF_RAWDATA)) {
async->munge_count += num_bytes;
if ((int)(async->munge_count - async->buf_write_count) > 0)
BUG();
BUG_ON((int)(async->munge_count - async->buf_write_count) > 0);
return num_bytes;
}
/* don't munge partial samples */
@ -567,7 +565,7 @@ unsigned int comedi_buf_munge(comedi_async * async, unsigned int num_bytes)
s->munge(s->device, s, async->prealloc_buf + async->munge_ptr,
block_size, async->munge_chan);
smp_wmb(); //barrier insures data is munged in buffer before munge_count is incremented
smp_wmb(); /* barrier insures data is munged in buffer before munge_count is incremented */
async->munge_chan += block_size / num_sample_bytes;
async->munge_chan %= async->cmd.chanlist_len;
@ -576,12 +574,11 @@ unsigned int comedi_buf_munge(comedi_async * async, unsigned int num_bytes)
async->munge_ptr %= async->prealloc_bufsz;
count += block_size;
}
if ((int)(async->munge_count - async->buf_write_count) > 0)
BUG();
BUG_ON((int)(async->munge_count - async->buf_write_count) > 0);
return count;
}
unsigned int comedi_buf_write_n_available(comedi_async * async)
unsigned int comedi_buf_write_n_available(struct comedi_async *async)
{
unsigned int free_end;
unsigned int nbytes;
@ -601,7 +598,7 @@ unsigned int comedi_buf_write_n_available(comedi_async * async)
}
/* allocates chunk for the writer from free buffer space */
unsigned int comedi_buf_write_alloc(comedi_async * async, unsigned int nbytes)
unsigned int comedi_buf_write_alloc(struct comedi_async *async, unsigned int nbytes)
{
unsigned int free_end = async->buf_read_count + async->prealloc_bufsz;
@ -616,7 +613,7 @@ unsigned int comedi_buf_write_alloc(comedi_async * async, unsigned int nbytes)
}
/* allocates nothing unless it can completely fulfill the request */
unsigned int comedi_buf_write_alloc_strict(comedi_async * async,
unsigned int comedi_buf_write_alloc_strict(struct comedi_async *async,
unsigned int nbytes)
{
unsigned int free_end = async->buf_read_count + async->prealloc_bufsz;
@ -632,7 +629,7 @@ unsigned int comedi_buf_write_alloc_strict(comedi_async * async,
}
/* transfers a chunk from writer to filled buffer space */
unsigned comedi_buf_write_free(comedi_async * async, unsigned int nbytes)
unsigned comedi_buf_write_free(struct comedi_async *async, unsigned int nbytes)
{
if ((int)(async->buf_write_count + nbytes -
async->buf_write_alloc_count) > 0) {
@ -650,7 +647,7 @@ unsigned comedi_buf_write_free(comedi_async * async, unsigned int nbytes)
}
/* allocates a chunk for the reader from filled (and munged) buffer space */
unsigned comedi_buf_read_alloc(comedi_async * async, unsigned nbytes)
unsigned comedi_buf_read_alloc(struct comedi_async *async, unsigned nbytes)
{
if ((int)(async->buf_read_alloc_count + nbytes - async->munge_count) >
0) {
@ -664,9 +661,9 @@ unsigned comedi_buf_read_alloc(comedi_async * async, unsigned nbytes)
}
/* transfers control of a chunk from reader to free buffer space */
unsigned comedi_buf_read_free(comedi_async * async, unsigned int nbytes)
unsigned comedi_buf_read_free(struct comedi_async *async, unsigned int nbytes)
{
// barrier insures data has been read out of buffer before read count is incremented
/* barrier insures data has been read out of buffer before read count is incremented */
smp_mb();
if ((int)(async->buf_read_count + nbytes -
async->buf_read_alloc_count) > 0) {
@ -680,7 +677,7 @@ unsigned comedi_buf_read_free(comedi_async * async, unsigned int nbytes)
return nbytes;
}
void comedi_buf_memcpy_to(comedi_async * async, unsigned int offset,
void comedi_buf_memcpy_to(struct comedi_async *async, unsigned int offset,
const void *data, unsigned int num_bytes)
{
unsigned int write_ptr = async->buf_write_ptr + offset;
@ -705,7 +702,7 @@ void comedi_buf_memcpy_to(comedi_async * async, unsigned int offset,
}
}
void comedi_buf_memcpy_from(comedi_async * async, unsigned int offset,
void comedi_buf_memcpy_from(struct comedi_async *async, unsigned int offset,
void *dest, unsigned int nbytes)
{
void *src;
@ -731,7 +728,7 @@ void comedi_buf_memcpy_from(comedi_async * async, unsigned int offset,
}
}
unsigned int comedi_buf_read_n_available(comedi_async * async)
unsigned int comedi_buf_read_n_available(struct comedi_async *async)
{
unsigned num_bytes;
@ -746,32 +743,32 @@ unsigned int comedi_buf_read_n_available(comedi_async * async)
return num_bytes;
}
int comedi_buf_get(comedi_async * async, sampl_t * x)
int comedi_buf_get(struct comedi_async *async, short *x)
{
unsigned int n = comedi_buf_read_n_available(async);
if (n < sizeof(sampl_t))
if (n < sizeof(short))
return 0;
comedi_buf_read_alloc(async, sizeof(sampl_t));
*x = *(sampl_t *) (async->prealloc_buf + async->buf_read_ptr);
comedi_buf_read_free(async, sizeof(sampl_t));
comedi_buf_read_alloc(async, sizeof(short));
*x = *(short *) (async->prealloc_buf + async->buf_read_ptr);
comedi_buf_read_free(async, sizeof(short));
return 1;
}
int comedi_buf_put(comedi_async * async, sampl_t x)
int comedi_buf_put(struct comedi_async *async, short x)
{
unsigned int n = comedi_buf_write_alloc_strict(async, sizeof(sampl_t));
unsigned int n = comedi_buf_write_alloc_strict(async, sizeof(short));
if (n < sizeof(sampl_t)) {
if (n < sizeof(short)) {
async->events |= COMEDI_CB_ERROR;
return 0;
}
*(sampl_t *) (async->prealloc_buf + async->buf_write_ptr) = x;
comedi_buf_write_free(async, sizeof(sampl_t));
*(short *) (async->prealloc_buf + async->buf_write_ptr) = x;
comedi_buf_write_free(async, sizeof(short));
return 1;
}
void comedi_reset_async_buf(comedi_async * async)
void comedi_reset_async_buf(struct comedi_async *async)
{
async->buf_write_alloc_count = 0;
async->buf_write_count = 0;
@ -792,14 +789,27 @@ void comedi_reset_async_buf(comedi_async * async)
int comedi_auto_config(struct device *hardware_device, const char *board_name, const int *options, unsigned num_options)
{
comedi_devconfig it;
struct comedi_devconfig it;
int minor;
struct comedi_device_file_info *dev_file_info;
int retval;
unsigned *private_data = NULL;
if (!comedi_autoconfig) {
dev_set_drvdata(hardware_device, NULL);
return 0;
}
minor = comedi_alloc_board_minor(hardware_device);
if(minor < 0) return minor;
dev_set_drvdata(hardware_device, (void*)(unsigned long)minor);
private_data = kmalloc(sizeof(unsigned), GFP_KERNEL);
if (private_data == NULL) {
retval = -ENOMEM;
goto cleanup;
}
*private_data = minor;
dev_set_drvdata(hardware_device, private_data);
dev_file_info = comedi_get_device_file_info(minor);
@ -812,8 +822,11 @@ int comedi_auto_config(struct device *hardware_device, const char *board_name, c
mutex_lock(&dev_file_info->device->mutex);
retval = comedi_device_attach(dev_file_info->device, &it);
mutex_unlock(&dev_file_info->device->mutex);
cleanup:
if(retval < 0)
{
kfree(private_data);
comedi_free_board_minor(minor);
}
return retval;
@ -821,20 +834,23 @@ int comedi_auto_config(struct device *hardware_device, const char *board_name, c
void comedi_auto_unconfig(struct device *hardware_device)
{
unsigned long minor = (unsigned long)dev_get_drvdata(hardware_device);
unsigned *minor = (unsigned *)dev_get_drvdata(hardware_device);
if(minor == NULL) return;
BUG_ON(minor >= COMEDI_NUM_BOARD_MINORS);
BUG_ON(*minor >= COMEDI_NUM_BOARD_MINORS);
comedi_free_board_minor(minor);
comedi_free_board_minor(*minor);
dev_set_drvdata(hardware_device, NULL);
kfree(minor);
}
int comedi_pci_auto_config(struct pci_dev *pcidev, const char *board_name)
{
int options[2];
// pci bus
/* pci bus */
options[0] = pcidev->bus->number;
// pci slot
/* pci slot */
options[1] = PCI_SLOT(pcidev->devfn);
return comedi_auto_config(&pcidev->dev, board_name, options, sizeof(options) / sizeof(options[0]));
@ -844,3 +860,16 @@ void comedi_pci_auto_unconfig(struct pci_dev *pcidev)
{
comedi_auto_unconfig(&pcidev->dev);
}
int comedi_usb_auto_config(struct usb_device *usbdev,
const char *board_name)
{
BUG_ON(usbdev == NULL);
return comedi_auto_config(&usbdev->dev, board_name, NULL, 0);
}
void comedi_usb_auto_unconfig(struct usb_device *usbdev)
{
BUG_ON(usbdev == NULL);
comedi_auto_unconfig(&usbdev->dev);
}

View file

@ -0,0 +1,420 @@
/*
comedi/drivers/8253.h
Header file for 8253
COMEDI - Linux Control and Measurement Device Interface
Copyright (C) 2000 David A. Schleef <ds@schleef.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef _8253_H
#define _8253_H
#ifndef CMDTEST
#include "../comedi.h"
#else
#include "../comedi.h"
#endif
#define i8253_cascade_ns_to_timer i8253_cascade_ns_to_timer_2div
static inline void i8253_cascade_ns_to_timer_2div_old(int i8253_osc_base,
unsigned int *d1, unsigned int *d2, unsigned int *nanosec,
int round_mode)
{
int divider;
int div1, div2;
int div1_glb, div2_glb, ns_glb;
int div1_lub, div2_lub, ns_lub;
int ns;
divider = (*nanosec + i8253_osc_base / 2) / i8253_osc_base;
/* find 2 integers 1<={x,y}<=65536 such that x*y is
close to divider */
div1_lub = div2_lub = 0;
div1_glb = div2_glb = 0;
ns_glb = 0;
ns_lub = 0xffffffff;
div2 = 0x10000;
for (div1 = divider / 65536 + 1; div1 < div2; div1++) {
div2 = divider / div1;
ns = i8253_osc_base * div1 * div2;
if (ns <= *nanosec && ns > ns_glb) {
ns_glb = ns;
div1_glb = div1;
div2_glb = div2;
}
div2++;
if (div2 <= 65536) {
ns = i8253_osc_base * div1 * div2;
if (ns > *nanosec && ns < ns_lub) {
ns_lub = ns;
div1_lub = div1;
div2_lub = div2;
}
}
}
*nanosec = div1_lub * div2_lub * i8253_osc_base;
*d1 = div1_lub & 0xffff;
*d2 = div2_lub & 0xffff;
return;
}
static inline void i8253_cascade_ns_to_timer_power(int i8253_osc_base,
unsigned int *d1, unsigned int *d2, unsigned int *nanosec,
int round_mode)
{
int div1, div2;
int base;
for (div1 = 2; div1 <= (1 << 16); div1 <<= 1) {
base = i8253_osc_base * div1;
round_mode &= TRIG_ROUND_MASK;
switch (round_mode) {
case TRIG_ROUND_NEAREST:
default:
div2 = (*nanosec + base / 2) / base;
break;
case TRIG_ROUND_DOWN:
div2 = (*nanosec) / base;
break;
case TRIG_ROUND_UP:
div2 = (*nanosec + base - 1) / base;
break;
}
if (div2 < 2)
div2 = 2;
if (div2 <= 65536) {
*nanosec = div2 * base;
*d1 = div1 & 0xffff;
*d2 = div2 & 0xffff;
return;
}
}
/* shouldn't get here */
div1 = 0x10000;
div2 = 0x10000;
*nanosec = div1 * div2 * i8253_osc_base;
*d1 = div1 & 0xffff;
*d2 = div2 & 0xffff;
}
static inline void i8253_cascade_ns_to_timer_2div(int i8253_osc_base,
unsigned int *d1, unsigned int *d2, unsigned int *nanosec,
int round_mode)
{
unsigned int divider;
unsigned int div1, div2;
unsigned int div1_glb, div2_glb, ns_glb;
unsigned int div1_lub, div2_lub, ns_lub;
unsigned int ns;
unsigned int start;
unsigned int ns_low, ns_high;
static const unsigned int max_count = 0x10000;
/* exit early if everything is already correct (this can save time
* since this function may be called repeatedly during command tests
* and execution) */
div1 = *d1 ? *d1 : max_count;
div2 = *d2 ? *d2 : max_count;
divider = div1 * div2;
if (div1 * div2 * i8253_osc_base == *nanosec &&
div1 > 1 && div1 <= max_count &&
div2 > 1 && div2 <= max_count &&
/* check for overflow */
divider > div1 && divider > div2 &&
divider * i8253_osc_base > divider &&
divider * i8253_osc_base > i8253_osc_base) {
return;
}
divider = *nanosec / i8253_osc_base;
div1_lub = div2_lub = 0;
div1_glb = div2_glb = 0;
ns_glb = 0;
ns_lub = 0xffffffff;
div2 = max_count;
start = divider / div2;
if (start < 2)
start = 2;
for (div1 = start; div1 <= divider / div1 + 1 && div1 <= max_count;
div1++) {
for (div2 = divider / div1;
div1 * div2 <= divider + div1 + 1 && div2 <= max_count;
div2++) {
ns = i8253_osc_base * div1 * div2;
if (ns <= *nanosec && ns > ns_glb) {
ns_glb = ns;
div1_glb = div1;
div2_glb = div2;
}
if (ns >= *nanosec && ns < ns_lub) {
ns_lub = ns;
div1_lub = div1;
div2_lub = div2;
}
}
}
round_mode &= TRIG_ROUND_MASK;
switch (round_mode) {
case TRIG_ROUND_NEAREST:
default:
ns_high = div1_lub * div2_lub * i8253_osc_base;
ns_low = div1_glb * div2_glb * i8253_osc_base;
if (ns_high - *nanosec < *nanosec - ns_low) {
div1 = div1_lub;
div2 = div2_lub;
} else {
div1 = div1_glb;
div2 = div2_glb;
}
break;
case TRIG_ROUND_UP:
div1 = div1_lub;
div2 = div2_lub;
break;
case TRIG_ROUND_DOWN:
div1 = div1_glb;
div2 = div2_glb;
break;
}
*nanosec = div1 * div2 * i8253_osc_base;
*d1 = div1 & 0xffff; // masking is done since counter maps zero to 0x10000
*d2 = div2 & 0xffff;
return;
}
#ifndef CMDTEST
/* i8254_load programs 8254 counter chip. It should also work for the 8253.
* base_address is the lowest io address for the chip (the address of counter 0).
* counter_number is the counter you want to load (0,1 or 2)
* count is the number to load into the counter.
*
* You probably want to use mode 2.
*
* Use i8254_mm_load() if you board uses memory-mapped io, it is
* the same as i8254_load() except it uses writeb() instead of outb().
*
* Neither i8254_load() or i8254_read() do their loading/reading
* atomically. The 16 bit read/writes are performed with two successive
* 8 bit read/writes. So if two parts of your driver do a load/read on
* the same counter, it may be necessary to protect these functions
* with a spinlock.
*
* FMH
*/
#define i8254_control_reg 3
static inline int i8254_load(unsigned long base_address, unsigned int regshift,
unsigned int counter_number, unsigned int count, unsigned int mode)
{
unsigned int byte;
if (counter_number > 2)
return -1;
if (count > 0xffff)
return -1;
if (mode > 5)
return -1;
if ((mode == 2 || mode == 3) && count == 1)
return -1;
byte = counter_number << 6;
byte |= 0x30; // load low then high byte
byte |= (mode << 1); // set counter mode
outb(byte, base_address + (i8254_control_reg << regshift));
byte = count & 0xff; // lsb of counter value
outb(byte, base_address + (counter_number << regshift));
byte = (count >> 8) & 0xff; // msb of counter value
outb(byte, base_address + (counter_number << regshift));
return 0;
}
static inline int i8254_mm_load(void *base_address, unsigned int regshift,
unsigned int counter_number, unsigned int count, unsigned int mode)
{
unsigned int byte;
if (counter_number > 2)
return -1;
if (count > 0xffff)
return -1;
if (mode > 5)
return -1;
if ((mode == 2 || mode == 3) && count == 1)
return -1;
byte = counter_number << 6;
byte |= 0x30; // load low then high byte
byte |= (mode << 1); // set counter mode
writeb(byte, base_address + (i8254_control_reg << regshift));
byte = count & 0xff; // lsb of counter value
writeb(byte, base_address + (counter_number << regshift));
byte = (count >> 8) & 0xff; // msb of counter value
writeb(byte, base_address + (counter_number << regshift));
return 0;
}
/* Returns 16 bit counter value, should work for 8253 also.*/
static inline int i8254_read(unsigned long base_address, unsigned int regshift,
unsigned int counter_number)
{
unsigned int byte;
int ret;
if (counter_number > 2)
return -1;
// latch counter
byte = counter_number << 6;
outb(byte, base_address + (i8254_control_reg << regshift));
// read lsb
ret = inb(base_address + (counter_number << regshift));
// read msb
ret += inb(base_address + (counter_number << regshift)) << 8;
return ret;
}
static inline int i8254_mm_read(void *base_address, unsigned int regshift,
unsigned int counter_number)
{
unsigned int byte;
int ret;
if (counter_number > 2)
return -1;
// latch counter
byte = counter_number << 6;
writeb(byte, base_address + (i8254_control_reg << regshift));
// read lsb
ret = readb(base_address + (counter_number << regshift));
// read msb
ret += readb(base_address + (counter_number << regshift)) << 8;
return ret;
}
/* Loads 16 bit initial counter value, should work for 8253 also. */
static inline void i8254_write(unsigned long base_address,
unsigned int regshift, unsigned int counter_number, unsigned int count)
{
unsigned int byte;
if (counter_number > 2)
return;
byte = count & 0xff; // lsb of counter value
outb(byte, base_address + (counter_number << regshift));
byte = (count >> 8) & 0xff; // msb of counter value
outb(byte, base_address + (counter_number << regshift));
}
static inline void i8254_mm_write(void *base_address,
unsigned int regshift, unsigned int counter_number, unsigned int count)
{
unsigned int byte;
if (counter_number > 2)
return;
byte = count & 0xff; // lsb of counter value
writeb(byte, base_address + (counter_number << regshift));
byte = (count >> 8) & 0xff; // msb of counter value
writeb(byte, base_address + (counter_number << regshift));
}
/* Set counter mode, should work for 8253 also.
* Note: the 'mode' value is different to that for i8254_load() and comes
* from the INSN_CONFIG_8254_SET_MODE command:
* I8254_MODE0, I8254_MODE1, ..., I8254_MODE5
* OR'ed with:
* I8254_BCD, I8254_BINARY
*/
static inline int i8254_set_mode(unsigned long base_address,
unsigned int regshift, unsigned int counter_number, unsigned int mode)
{
unsigned int byte;
if (counter_number > 2)
return -1;
if (mode > (I8254_MODE5 | I8254_BINARY))
return -1;
byte = counter_number << 6;
byte |= 0x30; // load low then high byte
byte |= mode; // set counter mode and BCD|binary
outb(byte, base_address + (i8254_control_reg << regshift));
return 0;
}
static inline int i8254_mm_set_mode(void *base_address,
unsigned int regshift, unsigned int counter_number, unsigned int mode)
{
unsigned int byte;
if (counter_number > 2)
return -1;
if (mode > (I8254_MODE5 | I8254_BINARY))
return -1;
byte = counter_number << 6;
byte |= 0x30; // load low then high byte
byte |= mode; // set counter mode and BCD|binary
writeb(byte, base_address + (i8254_control_reg << regshift));
return 0;
}
static inline int i8254_status(unsigned long base_address,
unsigned int regshift, unsigned int counter_number)
{
outb(0xE0 | (2 << counter_number),
base_address + (i8254_control_reg << regshift));
return inb(base_address + (counter_number << regshift));
}
static inline int i8254_mm_status(void *base_address,
unsigned int regshift, unsigned int counter_number)
{
writeb(0xE0 | (2 << counter_number),
base_address + (i8254_control_reg << regshift));
return readb(base_address + (counter_number << regshift));
}
#endif
#endif

View file

@ -0,0 +1,442 @@
/*
comedi/drivers/8255.c
Driver for 8255
COMEDI - Linux Control and Measurement Device Interface
Copyright (C) 1998 David A. Schleef <ds@schleef.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
Driver: 8255
Description: generic 8255 support
Devices: [standard] 8255 (8255)
Author: ds
Status: works
Updated: Fri, 7 Jun 2002 12:56:45 -0700
The classic in digital I/O. The 8255 appears in Comedi as a single
digital I/O subdevice with 24 channels. The channel 0 corresponds
to the 8255's port A, bit 0; channel 23 corresponds to port C, bit
7. Direction configuration is done in blocks, with channels 0-7,
8-15, 16-19, and 20-23 making up the 4 blocks. The only 8255 mode
supported is mode 0.
You should enable compilation this driver if you plan to use a board
that has an 8255 chip. For multifunction boards, the main driver will
configure the 8255 subdevice automatically.
This driver also works independently with ISA and PCI cards that
directly map the 8255 registers to I/O ports, including cards with
multiple 8255 chips. To configure the driver for such a card, the
option list should be a list of the I/O port bases for each of the
8255 chips. For example,
comedi_config /dev/comedi0 8255 0x200,0x204,0x208,0x20c
Note that most PCI 8255 boards do NOT work with this driver, and
need a separate driver as a wrapper. For those that do work, the
I/O port base address can be found in the output of 'lspci -v'.
*/
/*
This file contains an exported subdevice for driving an 8255.
To use this subdevice as part of another driver, you need to
set up the subdevice in the attach function of the driver by
calling:
subdev_8255_init(device, subdevice, callback_function, arg)
device and subdevice are pointers to the device and subdevice
structures. callback_function will be called to provide the
low-level input/output to the device, i.e., actual register
access. callback_function will be called with the value of arg
as the last parameter. If the 8255 device is mapped as 4
consecutive I/O ports, you can use NULL for callback_function
and the I/O port base for arg, and an internal function will
handle the register access.
In addition, if the main driver handles interrupts, you can
enable commands on the subdevice by calling subdev_8255_init_irq()
instead. Then, when you get an interrupt that is likely to be
from the 8255, you should call subdev_8255_interrupt(), which
will copy the latched value to a Comedi buffer.
*/
#include "../comedidev.h"
#include <linux/ioport.h>
#define _8255_SIZE 4
#define _8255_DATA 0
#define _8255_CR 3
#define CR_C_LO_IO 0x01
#define CR_B_IO 0x02
#define CR_B_MODE 0x04
#define CR_C_HI_IO 0x08
#define CR_A_IO 0x10
#define CR_A_MODE(a) ((a)<<5)
#define CR_CW 0x80
struct subdev_8255_struct {
unsigned long cb_arg;
int (*cb_func) (int, int, int, unsigned long);
int have_irq;
};
#define CALLBACK_ARG (((struct subdev_8255_struct *)s->private)->cb_arg)
#define CALLBACK_FUNC (((struct subdev_8255_struct *)s->private)->cb_func)
#define subdevpriv ((struct subdev_8255_struct *)s->private)
static int dev_8255_attach(struct comedi_device *dev, struct comedi_devconfig * it);
static int dev_8255_detach(struct comedi_device *dev);
static struct comedi_driver driver_8255 = {
driver_name:"8255",
module:THIS_MODULE,
attach:dev_8255_attach,
detach:dev_8255_detach,
};
COMEDI_INITCLEANUP(driver_8255);
static void do_config(struct comedi_device *dev, struct comedi_subdevice * s);
void subdev_8255_interrupt(struct comedi_device *dev, struct comedi_subdevice * s)
{
short d;
d = CALLBACK_FUNC(0, _8255_DATA, 0, CALLBACK_ARG);
d |= (CALLBACK_FUNC(0, _8255_DATA + 1, 0, CALLBACK_ARG) << 8);
comedi_buf_put(s->async, d);
s->async->events |= COMEDI_CB_EOS;
comedi_event(dev, s);
}
static int subdev_8255_cb(int dir, int port, int data, unsigned long arg)
{
unsigned long iobase = arg;
if (dir) {
outb(data, iobase + port);
return 0;
} else {
return inb(iobase + port);
}
}
static int subdev_8255_insn(struct comedi_device *dev, struct comedi_subdevice * s,
struct comedi_insn * insn, unsigned int * data)
{
if (data[0]) {
s->state &= ~data[0];
s->state |= (data[0] & data[1]);
if (data[0] & 0xff)
CALLBACK_FUNC(1, _8255_DATA, s->state & 0xff,
CALLBACK_ARG);
if (data[0] & 0xff00)
CALLBACK_FUNC(1, _8255_DATA + 1, (s->state >> 8) & 0xff,
CALLBACK_ARG);
if (data[0] & 0xff0000)
CALLBACK_FUNC(1, _8255_DATA + 2,
(s->state >> 16) & 0xff, CALLBACK_ARG);
}
data[1] = CALLBACK_FUNC(0, _8255_DATA, 0, CALLBACK_ARG);
data[1] |= (CALLBACK_FUNC(0, _8255_DATA + 1, 0, CALLBACK_ARG) << 8);
data[1] |= (CALLBACK_FUNC(0, _8255_DATA + 2, 0, CALLBACK_ARG) << 16);
return 2;
}
static int subdev_8255_insn_config(struct comedi_device *dev, struct comedi_subdevice * s,
struct comedi_insn * insn, unsigned int * data)
{
unsigned int mask;
unsigned int bits;
mask = 1 << CR_CHAN(insn->chanspec);
if (mask & 0x0000ff) {
bits = 0x0000ff;
} else if (mask & 0x00ff00) {
bits = 0x00ff00;
} else if (mask & 0x0f0000) {
bits = 0x0f0000;
} else {
bits = 0xf00000;
}
switch (data[0]) {
case INSN_CONFIG_DIO_INPUT:
s->io_bits &= ~bits;
break;
case INSN_CONFIG_DIO_OUTPUT:
s->io_bits |= bits;
break;
case INSN_CONFIG_DIO_QUERY:
data[1] = (s->io_bits & bits) ? COMEDI_OUTPUT : COMEDI_INPUT;
return insn->n;
break;
default:
return -EINVAL;
}
do_config(dev, s);
return 1;
}
static void do_config(struct comedi_device *dev, struct comedi_subdevice * s)
{
int config;
config = CR_CW;
/* 1 in io_bits indicates output, 1 in config indicates input */
if (!(s->io_bits & 0x0000ff))
config |= CR_A_IO;
if (!(s->io_bits & 0x00ff00))
config |= CR_B_IO;
if (!(s->io_bits & 0x0f0000))
config |= CR_C_LO_IO;
if (!(s->io_bits & 0xf00000))
config |= CR_C_HI_IO;
CALLBACK_FUNC(1, _8255_CR, config, CALLBACK_ARG);
}
static int subdev_8255_cmdtest(struct comedi_device *dev, struct comedi_subdevice * s,
struct comedi_cmd * cmd)
{
int err = 0;
unsigned int tmp;
/* step 1 */
tmp = cmd->start_src;
cmd->start_src &= TRIG_NOW;
if (!cmd->start_src || tmp != cmd->start_src)
err++;
tmp = cmd->scan_begin_src;
cmd->scan_begin_src &= TRIG_EXT;
if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
err++;
tmp = cmd->convert_src;
cmd->convert_src &= TRIG_FOLLOW;
if (!cmd->convert_src || tmp != cmd->convert_src)
err++;
tmp = cmd->scan_end_src;
cmd->scan_end_src &= TRIG_COUNT;
if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
err++;
tmp = cmd->stop_src;
cmd->stop_src &= TRIG_NONE;
if (!cmd->stop_src || tmp != cmd->stop_src)
err++;
if (err)
return 1;
/* step 2 */
if (err)
return 2;
/* step 3 */
if (cmd->start_arg != 0) {
cmd->start_arg = 0;
err++;
}
if (cmd->scan_begin_arg != 0) {
cmd->scan_begin_arg = 0;
err++;
}
if (cmd->convert_arg != 0) {
cmd->convert_arg = 0;
err++;
}
if (cmd->scan_end_arg != 1) {
cmd->scan_end_arg = 1;
err++;
}
if (cmd->stop_arg != 0) {
cmd->stop_arg = 0;
err++;
}
if (err)
return 3;
/* step 4 */
if (err)
return 4;
return 0;
}
static int subdev_8255_cmd(struct comedi_device *dev, struct comedi_subdevice * s)
{
/* FIXME */
return 0;
}
static int subdev_8255_cancel(struct comedi_device *dev, struct comedi_subdevice * s)
{
/* FIXME */
return 0;
}
int subdev_8255_init(struct comedi_device *dev, struct comedi_subdevice * s, int (*cb) (int,
int, int, unsigned long), unsigned long arg)
{
s->type = COMEDI_SUBD_DIO;
s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
s->n_chan = 24;
s->range_table = &range_digital;
s->maxdata = 1;
s->private = kmalloc(sizeof(struct subdev_8255_struct), GFP_KERNEL);
if (!s->private)
return -ENOMEM;
CALLBACK_ARG = arg;
if (cb == NULL) {
CALLBACK_FUNC = subdev_8255_cb;
} else {
CALLBACK_FUNC = cb;
}
s->insn_bits = subdev_8255_insn;
s->insn_config = subdev_8255_insn_config;
s->state = 0;
s->io_bits = 0;
do_config(dev, s);
return 0;
}
int subdev_8255_init_irq(struct comedi_device *dev, struct comedi_subdevice * s,
int (*cb) (int, int, int, unsigned long), unsigned long arg)
{
int ret;
ret = subdev_8255_init(dev, s, cb, arg);
if (ret < 0)
return ret;
s->do_cmdtest = subdev_8255_cmdtest;
s->do_cmd = subdev_8255_cmd;
s->cancel = subdev_8255_cancel;
subdevpriv->have_irq = 1;
return 0;
}
void subdev_8255_cleanup(struct comedi_device *dev, struct comedi_subdevice * s)
{
if (s->private) {
if (subdevpriv->have_irq) {
}
kfree(s->private);
}
}
/*
Start of the 8255 standalone device
*/
static int dev_8255_attach(struct comedi_device *dev, struct comedi_devconfig * it)
{
int ret;
unsigned long iobase;
int i;
printk("comedi%d: 8255:", dev->minor);
dev->board_name = "8255";
for (i = 0; i < COMEDI_NDEVCONFOPTS; i++) {
iobase = it->options[i];
if (!iobase)
break;
}
if (i == 0) {
printk(" no devices specified\n");
return -EINVAL;
}
if ((ret = alloc_subdevices(dev, i)) < 0)
return ret;
for (i = 0; i < dev->n_subdevices; i++) {
iobase = it->options[i];
printk(" 0x%04lx", iobase);
if (!request_region(iobase, _8255_SIZE, "8255")) {
printk(" (I/O port conflict)");
dev->subdevices[i].type = COMEDI_SUBD_UNUSED;
} else {
subdev_8255_init(dev, dev->subdevices + i, NULL,
iobase);
}
}
printk("\n");
return 0;
}
static int dev_8255_detach(struct comedi_device *dev)
{
int i;
unsigned long iobase;
struct comedi_subdevice *s;
printk("comedi%d: 8255: remove\n", dev->minor);
for (i = 0; i < dev->n_subdevices; i++) {
s = dev->subdevices + i;
if (s->type != COMEDI_SUBD_UNUSED) {
iobase = CALLBACK_ARG;
release_region(iobase, _8255_SIZE);
}
subdev_8255_cleanup(dev, s);
}
return 0;
}
EXPORT_SYMBOL(subdev_8255_init);
EXPORT_SYMBOL(subdev_8255_init_irq);
EXPORT_SYMBOL(subdev_8255_cleanup);
EXPORT_SYMBOL(subdev_8255_interrupt);

View file

@ -0,0 +1,57 @@
/*
module/8255.h
Header file for 8255
COMEDI - Linux Control and Measurement Device Interface
Copyright (C) 1998 David A. Schleef <ds@schleef.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef _8255_H
#define _8255_H
#include "../comedidev.h"
#if defined(CONFIG_COMEDI_8255) || defined(CONFIG_COMEDI_8255_MODULE)
int subdev_8255_init(struct comedi_device * dev, struct comedi_subdevice * s,
int (*cb) (int, int, int, unsigned long), unsigned long arg);
int subdev_8255_init_irq(struct comedi_device * dev, struct comedi_subdevice * s,
int (*cb) (int, int, int, unsigned long), unsigned long arg);
void subdev_8255_cleanup(struct comedi_device * dev, struct comedi_subdevice * s);
void subdev_8255_interrupt(struct comedi_device * dev, struct comedi_subdevice * s);
#else
static inline int subdev_8255_init(struct comedi_device * dev, struct comedi_subdevice * s,
void *x, unsigned long y)
{
printk("8255 support not configured -- disabling subdevice\n");
s->type = COMEDI_SUBD_UNUSED;
return 0;
}
static inline void subdev_8255_cleanup(struct comedi_device * dev,
struct comedi_subdevice * s)
{
}
#endif
#endif

View file

@ -8,12 +8,121 @@ obj-$(CONFIG_COMEDI) += comedi_test.o
obj-$(CONFIG_COMEDI) += comedi_parport.o
# Comedi PCI drivers
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += mite.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += 8255.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += acl7225b.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += addi_apci_035.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += addi_apci_1032.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += addi_apci_1500.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += addi_apci_1516.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += addi_apci_1564.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += addi_apci_16xx.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += addi_apci_2016.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += addi_apci_2032.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += addi_apci_2200.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += addi_apci_3001.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += addi_apci_3120.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += addi_apci_3501.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += addi_apci_3xxx.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += adl_pci6208.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += adl_pci7296.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += adl_pci7432.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += adl_pci8164.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += adl_pci9111.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += adl_pci9118.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += adq12b.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += adv_pci1710.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += adv_pci1723.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += adv_pci_dio.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += aio_aio12_8.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += aio_iiro_16.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += amplc_dio200.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += amplc_pc236.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += amplc_pc263.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += amplc_pci224.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += amplc_pci230.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += c6xdigio.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += cb_pcidas64.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += cb_pcidas.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += cb_pcidda.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += cb_pcidio.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += cb_pcimdas.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += cb_pcimdda.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += comedi_bond.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += comedi_parport.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += comedi_test.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += contec_pci_dio.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += daqboard2000.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += das08.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += das16m1.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += das16.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += das1800.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += das6402.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += das800.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += dmm32at.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += dt2801.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += dt2811.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += dt2814.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += dt2815.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += dt2817.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += dt282x.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += dt3000.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += fl512.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += gsc_hpdi.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += icp_multi.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += me_daq.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += ii_pci20kc.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += jr3_pci.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += ke_counter.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += me4000.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += me_daq.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += mite.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += mpc624.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += multiq3.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += ni_6527.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += ni_65xx.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += ni_660x.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += ni_670x.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += ni_at_a2150.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += ni_at_ao.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += ni_atmio16d.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += ni_atmio.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += ni_labpc.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += ni_pcidio.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += ni_pcimio.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += ni_tiocmd.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += ni_tio.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += pcl711.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += pcl724.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += pcl725.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += pcl726.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += pcl730.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += pcl812.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += pcl816.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += pcl818.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += pcm3724.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += pcm3730.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += pcmad.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += pcmda12.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += pcmmio.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += pcmuio.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += poc.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += rtd520.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += rti800.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += rti802.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += s526.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += s626.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += serial2002.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += skel.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += ssv_dnp.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += unioxx5.o
# Comedi PCMCIA drivers
obj-$(CONFIG_COMEDI_PCMCIA_DRIVERS) += cb_das16_cs.o
obj-$(CONFIG_COMEDI_PCMCIA_DRIVERS) += das08_cs.o
obj-$(CONFIG_COMEDI_PCMCIA_DRIVERS) += ni_daq_700.o
obj-$(CONFIG_COMEDI_PCMCIA_DRIVERS) += ni_daq_dio24.o
obj-$(CONFIG_COMEDI_PCMCIA_DRIVERS) += ni_labpc_cs.o
obj-$(CONFIG_COMEDI_PCMCIA_DRIVERS) += ni_mio_cs.o
obj-$(CONFIG_COMEDI_PCMCIA_DRIVERS) += quatech_daqp_cs.o
# Comedi USB drivers
obj-$(CONFIG_COMEDI_USB_DRIVERS) += usbdux.o

View file

@ -0,0 +1,149 @@
/*
* comedi/drivers/acl7225b.c
* Driver for Adlink NuDAQ ACL-7225b and clones
* José Luis Sánchez
*/
/*
Driver: acl7225b
Description: Adlink NuDAQ ACL-7225b & compatibles
Author: José Luis Sánchez (jsanchezv@teleline.es)
Status: testing
Devices: [Adlink] ACL-7225b (acl7225b), [ICP] P16R16DIO (p16r16dio)
*/
#include "../comedidev.h"
#include <linux/ioport.h>
#define ACL7225_SIZE 8 /* Requires 8 ioports, but only 4 are used */
#define P16R16DIO_SIZE 4
#define ACL7225_RIO_LO 0 /* Relays input/output low byte (R0-R7) */
#define ACL7225_RIO_HI 1 /* Relays input/output high byte (R8-R15) */
#define ACL7225_DI_LO 2 /* Digital input low byte (DI0-DI7) */
#define ACL7225_DI_HI 3 /* Digital input high byte (DI8-DI15) */
static int acl7225b_attach(struct comedi_device *dev, struct comedi_devconfig * it);
static int acl7225b_detach(struct comedi_device *dev);
struct boardtype {
const char *name; // driver name
int io_range; // len of I/O space
};
static const struct boardtype boardtypes[] = {
{"acl7225b", ACL7225_SIZE,},
{"p16r16dio", P16R16DIO_SIZE,},
};
#define n_boardtypes (sizeof(boardtypes)/sizeof(struct boardtype))
#define this_board ((const struct boardtype *)dev->board_ptr)
static struct comedi_driver driver_acl7225b = {
driver_name:"acl7225b",
module:THIS_MODULE,
attach:acl7225b_attach,
detach:acl7225b_detach,
board_name:&boardtypes[0].name,
num_names:n_boardtypes,
offset:sizeof(struct boardtype),
};
COMEDI_INITCLEANUP(driver_acl7225b);
static int acl7225b_do_insn(struct comedi_device *dev, struct comedi_subdevice * s,
struct comedi_insn * insn, unsigned int * data)
{
if (insn->n != 2)
return -EINVAL;
if (data[0]) {
s->state &= ~data[0];
s->state |= (data[0] & data[1]);
}
if (data[0] & 0x00ff)
outb(s->state & 0xff, dev->iobase + (unsigned long)s->private);
if (data[0] & 0xff00)
outb((s->state >> 8),
dev->iobase + (unsigned long)s->private + 1);
data[1] = s->state;
return 2;
}
static int acl7225b_di_insn(struct comedi_device *dev, struct comedi_subdevice * s,
struct comedi_insn * insn, unsigned int * data)
{
if (insn->n != 2)
return -EINVAL;
data[1] = inb(dev->iobase + (unsigned long)s->private) |
(inb(dev->iobase + (unsigned long)s->private + 1) << 8);
return 2;
}
static int acl7225b_attach(struct comedi_device *dev, struct comedi_devconfig * it)
{
struct comedi_subdevice *s;
int iobase, iorange;
iobase = it->options[0];
iorange = this_board->io_range;
printk("comedi%d: acl7225b: board=%s 0x%04x ", dev->minor,
this_board->name, iobase);
if (!request_region(iobase, iorange, "acl7225b")) {
printk("I/O port conflict\n");
return -EIO;
}
dev->board_name = this_board->name;
dev->iobase = iobase;
dev->irq = 0;
if (alloc_subdevices(dev, 3) < 0)
return -ENOMEM;
s = dev->subdevices + 0;
/* Relays outputs */
s->type = COMEDI_SUBD_DO;
s->subdev_flags = SDF_WRITABLE;
s->maxdata = 1;
s->n_chan = 16;
s->insn_bits = acl7225b_do_insn;
s->range_table = &range_digital;
s->private = (void *)ACL7225_RIO_LO;
s = dev->subdevices + 1;
/* Relays status */
s->type = COMEDI_SUBD_DI;
s->subdev_flags = SDF_READABLE;
s->maxdata = 1;
s->n_chan = 16;
s->insn_bits = acl7225b_di_insn;
s->range_table = &range_digital;
s->private = (void *)ACL7225_RIO_LO;
s = dev->subdevices + 2;
/* Isolated digital inputs */
s->type = COMEDI_SUBD_DI;
s->subdev_flags = SDF_READABLE;
s->maxdata = 1;
s->n_chan = 16;
s->insn_bits = acl7225b_di_insn;
s->range_table = &range_digital;
s->private = (void *)ACL7225_DI_LO;
printk("\n");
return 0;
}
static int acl7225b_detach(struct comedi_device *dev)
{
printk("comedi%d: acl7225b: remove\n", dev->minor);
if (dev->iobase)
release_region(dev->iobase, this_board->io_range);
return 0;
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,73 @@
/*
* Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
*
* ADDI-DATA GmbH
* Dieselstrasse 3
* D-77833 Ottersweier
* Tel: +19(0)7223/9493-0
* Fax: +49(0)7223/9493-92
* http://www.addi-data-com
* info@addi-data.com
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*/
#define APCI1710_PCI_BUS_CLOCK 0
#define APCI1710_FRONT_CONNECTOR_INPUT 1
#define APCI1710_TIMER_READVALUE 0
#define APCI1710_TIMER_GETOUTPUTLEVEL 1
#define APCI1710_TIMER_GETPROGRESSSTATUS 2
#define APCI1710_TIMER_WRITEVALUE 3
#define APCI1710_TIMER_READINTERRUPT 1
#define APCI1710_TIMER_READALLTIMER 2
/* BEGIN JK 27.10.03 : Add the possibility to use a 40 Mhz quartz */
#ifndef APCI1710_10MHZ
#define APCI1710_10MHZ 10
#endif
/* END JK 27.10.03 : Add the possibility to use a 40 Mhz quartz */
/*
* 82X54 TIMER INISIALISATION FUNCTION
*/
INT i_APCI1710_InsnConfigInitTimer(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
INT i_APCI1710_InsnWriteEnableDisableTimer(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
/*
* 82X54 READ FUNCTION
*/
INT i_APCI1710_InsnReadAllTimerValue(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
INT i_APCI1710_InsnBitsTimer(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
/*
* 82X54 READ & WRITE FUNCTION
*/
INT i_APCI1710_ReadTimerValue(struct comedi_device *dev,
BYTE b_ModulNbr, BYTE b_TimerNbr,
PULONG pul_TimerValue);
INT i_APCI1710_GetTimerOutputLevel(struct comedi_device *dev,
BYTE b_ModulNbr, BYTE b_TimerNbr,
PBYTE pb_OutputLevel);
INT i_APCI1710_GetTimerProgressStatus(struct comedi_device *dev,
BYTE b_ModulNbr, BYTE b_TimerNbr,
PBYTE pb_TimerStatus);
/*
* 82X54 WRITE FUNCTION
*/
INT i_APCI1710_WriteTimerValue(struct comedi_device *dev,
BYTE b_ModulNbr, BYTE b_TimerNbr,
ULONG ul_WriteValue);

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,74 @@
/*
* Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
*
* ADDI-DATA GmbH
* Dieselstrasse 3
* D-77833 Ottersweier
* Tel: +19(0)7223/9493-0
* Fax: +49(0)7223/9493-92
* http://www.addi-data-com
* info@addi-data.com
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*/
#define APCI1710_30MHZ 30
#define APCI1710_33MHZ 33
#define APCI1710_40MHZ 40
#define APCI1710_SINGLE 0
#define APCI1710_CONTINUOUS 1
#define APCI1710_CHRONO_PROGRESS_STATUS 0
#define APCI1710_CHRONO_READVALUE 1
#define APCI1710_CHRONO_CONVERTVALUE 2
#define APCI1710_CHRONO_READINTERRUPT 3
#define APCI1710_CHRONO_SET_CHANNELON 0
#define APCI1710_CHRONO_SET_CHANNELOFF 1
#define APCI1710_CHRONO_READ_CHANNEL 2
#define APCI1710_CHRONO_READ_PORT 3
/*
* CHRONOMETER INISIALISATION FUNCTION
*/
INT i_APCI1710_InsnConfigInitChrono(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
INT i_APCI1710_InsnWriteEnableDisableChrono(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data);
/*
* CHRONOMETER READ FUNCTION
*/
INT i_APCI1710_InsnReadChrono(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
INT i_APCI1710_GetChronoProgressStatus(struct comedi_device *dev,
BYTE b_ModulNbr, PBYTE pb_ChronoStatus);
INT i_APCI1710_ReadChronoValue(struct comedi_device *dev,
BYTE b_ModulNbr,
UINT ui_TimeOut, PBYTE pb_ChronoStatus,
PULONG pul_ChronoValue);
INT i_APCI1710_ConvertChronoValue(struct comedi_device *dev,
BYTE b_ModulNbr,
ULONG ul_ChronoValue,
PULONG pul_Hour,
PBYTE pb_Minute,
PBYTE pb_Second,
PUINT pui_MilliSecond, PUINT pui_MicroSecond,
PUINT pui_NanoSecond);
/*
* CHRONOMETER DIGITAL INPUT OUTPUT FUNCTION
*/
INT i_APCI1710_InsnBitsChronoDigitalIO(struct comedi_device *dev,
struct comedi_subdevice *s, struct comedi_insn *insn,
unsigned int *data);

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,46 @@
/*
* Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
*
* ADDI-DATA GmbH
* Dieselstrasse 3
* D-77833 Ottersweier
* Tel: +19(0)7223/9493-0
* Fax: +49(0)7223/9493-92
* http://www.addi-data-com
* info@addi-data.com
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*/
#define APCI1710_ON 1 /* Digital Output ON or OFF */
#define APCI1710_OFF 0
#define APCI1710_INPUT 0 /* Digital I/O */
#define APCI1710_OUTPUT 1
#define APCI1710_DIGIO_MEMORYONOFF 0x10
#define APCI1710_DIGIO_INIT 0x11
/*
* DIGITAL I/O INISIALISATION FUNCTION
*/
INT i_APCI1710_InsnConfigDigitalIO(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
/*
* INPUT OUTPUT FUNCTIONS
*/
INT i_APCI1710_InsnReadDigitalIOChlValue(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
INT i_APCI1710_InsnWriteDigitalIOChlOnOff(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
INT i_APCI1710_InsnBitsDigitalIOPortOnOff(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,271 @@
/*
* Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
*
* ADDI-DATA GmbH
* Dieselstrasse 3
* D-77833 Ottersweier
* Tel: +19(0)7223/9493-0
* Fax: +49(0)7223/9493-92
* http://www.addi-data-com
* info@addi-data.com
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*/
#define APCI1710_16BIT_COUNTER 0x10
#define APCI1710_32BIT_COUNTER 0x0
#define APCI1710_QUADRUPLE_MODE 0x0
#define APCI1710_DOUBLE_MODE 0x3
#define APCI1710_SIMPLE_MODE 0xF
#define APCI1710_DIRECT_MODE 0x80
#define APCI1710_HYSTERESIS_ON 0x60
#define APCI1710_HYSTERESIS_OFF 0x0
#define APCI1710_INCREMENT 0x60
#define APCI1710_DECREMENT 0x0
#define APCI1710_LATCH_COUNTER 0x1
#define APCI1710_CLEAR_COUNTER 0x0
#define APCI1710_LOW 0x0
#define APCI1710_HIGH 0x1
/*********************/
/* Version 0600-0229 */
/*********************/
#define APCI1710_HIGH_EDGE_CLEAR_COUNTER 0x0
#define APCI1710_HIGH_EDGE_LATCH_COUNTER 0x1
#define APCI1710_LOW_EDGE_CLEAR_COUNTER 0x2
#define APCI1710_LOW_EDGE_LATCH_COUNTER 0x3
#define APCI1710_HIGH_EDGE_LATCH_AND_CLEAR_COUNTER 0x4
#define APCI1710_LOW_EDGE_LATCH_AND_CLEAR_COUNTER 0x5
#define APCI1710_SOURCE_0 0x0
#define APCI1710_SOURCE_1 0x1
#define APCI1710_30MHZ 30
#define APCI1710_33MHZ 33
#define APCI1710_40MHZ 40
#define APCI1710_ENABLE_LATCH_INT 0x80
#define APCI1710_DISABLE_LATCH_INT (~APCI1710_ENABLE_LATCH_INT)
#define APCI1710_INDEX_LATCH_COUNTER 0x10
#define APCI1710_INDEX_AUTO_MODE 0x8
#define APCI1710_ENABLE_INDEX 0x4
#define APCI1710_DISABLE_INDEX (~APCI1710_ENABLE_INDEX)
#define APCI1710_ENABLE_LATCH_AND_CLEAR 0x8
#define APCI1710_DISABLE_LATCH_AND_CLEAR (~APCI1710_ENABLE_LATCH_AND_CLEAR)
#define APCI1710_SET_LOW_INDEX_LEVEL 0x4
#define APCI1710_SET_HIGH_INDEX_LEVEL (~APCI1710_SET_LOW_INDEX_LEVEL)
#define APCI1710_INVERT_INDEX_RFERENCE 0x2
#define APCI1710_DEFAULT_INDEX_RFERENCE (~APCI1710_INVERT_INDEX_RFERENCE)
#define APCI1710_ENABLE_INDEX_INT 0x1
#define APCI1710_DISABLE_INDEX_INT (~APCI1710_ENABLE_INDEX_INT)
#define APCI1710_ENABLE_FREQUENCY 0x4
#define APCI1710_DISABLE_FREQUENCY (~APCI1710_ENABLE_FREQUENCY)
#define APCI1710_ENABLE_FREQUENCY_INT 0x8
#define APCI1710_DISABLE_FREQUENCY_INT (~APCI1710_ENABLE_FREQUENCY_INT)
#define APCI1710_ENABLE_40MHZ_FREQUENCY 0x40
#define APCI1710_DISABLE_40MHZ_FREQUENCY (~APCI1710_ENABLE_40MHZ_FREQUENCY)
#define APCI1710_ENABLE_40MHZ_FILTER 0x80
#define APCI1710_DISABLE_40MHZ_FILTER (~APCI1710_ENABLE_40MHZ_FILTER)
#define APCI1710_ENABLE_COMPARE_INT 0x2
#define APCI1710_DISABLE_COMPARE_INT (~APCI1710_ENABLE_COMPARE_INT)
#define APCI1710_ENABLE_INDEX_ACTION 0x20
#define APCI1710_DISABLE_INDEX_ACTION (~APCI1710_ENABLE_INDEX_ACTION)
#define APCI1710_REFERENCE_HIGH 0x40
#define APCI1710_REFERENCE_LOW (~APCI1710_REFERENCE_HIGH)
#define APCI1710_TOR_GATE_LOW 0x40
#define APCI1710_TOR_GATE_HIGH (~APCI1710_TOR_GATE_LOW)
/* INSN CONFIG */
#define APCI1710_INCCPT_INITCOUNTER 100
#define APCI1710_INCCPT_COUNTERAUTOTEST 101
#define APCI1710_INCCPT_INITINDEX 102
#define APCI1710_INCCPT_INITREFERENCE 103
#define APCI1710_INCCPT_INITEXTERNALSTROBE 104
#define APCI1710_INCCPT_INITCOMPARELOGIC 105
#define APCI1710_INCCPT_INITFREQUENCYMEASUREMENT 106
/* INSN READ */
#define APCI1710_INCCPT_READLATCHREGISTERSTATUS 200
#define APCI1710_INCCPT_READLATCHREGISTERVALUE 201
#define APCI1710_INCCPT_READ16BITCOUNTERVALUE 202
#define APCI1710_INCCPT_READ32BITCOUNTERVALUE 203
#define APCI1710_INCCPT_GETINDEXSTATUS 204
#define APCI1710_INCCPT_GETREFERENCESTATUS 205
#define APCI1710_INCCPT_GETUASSTATUS 206
#define APCI1710_INCCPT_GETCBSTATUS 207
#define APCI1710_INCCPT_GET16BITCBSTATUS 208
#define APCI1710_INCCPT_GETUDSTATUS 209
#define APCI1710_INCCPT_GETINTERRUPTUDLATCHEDSTATUS 210
#define APCI1710_INCCPT_READFREQUENCYMEASUREMENT 211
#define APCI1710_INCCPT_READINTERRUPT 212
/* INSN BITS */
#define APCI1710_INCCPT_CLEARCOUNTERVALUE 300
#define APCI1710_INCCPT_CLEARALLCOUNTERVALUE 301
#define APCI1710_INCCPT_SETINPUTFILTER 302
#define APCI1710_INCCPT_LATCHCOUNTER 303
#define APCI1710_INCCPT_SETINDEXANDREFERENCESOURCE 304
#define APCI1710_INCCPT_SETDIGITALCHLON 305
#define APCI1710_INCCPT_SETDIGITALCHLOFF 306
/* INSN WRITE */
#define APCI1710_INCCPT_ENABLELATCHINTERRUPT 400
#define APCI1710_INCCPT_DISABLELATCHINTERRUPT 401
#define APCI1710_INCCPT_WRITE16BITCOUNTERVALUE 402
#define APCI1710_INCCPT_WRITE32BITCOUNTERVALUE 403
#define APCI1710_INCCPT_ENABLEINDEX 404
#define APCI1710_INCCPT_DISABLEINDEX 405
#define APCI1710_INCCPT_ENABLECOMPARELOGIC 406
#define APCI1710_INCCPT_DISABLECOMPARELOGIC 407
#define APCI1710_INCCPT_ENABLEFREQUENCYMEASUREMENT 408
#define APCI1710_INCCPT_DISABLEFREQUENCYMEASUREMENT 409
/************ Main Functions *************/
INT i_APCI1710_InsnConfigINCCPT(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int * data);
INT i_APCI1710_InsnBitsINCCPT(struct comedi_device *dev, struct comedi_subdevice * s,
struct comedi_insn *insn, unsigned int * data);
INT i_APCI1710_InsnWriteINCCPT(struct comedi_device *dev, struct comedi_subdevice * s,
struct comedi_insn *insn, unsigned int * data);
INT i_APCI1710_InsnReadINCCPT(struct comedi_device *dev, struct comedi_subdevice * s,
struct comedi_insn *insn, unsigned int * data);
/*********** Supplementary Functions********/
/* INSN CONFIG */
INT i_APCI1710_InitCounter(struct comedi_device *dev,
BYTE b_ModulNbr,
BYTE b_CounterRange,
BYTE b_FirstCounterModus,
BYTE b_FirstCounterOption,
BYTE b_SecondCounterModus,
BYTE b_SecondCounterOption);
INT i_APCI1710_CounterAutoTest(struct comedi_device *dev, PBYTE pb_TestStatus);
INT i_APCI1710_InitIndex(struct comedi_device *dev,
BYTE b_ModulNbr,
BYTE b_ReferenceAction,
BYTE b_IndexOperation, BYTE b_AutoMode,
BYTE b_InterruptEnable);
INT i_APCI1710_InitReference(struct comedi_device *dev,
BYTE b_ModulNbr, BYTE b_ReferenceLevel);
INT i_APCI1710_InitExternalStrobe(struct comedi_device *dev,
BYTE b_ModulNbr, BYTE b_ExternalStrobe,
BYTE b_ExternalStrobeLevel);
INT i_APCI1710_InitCompareLogic(struct comedi_device *dev,
BYTE b_ModulNbr, UINT ui_CompareValue);
INT i_APCI1710_InitFrequencyMeasurement(struct comedi_device *dev,
BYTE b_ModulNbr,
BYTE b_PCIInputClock,
BYTE b_TimingUnity,
ULONG ul_TimingInterval,
PULONG pul_RealTimingInterval);
/* INSN BITS */
INT i_APCI1710_ClearCounterValue(struct comedi_device *dev, BYTE b_ModulNbr);
INT i_APCI1710_ClearAllCounterValue(struct comedi_device *dev);
INT i_APCI1710_SetInputFilter(struct comedi_device *dev,
BYTE b_ModulNbr, BYTE b_PCIInputClock,
BYTE b_Filter);
INT i_APCI1710_LatchCounter(struct comedi_device *dev,
BYTE b_ModulNbr, BYTE b_LatchReg);
INT i_APCI1710_SetIndexAndReferenceSource(struct comedi_device *dev,
BYTE b_ModulNbr,
BYTE b_SourceSelection);
INT i_APCI1710_SetDigitalChlOn(struct comedi_device *dev, BYTE b_ModulNbr);
INT i_APCI1710_SetDigitalChlOff(struct comedi_device *dev, BYTE b_ModulNbr);
/* INSN WRITE */
INT i_APCI1710_EnableLatchInterrupt(struct comedi_device *dev, BYTE b_ModulNbr);
INT i_APCI1710_DisableLatchInterrupt(struct comedi_device *dev, BYTE b_ModulNbr);
INT i_APCI1710_Write16BitCounterValue(struct comedi_device *dev,
BYTE b_ModulNbr, BYTE b_SelectedCounter,
UINT ui_WriteValue);
INT i_APCI1710_Write32BitCounterValue(struct comedi_device *dev,
BYTE b_ModulNbr, ULONG ul_WriteValue);
INT i_APCI1710_EnableIndex(struct comedi_device *dev, BYTE b_ModulNbr);
INT i_APCI1710_DisableIndex(struct comedi_device *dev, BYTE b_ModulNbr);
INT i_APCI1710_EnableCompareLogic(struct comedi_device *dev, BYTE b_ModulNbr);
INT i_APCI1710_DisableCompareLogic(struct comedi_device *dev, BYTE b_ModulNbr);
INT i_APCI1710_EnableFrequencyMeasurement(struct comedi_device *dev,
BYTE b_ModulNbr,
BYTE b_InterruptEnable);
INT i_APCI1710_DisableFrequencyMeasurement(struct comedi_device *dev,
BYTE b_ModulNbr);
/* INSN READ */
INT i_APCI1710_ReadLatchRegisterStatus(struct comedi_device *dev,
BYTE b_ModulNbr, BYTE b_LatchReg,
PBYTE pb_LatchStatus);
INT i_APCI1710_ReadLatchRegisterValue(struct comedi_device *dev,
BYTE b_ModulNbr, BYTE b_LatchReg,
PULONG pul_LatchValue);
INT i_APCI1710_Read16BitCounterValue(struct comedi_device *dev,
BYTE b_ModulNbr, BYTE b_SelectedCounter,
PUINT pui_CounterValue);
INT i_APCI1710_Read32BitCounterValue(struct comedi_device *dev,
BYTE b_ModulNbr, PULONG pul_CounterValue);
INT i_APCI1710_GetIndexStatus(struct comedi_device *dev,
BYTE b_ModulNbr, PBYTE pb_IndexStatus);
INT i_APCI1710_GetReferenceStatus(struct comedi_device *dev,
BYTE b_ModulNbr, PBYTE pb_ReferenceStatus);
INT i_APCI1710_GetUASStatus(struct comedi_device *dev,
BYTE b_ModulNbr, PBYTE pb_UASStatus);
INT i_APCI1710_GetCBStatus(struct comedi_device *dev,
BYTE b_ModulNbr, PBYTE pb_CBStatus);
INT i_APCI1710_Get16BitCBStatus(struct comedi_device *dev,
BYTE b_ModulNbr, PBYTE pb_CBStatusCounter0,
PBYTE pb_CBStatusCounter1);
INT i_APCI1710_GetUDStatus(struct comedi_device *dev,
BYTE b_ModulNbr, PBYTE pb_UDStatus);
INT i_APCI1710_GetInterruptUDLatchedStatus(struct comedi_device *dev,
BYTE b_ModulNbr, PBYTE pb_UDStatus);
INT i_APCI1710_ReadFrequencyMeasurement(struct comedi_device *dev,
BYTE b_ModulNbr,
PBYTE pb_Status, PBYTE pb_UDStatus,
PULONG pul_ReadValue);

View file

@ -0,0 +1,861 @@
/**
@verbatim
Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
ADDI-DATA GmbH
Dieselstrasse 3
D-77833 Ottersweier
Tel: +19(0)7223/9493-0
Fax: +49(0)7223/9493-92
http://www.addi-data-com
info@addi-data.com
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
You shoud also find the complete GPL in the COPYING file accompanying this source code.
@endverbatim
*/
/*
+-----------------------------------------------------------------------+
| (C) ADDI-DATA GmbH Dieselstraße 3 D-77833 Ottersweier |
+-----------------------------------------------------------------------+
| Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com |
| Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com |
+-----------------------------------------------------------------------+
| Project : API APCI1710 | Compiler : gcc |
| Module name : Inp_CPT.C | Version : 2.96 |
+-------------------------------+---------------------------------------+
| Project manager: Eric Stolz | Date : 02/12/2002 |
+-----------------------------------------------------------------------+
| Description : APCI-1710 pulse encoder module |
| |
| |
+-----------------------------------------------------------------------+
| UPDATES |
+-----------------------------------------------------------------------+
| Date | Author | Description of updates |
+----------+-----------+------------------------------------------------+
| | | |
|----------|-----------|------------------------------------------------|
| 08/05/00 | Guinot C | - 0400/0228 All Function in RING 0 |
| | | available |
+-----------------------------------------------------------------------+
*/
/*
+----------------------------------------------------------------------------+
| Included files |
+----------------------------------------------------------------------------+
*/
#include "APCI1710_Inp_cpt.h"
/*
+----------------------------------------------------------------------------+
| Function Name : _INT_ i_APCI1710_InitPulseEncoder |
| (BYTE_ b_BoardHandle, |
| BYTE_ b_ModulNbr, |
| BYTE_ b_PulseEncoderNbr, |
| BYTE_ b_InputLevelSelection, |
| BYTE_ b_TriggerOutputAction, |
| ULONG_ ul_StartValue) |
+----------------------------------------------------------------------------+
| Task : Configure the pulse encoder operating mode selected via|
| b_ModulNbr and b_PulseEncoderNbr. The pulse encoder |
| after each pulse decrement the counter value from 1. |
| |
| You must calling this function be for you call any |
| other function witch access of pulse encoders. |
+----------------------------------------------------------------------------+
| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710|
| BYTE_ b_ModulNbr : Module number to |
| configure (0 to 3) |
| BYTE_ b_PulseEncoderNbr : Pulse encoder selection |
| (0 to 3) |
| BYTE_ b_InputLevelSelection : Input level selection |
| (0 or 1) |
| 0 : Set pulse encoder|
| count the the low|
| level pulse. |
| 1 : Set pulse encoder|
| count the the |
| high level pulse.|
| BYTE_ b_TriggerOutputAction : Digital TRIGGER output |
| action |
| 0 : No action |
| 1 : Set the trigger |
| output to "1" |
| (high) after the |
| passage from 1 to|
| 0 from pulse |
| encoder. |
| 2 : Set the trigger |
| output to "0" |
| (low) after the |
| passage from 1 to|
| 0 from pulse |
| encoder |
| ULONG_ ul_StartValue : Pulse encoder start value|
| (1 to 4294967295)
b_ModulNbr =(BYTE) CR_AREF(insn->chanspec);
b_PulseEncoderNbr =(BYTE) data[0];
b_InputLevelSelection =(BYTE) data[1];
b_TriggerOutputAction =(BYTE) data[2];
ul_StartValue =(ULONG) data[3];
|
+----------------------------------------------------------------------------+
| Output Parameters : - |
+----------------------------------------------------------------------------+
| Return Value : 0: No error |
| -1: The handle parameter of the board is wrong |
| -2: The module is not a pulse encoder module |
| -3: Pulse encoder selection is wrong |
| -4: Input level selection is wrong |
| -5: Digital TRIGGER output action selection is wrong |
| -6: Pulse encoder start value is wrong |
+----------------------------------------------------------------------------+
*/
INT i_APCI1710_InsnConfigInitPulseEncoder(struct comedi_device * dev,
struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
{
INT i_ReturnValue = 0;
DWORD dw_IntRegister;
BYTE b_ModulNbr;
BYTE b_PulseEncoderNbr;
BYTE b_InputLevelSelection;
BYTE b_TriggerOutputAction;
ULONG ul_StartValue;
b_ModulNbr = (BYTE) CR_AREF(insn->chanspec);
b_PulseEncoderNbr = (BYTE) data[0];
b_InputLevelSelection = (BYTE) data[1];
b_TriggerOutputAction = (BYTE) data[2];
ul_StartValue = (ULONG) data[3];
i_ReturnValue = insn->n;
/***********************************/
/* Test the selected module number */
/***********************************/
if (b_ModulNbr <= 3) {
/*************************/
/* Test if pulse encoder */
/*************************/
if ((devpriv->s_BoardInfos.
dw_MolduleConfiguration[b_ModulNbr] &
APCI1710_PULSE_ENCODER) ==
APCI1710_PULSE_ENCODER) {
/******************************************/
/* Test the selected pulse encoder number */
/******************************************/
if (b_PulseEncoderNbr <= 3) {
/************************/
/* Test the input level */
/************************/
if ((b_InputLevelSelection == 0)
|| (b_InputLevelSelection == 1)) {
/*******************************************/
/* Test the ouput TRIGGER action selection */
/*******************************************/
if ((b_TriggerOutputAction <= 2)
|| (b_PulseEncoderNbr > 0)) {
if (ul_StartValue > 1) {
dw_IntRegister =
inl(devpriv->
s_BoardInfos.
ui_Address +
20 +
(64 * b_ModulNbr));
/***********************/
/* Set the start value */
/***********************/
outl(ul_StartValue,
devpriv->
s_BoardInfos.
ui_Address +
(b_PulseEncoderNbr
* 4) +
(64 * b_ModulNbr));
/***********************/
/* Set the input level */
/***********************/
devpriv->
s_ModuleInfo
[b_ModulNbr].
s_PulseEncoderModuleInfo.
dw_SetRegister =
(devpriv->
s_ModuleInfo
[b_ModulNbr].
s_PulseEncoderModuleInfo.
dw_SetRegister &
(0xFFFFFFFFUL -
(1UL << (8 + b_PulseEncoderNbr)))) | ((1UL & (~b_InputLevelSelection)) << (8 + b_PulseEncoderNbr));
/*******************************/
/* Test if output trigger used */
/*******************************/
if ((b_TriggerOutputAction > 0) && (b_PulseEncoderNbr > 1)) {
/****************************/
/* Enable the output action */
/****************************/
devpriv->
s_ModuleInfo
[b_ModulNbr].
s_PulseEncoderModuleInfo.
dw_SetRegister
=
devpriv->
s_ModuleInfo
[b_ModulNbr].
s_PulseEncoderModuleInfo.
dw_SetRegister
| (1UL
<< (4 + b_PulseEncoderNbr));
/*********************************/
/* Set the output TRIGGER action */
/*********************************/
devpriv->
s_ModuleInfo
[b_ModulNbr].
s_PulseEncoderModuleInfo.
dw_SetRegister
=
(devpriv->
s_ModuleInfo
[b_ModulNbr].
s_PulseEncoderModuleInfo.
dw_SetRegister
&
(0xFFFFFFFFUL
-
(1UL << (12 + b_PulseEncoderNbr)))) | ((1UL & (b_TriggerOutputAction - 1)) << (12 + b_PulseEncoderNbr));
} else {
/*****************************/
/* Disable the output action */
/*****************************/
devpriv->
s_ModuleInfo
[b_ModulNbr].
s_PulseEncoderModuleInfo.
dw_SetRegister
=
devpriv->
s_ModuleInfo
[b_ModulNbr].
s_PulseEncoderModuleInfo.
dw_SetRegister
&
(0xFFFFFFFFUL
-
(1UL << (4 + b_PulseEncoderNbr)));
}
/*************************/
/* Set the configuration */
/*************************/
outl(devpriv->
s_ModuleInfo
[b_ModulNbr].
s_PulseEncoderModuleInfo.
dw_SetRegister,
devpriv->
s_BoardInfos.
ui_Address +
20 +
(64 * b_ModulNbr));
devpriv->
s_ModuleInfo
[b_ModulNbr].
s_PulseEncoderModuleInfo.
s_PulseEncoderInfo
[b_PulseEncoderNbr].
b_PulseEncoderInit
= 1;
} else {
/**************************************/
/* Pulse encoder start value is wrong */
/**************************************/
DPRINTK("Pulse encoder start value is wrong\n");
i_ReturnValue = -6;
}
} else {
/****************************************************/
/* Digital TRIGGER output action selection is wrong */
/****************************************************/
DPRINTK("Digital TRIGGER output action selection is wrong\n");
i_ReturnValue = -5;
}
} else {
/**********************************/
/* Input level selection is wrong */
/**********************************/
DPRINTK("Input level selection is wrong\n");
i_ReturnValue = -4;
}
} else {
/************************************/
/* Pulse encoder selection is wrong */
/************************************/
DPRINTK("Pulse encoder selection is wrong\n");
i_ReturnValue = -3;
}
} else {
/********************************************/
/* The module is not a pulse encoder module */
/********************************************/
DPRINTK("The module is not a pulse encoder module\n");
i_ReturnValue = -2;
}
} else {
/********************************************/
/* The module is not a pulse encoder module */
/********************************************/
DPRINTK("The module is not a pulse encoder module\n");
i_ReturnValue = -2;
}
return (i_ReturnValue);
}
/*
+----------------------------------------------------------------------------+
| Function Name : _INT_ i_APCI1710_EnablePulseEncoder |
| (BYTE_ b_BoardHandle, |
| BYTE_ b_ModulNbr, |
| BYTE_ b_PulseEncoderNbr, |
| BYTE_ b_CycleSelection, |
| BYTE_ b_InterruptHandling) |
+----------------------------------------------------------------------------+
| Task : Enableor disable the selected pulse encoder (b_PulseEncoderNbr) |
| from selected module (b_ModulNbr). Each input pulse |
| decrement the pulse encoder counter value from 1. |
| If you enabled the interrupt (b_InterruptHandling), a |
| interrupt is generated when the pulse encoder has run |
| down. |
+----------------------------------------------------------------------------+
| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710|
| BYTE_ b_ModulNbr : Module number to |
| configure (0 to 3) |
| BYTE_ b_PulseEncoderNbr : Pulse encoder selection |
| (0 to 3) |
| BYTE_ b_CycleSelection : APCI1710_CONTINUOUS: |
| Each time the |
| counting value is set|
| on "0", the pulse |
| encoder load the |
| start value after |
| the next pulse. |
| APCI1710_SINGLE: |
| If the counter is set|
| on "0", the pulse |
| encoder is stopped. |
| BYTE_ b_InterruptHandling : Interrupts can be |
| generated, when the pulse|
| encoder has run down. |
| With this parameter the |
| user decides if |
| interrupts are used or |
| not. |
| APCI1710_ENABLE: |
| Interrupts are enabled |
| APCI1710_DISABLE: |
| Interrupts are disabled
b_ModulNbr =(BYTE) CR_AREF(insn->chanspec);
b_Action =(BYTE) data[0];
b_PulseEncoderNbr =(BYTE) data[1];
b_CycleSelection =(BYTE) data[2];
b_InterruptHandling =(BYTE) data[3];|
+----------------------------------------------------------------------------+
| Output Parameters : - |
+----------------------------------------------------------------------------+
| Return Value : 0: No error |
| -1: The handle parameter of the board is wrong |
| -2: Module selection is wrong |
| -3: Pulse encoder selection is wrong |
| -4: Pulse encoder not initialised. |
| See function "i_APCI1710_InitPulseEncoder" |
| -5: Cycle selection mode is wrong |
| -6: Interrupt handling mode is wrong |
| -7: Interrupt routine not installed. |
| See function "i_APCI1710_SetBoardIntRoutineX" |
+----------------------------------------------------------------------------+
*/
INT i_APCI1710_InsnWriteEnableDisablePulseEncoder(struct comedi_device * dev,
struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
{
INT i_ReturnValue = 0;
BYTE b_ModulNbr;
BYTE b_PulseEncoderNbr;
BYTE b_CycleSelection;
BYTE b_InterruptHandling;
BYTE b_Action;
i_ReturnValue = insn->n;
b_ModulNbr = (BYTE) CR_AREF(insn->chanspec);
b_Action = (BYTE) data[0];
b_PulseEncoderNbr = (BYTE) data[1];
b_CycleSelection = (BYTE) data[2];
b_InterruptHandling = (BYTE) data[3];
/***********************************/
/* Test the selected module number */
/***********************************/
if (b_ModulNbr <= 3) {
/******************************************/
/* Test the selected pulse encoder number */
/******************************************/
if (b_PulseEncoderNbr <= 3) {
/*************************************/
/* Test if pulse encoder initialised */
/*************************************/
if (devpriv->s_ModuleInfo[b_ModulNbr].
s_PulseEncoderModuleInfo.
s_PulseEncoderInfo[b_PulseEncoderNbr].
b_PulseEncoderInit == 1) {
switch (b_Action) {
case APCI1710_ENABLE:
/****************************/
/* Test the cycle selection */
/****************************/
if (b_CycleSelection ==
APCI1710_CONTINUOUS
|| b_CycleSelection ==
APCI1710_SINGLE) {
/*******************************/
/* Test the interrupt handling */
/*******************************/
if (b_InterruptHandling ==
APCI1710_ENABLE
|| b_InterruptHandling
== APCI1710_DISABLE) {
/******************************/
/* Test if interrupt not used */
/******************************/
if (b_InterruptHandling
==
APCI1710_DISABLE)
{
/*************************/
/* Disable the interrupt */
/*************************/
devpriv->
s_ModuleInfo
[b_ModulNbr].
s_PulseEncoderModuleInfo.
dw_SetRegister
=
devpriv->
s_ModuleInfo
[b_ModulNbr].
s_PulseEncoderModuleInfo.
dw_SetRegister
&
(0xFFFFFFFFUL
-
(1UL << b_PulseEncoderNbr));
} else {
/************************/
/* Enable the interrupt */
/************************/
devpriv->
s_ModuleInfo
[b_ModulNbr].
s_PulseEncoderModuleInfo.
dw_SetRegister
=
devpriv->
s_ModuleInfo
[b_ModulNbr].
s_PulseEncoderModuleInfo.
dw_SetRegister
| (1UL
<<
b_PulseEncoderNbr);
devpriv->tsk_Current = current; // Save the current process task structure
}
if (i_ReturnValue >= 0) {
/***********************************/
/* Enable or disable the interrupt */
/***********************************/
outl(devpriv->
s_ModuleInfo
[b_ModulNbr].
s_PulseEncoderModuleInfo.
dw_SetRegister,
devpriv->
s_BoardInfos.
ui_Address
+ 20 +
(64 * b_ModulNbr));
/****************************/
/* Enable the pulse encoder */
/****************************/
devpriv->
s_ModuleInfo
[b_ModulNbr].
s_PulseEncoderModuleInfo.
dw_ControlRegister
=
devpriv->
s_ModuleInfo
[b_ModulNbr].
s_PulseEncoderModuleInfo.
dw_ControlRegister
| (1UL
<<
b_PulseEncoderNbr);
/**********************/
/* Set the cycle mode */
/**********************/
devpriv->
s_ModuleInfo
[b_ModulNbr].
s_PulseEncoderModuleInfo.
dw_ControlRegister
=
(devpriv->
s_ModuleInfo
[b_ModulNbr].
s_PulseEncoderModuleInfo.
dw_ControlRegister
&
(0xFFFFFFFFUL
-
(1 << (b_PulseEncoderNbr + 4)))) | ((b_CycleSelection & 1UL) << (4 + b_PulseEncoderNbr));
/****************************/
/* Enable the pulse encoder */
/****************************/
outl(devpriv->
s_ModuleInfo
[b_ModulNbr].
s_PulseEncoderModuleInfo.
dw_ControlRegister,
devpriv->
s_BoardInfos.
ui_Address
+ 16 +
(64 * b_ModulNbr));
}
} else {
/************************************/
/* Interrupt handling mode is wrong */
/************************************/
DPRINTK("Interrupt handling mode is wrong\n");
i_ReturnValue = -6;
}
} else {
/*********************************/
/* Cycle selection mode is wrong */
/*********************************/
DPRINTK("Cycle selection mode is wrong\n");
i_ReturnValue = -5;
}
break;
case APCI1710_DISABLE:
devpriv->s_ModuleInfo[b_ModulNbr].
s_PulseEncoderModuleInfo.
dw_ControlRegister =
devpriv->
s_ModuleInfo[b_ModulNbr].
s_PulseEncoderModuleInfo.
dw_ControlRegister &
(0xFFFFFFFFUL -
(1UL << b_PulseEncoderNbr));
/*****************************/
/* Disable the pulse encoder */
/*****************************/
outl(devpriv->s_ModuleInfo[b_ModulNbr].
s_PulseEncoderModuleInfo.
dw_ControlRegister,
devpriv->s_BoardInfos.
ui_Address + 16 +
(64 * b_ModulNbr));
break;
} // switch End
} else {
/*********************************/
/* Pulse encoder not initialised */
/*********************************/
DPRINTK("Pulse encoder not initialised\n");
i_ReturnValue = -4;
}
} else {
/************************************/
/* Pulse encoder selection is wrong */
/************************************/
DPRINTK("Pulse encoder selection is wrong\n");
i_ReturnValue = -3;
}
} else {
/*****************************/
/* Module selection is wrong */
/*****************************/
DPRINTK("Module selection is wrong\n");
i_ReturnValue = -2;
}
return (i_ReturnValue);
}
/*
+----------------------------------------------------------------------------+
| Function Name : _INT_ i_APCI1710_ReadPulseEncoderStatus |
| (BYTE_ b_BoardHandle, |
| BYTE_ b_ModulNbr, |
| BYTE_ b_PulseEncoderNbr, |
| PBYTE_ pb_Status) |
+----------------------------------------------------------------------------+
| Task APCI1710_PULSEENCODER_READ : Reads the pulse encoder status
and valuefrom selected pulse |
| encoder (b_PulseEncoderNbr) from selected module |
| (b_ModulNbr). |
+----------------------------------------------------------------------------+
BYTE b_Type; data[0]
APCI1710_PULSEENCODER_WRITE
Writes a 32-bit value (ul_WriteValue) into the selected|
| pulse encoder (b_PulseEncoderNbr) from selected module |
| (b_ModulNbr). This operation set the new start pulse |
| encoder value.
APCI1710_PULSEENCODER_READ
| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710|
| CRAREF() BYTE_ b_ModulNbr : Module number to |
| configure (0 to 3) |
| data[1] BYTE_ b_PulseEncoderNbr : Pulse encoder selection |
| (0 to 3)
APCI1710_PULSEENCODER_WRITE
data[2] ULONG_ ul_WriteValue : 32-bit value to be |
| written |
+----------------------------------------------------------------------------+
| Output Parameters : PBYTE_ pb_Status : Pulse encoder status. |
| 0 : No overflow occur|
| 1 : Overflow occur
PULONG_ pul_ReadValue : Pulse encoder value | |
+----------------------------------------------------------------------------+
| Return Value : 0: No error |
| -1: The handle parameter of the board is wrong |
| -2: Module selection is wrong |
| -3: Pulse encoder selection is wrong |
| -4: Pulse encoder not initialised. |
| See function "i_APCI1710_InitPulseEncoder" |
+----------------------------------------------------------------------------+
*/
/*_INT_ i_APCI1710_ReadPulseEncoderStatus (BYTE_ b_BoardHandle,
BYTE_ b_ModulNbr,
BYTE_ b_PulseEncoderNbr,
PBYTE_ pb_Status)
*/
INT i_APCI1710_InsnBitsReadWritePulseEncoder(struct comedi_device * dev,
struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
{
INT i_ReturnValue = 0;
DWORD dw_StatusRegister;
BYTE b_ModulNbr;
BYTE b_PulseEncoderNbr;
PBYTE pb_Status;
BYTE b_Type;
PULONG pul_ReadValue;
ULONG ul_WriteValue;
i_ReturnValue = insn->n;
b_ModulNbr = (BYTE) CR_AREF(insn->chanspec);
b_Type = (BYTE) data[0];
b_PulseEncoderNbr = (BYTE) data[1];
pb_Status = (PBYTE) & data[0];
pul_ReadValue = (PULONG) & data[1];
/***********************************/
/* Test the selected module number */
/***********************************/
if (b_ModulNbr <= 3) {
/******************************************/
/* Test the selected pulse encoder number */
/******************************************/
if (b_PulseEncoderNbr <= 3) {
/*************************************/
/* Test if pulse encoder initialised */
/*************************************/
if (devpriv->s_ModuleInfo[b_ModulNbr].
s_PulseEncoderModuleInfo.
s_PulseEncoderInfo[b_PulseEncoderNbr].
b_PulseEncoderInit == 1) {
switch (b_Type) {
case APCI1710_PULSEENCODER_READ:
/****************************/
/* Read the status register */
/****************************/
dw_StatusRegister =
inl(devpriv->s_BoardInfos.
ui_Address + 16 +
(64 * b_ModulNbr));
devpriv->s_ModuleInfo[b_ModulNbr].
s_PulseEncoderModuleInfo.
dw_StatusRegister = devpriv->
s_ModuleInfo[b_ModulNbr].
s_PulseEncoderModuleInfo.
dw_StatusRegister |
dw_StatusRegister;
*pb_Status =
(BYTE) (devpriv->
s_ModuleInfo[b_ModulNbr].
s_PulseEncoderModuleInfo.
dw_StatusRegister >> (1 +
b_PulseEncoderNbr)) & 1;
devpriv->s_ModuleInfo[b_ModulNbr].
s_PulseEncoderModuleInfo.
dw_StatusRegister =
devpriv->
s_ModuleInfo[b_ModulNbr].
s_PulseEncoderModuleInfo.
dw_StatusRegister &
(0xFFFFFFFFUL - (1 << (1 +
b_PulseEncoderNbr)));
/******************/
/* Read the value */
/******************/
*pul_ReadValue =
inl(devpriv->s_BoardInfos.
ui_Address +
(4 * b_PulseEncoderNbr) +
(64 * b_ModulNbr));
break;
case APCI1710_PULSEENCODER_WRITE:
ul_WriteValue = (ULONG) data[2];
/*******************/
/* Write the value */
/*******************/
outl(ul_WriteValue,
devpriv->s_BoardInfos.
ui_Address +
(4 * b_PulseEncoderNbr) +
(64 * b_ModulNbr));
} //end of switch
} else {
/*********************************/
/* Pulse encoder not initialised */
/*********************************/
DPRINTK("Pulse encoder not initialised\n");
i_ReturnValue = -4;
}
} else {
/************************************/
/* Pulse encoder selection is wrong */
/************************************/
DPRINTK("Pulse encoder selection is wrong\n");
i_ReturnValue = -3;
}
} else {
/*****************************/
/* Module selection is wrong */
/*****************************/
DPRINTK("Module selection is wrong\n");
i_ReturnValue = -2;
}
return (i_ReturnValue);
}
INT i_APCI1710_InsnReadInterruptPulseEncoder(struct comedi_device * dev,
struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
{
data[0] = devpriv->s_InterruptParameters.
s_FIFOInterruptParameters[devpriv->
s_InterruptParameters.ui_Read].b_OldModuleMask;
data[1] = devpriv->s_InterruptParameters.
s_FIFOInterruptParameters[devpriv->
s_InterruptParameters.ui_Read].ul_OldInterruptMask;
data[2] = devpriv->s_InterruptParameters.
s_FIFOInterruptParameters[devpriv->
s_InterruptParameters.ui_Read].ul_OldCounterLatchValue;
/***************************/
/* Increment the read FIFO */
/***************************/
devpriv->s_InterruptParameters.
ui_Read = (devpriv->
s_InterruptParameters.ui_Read + 1) % APCI1710_SAVE_INTERRUPT;
return insn->n;
}

View file

@ -0,0 +1,47 @@
/*
* Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
*
* ADDI-DATA GmbH
* Dieselstrasse 3
* D-77833 Ottersweier
* Tel: +19(0)7223/9493-0
* Fax: +49(0)7223/9493-92
* http://www.addi-data-com
* info@addi-data.com
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*/
#define APCI1710_SINGLE 0
#define APCI1710_CONTINUOUS 1
#define APCI1710_PULSEENCODER_READ 0
#define APCI1710_PULSEENCODER_WRITE 1
INT i_APCI1710_InsnConfigInitPulseEncoder(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
INT i_APCI1710_InsnWriteEnableDisablePulseEncoder(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data);
/*
* READ PULSE ENCODER FUNCTIONS
*/
INT i_APCI1710_InsnReadInterruptPulseEncoder(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data);
/*
* WRITE PULSE ENCODER FUNCTIONS
*/
INT i_APCI1710_InsnBitsReadWritePulseEncoder(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data);

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,76 @@
/*
* Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
*
* ADDI-DATA GmbH
* Dieselstrasse 3
* D-77833 Ottersweier
* Tel: +19(0)7223/9493-0
* Fax: +49(0)7223/9493-92
* http://www.addi-data-com
* info@addi-data.com
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*/
#define APCI1710_30MHZ 30
#define APCI1710_33MHZ 33
#define APCI1710_40MHZ 40
#define APCI1710_PWM_INIT 0
#define APCI1710_PWM_GETINITDATA 1
#define APCI1710_PWM_DISABLE 0
#define APCI1710_PWM_ENABLE 1
#define APCI1710_PWM_NEWTIMING 2
INT i_APCI1710_InsnConfigPWM(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
INT i_APCI1710_InitPWM(struct comedi_device *dev,
BYTE b_ModulNbr,
BYTE b_PWM,
BYTE b_ClockSelection,
BYTE b_TimingUnit,
ULONG ul_LowTiming,
ULONG ul_HighTiming,
PULONG pul_RealLowTiming, PULONG pul_RealHighTiming);
INT i_APCI1710_GetPWMInitialisation(struct comedi_device *dev,
BYTE b_ModulNbr,
BYTE b_PWM,
PBYTE pb_TimingUnit,
PULONG pul_LowTiming,
PULONG pul_HighTiming,
PBYTE pb_StartLevel,
PBYTE pb_StopMode,
PBYTE pb_StopLevel,
PBYTE pb_ExternGate,
PBYTE pb_InterruptEnable, PBYTE pb_Enable);
INT i_APCI1710_InsnWritePWM(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
INT i_APCI1710_EnablePWM(struct comedi_device *dev,
BYTE b_ModulNbr,
BYTE b_PWM,
BYTE b_StartLevel,
BYTE b_StopMode,
BYTE b_StopLevel, BYTE b_ExternGate,
BYTE b_InterruptEnable);
INT i_APCI1710_SetNewPWMTiming(struct comedi_device *dev,
BYTE b_ModulNbr,
BYTE b_PWM, BYTE b_TimingUnit,
ULONG ul_LowTiming, ULONG ul_HighTiming);
INT i_APCI1710_DisablePWM(struct comedi_device *dev, BYTE b_ModulNbr, BYTE b_PWM);
INT i_APCI1710_InsnReadGetPWMStatus(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
INT i_APCI1710_InsnBitsReadPWMInterrupt(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);

View file

@ -0,0 +1,848 @@
/**
@verbatim
Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
ADDI-DATA GmbH
Dieselstrasse 3
D-77833 Ottersweier
Tel: +19(0)7223/9493-0
Fax: +49(0)7223/9493-92
http://www.addi-data-com
info@addi-data.com
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
You shoud also find the complete GPL in the COPYING file accompanying this source code.
@endverbatim
*/
/*
+-----------------------------------------------------------------------+
| (C) ADDI-DATA GmbH Dieselstraße 3 D-77833 Ottersweier |
+-----------------------------------------------------------------------+
| Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com |
| Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com |
+-----------------------------------------------------------------------+
| Project : API APCI1710 | Compiler : gcc |
| Module name : SSI.C | Version : 2.96 |
+-------------------------------+---------------------------------------+
| Project manager: Eric Stolz | Date : 02/12/2002 |
+-----------------------------------------------------------------------+
| Description : APCI-1710 SSI counter module |
| |
| |
+-----------------------------------------------------------------------+
| UPDATES |
+-----------------------------------------------------------------------+
| Date | Author | Description of updates |
+----------+-----------+------------------------------------------------+
| 13/05/98 | S. Weber | SSI digital input / output implementation |
|----------|-----------|------------------------------------------------|
| 22/03/00 | C.Guinot | 0100/0226 -> 0200/0227 |
| | | Änderung in InitSSI Funktion |
| | | b_SSIProfile >= 2 anstatt b_SSIProfile > 2 |
| | | |
+-----------------------------------------------------------------------+
| 08/05/00 | Guinot C | - 0400/0228 All Function in RING 0 |
| | | available |
+-----------------------------------------------------------------------+
*/
/*
+----------------------------------------------------------------------------+
| Included files |
+----------------------------------------------------------------------------+
*/
#include "APCI1710_Ssi.h"
/*
+----------------------------------------------------------------------------+
| Function Name : _INT_ i_APCI1710_InitSSI |
| (BYTE_ b_BoardHandle, |
| BYTE_ b_ModulNbr, |
| BYTE_ b_SSIProfile, |
| BYTE_ b_PositionTurnLength, |
| BYTE_ b_TurnCptLength, |
| BYTE_ b_PCIInputClock, |
| ULONG_ ul_SSIOutputClock, |
| BYTE_ b_SSICountingMode) |
+----------------------------------------------------------------------------+
| Task : Configure the SSI operating mode from selected module |
| (b_ModulNbr). You must calling this function be for you|
| call any other function witch access of SSI. |
+----------------------------------------------------------------------------+
| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710|
| BYTE_ b_ModulNbr : Module number to |
| configure (0 to 3) |
| BYTE_ b_SSIProfile : Selection from SSI |
| profile length (2 to 32).|
| BYTE_ b_PositionTurnLength : Selection from SSI |
| position data length |
| (1 to 31). |
| BYTE_ b_TurnCptLength : Selection from SSI turn |
| counter data length |
| (1 to 31). |
| BYTE b_PCIInputClock : Selection from PCI bus |
| clock |
| - APCI1710_30MHZ : |
| The PC have a PCI bus |
| clock from 30 MHz |
| - APCI1710_33MHZ : |
| The PC have a PCI bus |
| clock from 33 MHz |
| ULONG_ ul_SSIOutputClock : Selection from SSI output|
| clock. |
| From 229 to 5 000 000 Hz|
| for 30 MHz selection. |
| From 252 to 5 000 000 Hz|
| for 33 MHz selection. |
| BYTE b_SSICountingMode : SSI counting mode |
| selection |
| - APCI1710_BINARY_MODE : |
| Binary counting mode. |
| - APCI1710_GRAY_MODE : |
| Gray counting mode.
b_ModulNbr = CR_AREF(insn->chanspec);
b_SSIProfile = (BYTE) data[0];
b_PositionTurnLength= (BYTE) data[1];
b_TurnCptLength = (BYTE) data[2];
b_PCIInputClock = (BYTE) data[3];
ul_SSIOutputClock = (ULONG) data[4];
b_SSICountingMode = (BYTE) data[5]; |
+----------------------------------------------------------------------------+
| Output Parameters : - |
+----------------------------------------------------------------------------+
| Return Value : 0: No error |
| -1: The handle parameter of the board is wrong |
| -2: The module parameter is wrong |
| -3: The module is not a SSI module |
| -4: The selected SSI profile length is wrong |
| -5: The selected SSI position data length is wrong |
| -6: The selected SSI turn counter data length is wrong |
| -7: The selected PCI input clock is wrong |
| -8: The selected SSI output clock is wrong |
| -9: The selected SSI counting mode parameter is wrong |
+----------------------------------------------------------------------------+
*/
INT i_APCI1710_InsnConfigInitSSI(struct comedi_device * dev, struct comedi_subdevice * s,
struct comedi_insn * insn, unsigned int * data)
{
INT i_ReturnValue = 0;
UINT ui_TimerValue;
BYTE b_ModulNbr, b_SSIProfile, b_PositionTurnLength, b_TurnCptLength,
b_PCIInputClock, b_SSICountingMode;
ULONG ul_SSIOutputClock;
b_ModulNbr = CR_AREF(insn->chanspec);
b_SSIProfile = (BYTE) data[0];
b_PositionTurnLength = (BYTE) data[1];
b_TurnCptLength = (BYTE) data[2];
b_PCIInputClock = (BYTE) data[3];
ul_SSIOutputClock = (ULONG) data[4];
b_SSICountingMode = (BYTE) data[5];
i_ReturnValue = insn->n;
/**************************/
/* Test the module number */
/**************************/
if (b_ModulNbr < 4) {
/***********************/
/* Test if SSI counter */
/***********************/
if ((devpriv->s_BoardInfos.
dw_MolduleConfiguration[b_ModulNbr] &
0xFFFF0000UL) == APCI1710_SSI_COUNTER) {
/*******************************/
/* Test the SSI profile length */
/*******************************/
// CG 22/03/00 b_SSIProfile >= 2 anstatt b_SSIProfile > 2
if (b_SSIProfile >= 2 && b_SSIProfile < 33) {
/*************************************/
/* Test the SSI position data length */
/*************************************/
if (b_PositionTurnLength > 0
&& b_PositionTurnLength < 32) {
/*****************************************/
/* Test the SSI turn counter data length */
/*****************************************/
if (b_TurnCptLength > 0
&& b_TurnCptLength < 32) {
/***************************/
/* Test the profile length */
/***************************/
if ((b_TurnCptLength +
b_PositionTurnLength)
<= b_SSIProfile) {
/****************************/
/* Test the PCI input clock */
/****************************/
if (b_PCIInputClock ==
APCI1710_30MHZ
||
b_PCIInputClock
==
APCI1710_33MHZ)
{
/*************************/
/* Test the output clock */
/*************************/
if ((b_PCIInputClock == APCI1710_30MHZ && (ul_SSIOutputClock > 228 && ul_SSIOutputClock <= 5000000UL)) || (b_PCIInputClock == APCI1710_33MHZ && (ul_SSIOutputClock > 251 && ul_SSIOutputClock <= 5000000UL))) {
if (b_SSICountingMode == APCI1710_BINARY_MODE || b_SSICountingMode == APCI1710_GRAY_MODE) {
/**********************/
/* Save configuration */
/**********************/
devpriv->
s_ModuleInfo
[b_ModulNbr].
s_SSICounterInfo.
b_SSIProfile
=
b_SSIProfile;
devpriv->
s_ModuleInfo
[b_ModulNbr].
s_SSICounterInfo.
b_PositionTurnLength
=
b_PositionTurnLength;
devpriv->
s_ModuleInfo
[b_ModulNbr].
s_SSICounterInfo.
b_TurnCptLength
=
b_TurnCptLength;
/*********************************/
/* Initialise the profile length */
/*********************************/
if (b_SSICountingMode == APCI1710_BINARY_MODE) {
outl(b_SSIProfile + 1, devpriv->s_BoardInfos.ui_Address + 4 + (64 * b_ModulNbr));
} else {
outl(b_SSIProfile, devpriv->s_BoardInfos.ui_Address + 4 + (64 * b_ModulNbr));
}
/******************************/
/* Calculate the output clock */
/******************************/
ui_TimerValue
=
(UINT)
(
((ULONG) (b_PCIInputClock) * 500000UL) / ul_SSIOutputClock);
/************************/
/* Initialise the timer */
/************************/
outl(ui_TimerValue, devpriv->s_BoardInfos.ui_Address + (64 * b_ModulNbr));
/********************************/
/* Initialise the counting mode */
/********************************/
outl(7 * b_SSICountingMode, devpriv->s_BoardInfos.ui_Address + 12 + (64 * b_ModulNbr));
devpriv->
s_ModuleInfo
[b_ModulNbr].
s_SSICounterInfo.
b_SSIInit
=
1;
} else {
/*****************************************************/
/* The selected SSI counting mode parameter is wrong */
/*****************************************************/
DPRINTK("The selected SSI counting mode parameter is wrong\n");
i_ReturnValue
=
-9;
}
} else {
/******************************************/
/* The selected SSI output clock is wrong */
/******************************************/
DPRINTK("The selected SSI output clock is wrong\n");
i_ReturnValue
=
-8;
}
} else {
/*****************************************/
/* The selected PCI input clock is wrong */
/*****************************************/
DPRINTK("The selected PCI input clock is wrong\n");
i_ReturnValue =
-7;
}
} else {
/********************************************/
/* The selected SSI profile length is wrong */
/********************************************/
DPRINTK("The selected SSI profile length is wrong\n");
i_ReturnValue = -4;
}
} else {
/******************************************************/
/* The selected SSI turn counter data length is wrong */
/******************************************************/
DPRINTK("The selected SSI turn counter data length is wrong\n");
i_ReturnValue = -6;
}
} else {
/**************************************************/
/* The selected SSI position data length is wrong */
/**************************************************/
DPRINTK("The selected SSI position data length is wrong\n");
i_ReturnValue = -5;
}
} else {
/********************************************/
/* The selected SSI profile length is wrong */
/********************************************/
DPRINTK("The selected SSI profile length is wrong\n");
i_ReturnValue = -4;
}
} else {
/**********************************/
/* The module is not a SSI module */
/**********************************/
DPRINTK("The module is not a SSI module\n");
i_ReturnValue = -3;
}
} else {
/***********************/
/* Module number error */
/***********************/
DPRINTK("Module number error\n");
i_ReturnValue = -2;
}
return (i_ReturnValue);
}
/*
+----------------------------------------------------------------------------+
| Function Name : _INT_ i_APCI1710_Read1SSIValue |
| (BYTE_ b_BoardHandle, |
| BYTE_ b_ModulNbr, |
| BYTE_ b_SelectedSSI, |
| PULONG_ pul_Position, |
| PULONG_ pul_TurnCpt)
INT i_APCI1710_ReadSSIValue(struct comedi_device *dev,struct comedi_subdevice *s,
struct comedi_insn *insn,unsigned int *data) |
+----------------------------------------------------------------------------+
| Task :
Read the selected SSI counter (b_SelectedSSI) from |
| selected module (b_ModulNbr).
or Read all SSI counter (b_SelectedSSI) from |
| selected module (b_ModulNbr). |
+----------------------------------------------------------------------------+
| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710|
| BYTE_ b_ModulNbr : Module number to |
| configure (0 to 3) |
| BYTE_ b_SelectedSSI : Selection from SSI |
| counter (0 to 2)
b_ModulNbr = (BYTE) CR_AREF(insn->chanspec);
b_SelectedSSI = (BYTE) CR_CHAN(insn->chanspec); (in case of single ssi)
b_ReadType = (BYTE) CR_RANGE(insn->chanspec);
|
+----------------------------------------------------------------------------+
| Output Parameters : PULONG_ pul_Position : SSI position in the turn |
| PULONG_ pul_TurnCpt : Number of turns
pul_Position = (PULONG) &data[0];
pul_TurnCpt = (PULONG) &data[1]; |
+----------------------------------------------------------------------------+
| Return Value : 0: No error |
| -1: The handle parameter of the board is wrong |
| -2: The module parameter is wrong |
| -3: The module is not a SSI module |
| -4: SSI not initialised see function |
| "i_APCI1710_InitSSI" |
| -5: The selected SSI is wrong |
+----------------------------------------------------------------------------+
*/
INT i_APCI1710_InsnReadSSIValue(struct comedi_device * dev, struct comedi_subdevice * s,
struct comedi_insn * insn, unsigned int * data)
{
INT i_ReturnValue = 0;
BYTE b_Cpt;
BYTE b_Length;
BYTE b_Schift;
BYTE b_SSICpt;
DWORD dw_And;
DWORD dw_And1;
DWORD dw_And2;
DWORD dw_StatusReg;
DWORD dw_CounterValue;
BYTE b_ModulNbr;
BYTE b_SelectedSSI;
BYTE b_ReadType;
PULONG pul_Position;
PULONG pul_TurnCpt;
PULONG pul_Position1;
PULONG pul_TurnCpt1;
i_ReturnValue = insn->n;
pul_Position1 = (PULONG) & data[0];
// For Read1
pul_TurnCpt1 = (PULONG) & data[1];
// For Read all
pul_Position = (PULONG) & data[0]; //0-2
pul_TurnCpt = (PULONG) & data[3]; //3-5
b_ModulNbr = (BYTE) CR_AREF(insn->chanspec);
b_SelectedSSI = (BYTE) CR_CHAN(insn->chanspec);
b_ReadType = (BYTE) CR_RANGE(insn->chanspec);
/**************************/
/* Test the module number */
/**************************/
if (b_ModulNbr < 4) {
/***********************/
/* Test if SSI counter */
/***********************/
if ((devpriv->s_BoardInfos.
dw_MolduleConfiguration[b_ModulNbr] &
0xFFFF0000UL) == APCI1710_SSI_COUNTER) {
/***************************/
/* Test if SSI initialised */
/***************************/
if (devpriv->s_ModuleInfo[b_ModulNbr].
s_SSICounterInfo.b_SSIInit == 1) {
switch (b_ReadType) {
case APCI1710_SSI_READ1VALUE:
/****************************************/
/* Test the selected SSI counter number */
/****************************************/
if (b_SelectedSSI < 3) {
/************************/
/* Start the conversion */
/************************/
outl(0, devpriv->s_BoardInfos.
ui_Address + 8 +
(64 * b_ModulNbr));
do {
/*******************/
/* Read the status */
/*******************/
dw_StatusReg =
inl(devpriv->
s_BoardInfos.
ui_Address +
(64 * b_ModulNbr));
}
while ((dw_StatusReg & 0x1) !=
0);
/******************************/
/* Read the SSI counter value */
/******************************/
dw_CounterValue =
inl(devpriv->
s_BoardInfos.
ui_Address + 4 +
(b_SelectedSSI * 4) +
(64 * b_ModulNbr));
b_Length =
devpriv->
s_ModuleInfo
[b_ModulNbr].
s_SSICounterInfo.
b_SSIProfile / 2;
if ((b_Length * 2) !=
devpriv->
s_ModuleInfo
[b_ModulNbr].
s_SSICounterInfo.
b_SSIProfile) {
b_Length++;
}
b_Schift =
b_Length -
devpriv->
s_ModuleInfo
[b_ModulNbr].
s_SSICounterInfo.
b_PositionTurnLength;
*pul_Position1 =
dw_CounterValue >>
b_Schift;
dw_And = 1;
for (b_Cpt = 0;
b_Cpt <
devpriv->
s_ModuleInfo
[b_ModulNbr].
s_SSICounterInfo.
b_PositionTurnLength;
b_Cpt++) {
dw_And = dw_And * 2;
}
*pul_Position1 =
*pul_Position1 &
((dw_And) - 1);
*pul_TurnCpt1 =
dw_CounterValue >>
b_Length;
dw_And = 1;
for (b_Cpt = 0;
b_Cpt <
devpriv->
s_ModuleInfo
[b_ModulNbr].
s_SSICounterInfo.
b_TurnCptLength;
b_Cpt++) {
dw_And = dw_And * 2;
}
*pul_TurnCpt1 =
*pul_TurnCpt1 &
((dw_And) - 1);
} else {
/*****************************/
/* The selected SSI is wrong */
/*****************************/
DPRINTK("The selected SSI is wrong\n");
i_ReturnValue = -5;
}
break;
case APCI1710_SSI_READALLVALUE:
dw_And1 = 1;
for (b_Cpt = 0;
b_Cpt <
devpriv->
s_ModuleInfo[b_ModulNbr].
s_SSICounterInfo.
b_PositionTurnLength; b_Cpt++) {
dw_And1 = dw_And1 * 2;
}
dw_And2 = 1;
for (b_Cpt = 0;
b_Cpt <
devpriv->
s_ModuleInfo[b_ModulNbr].
s_SSICounterInfo.
b_TurnCptLength; b_Cpt++) {
dw_And2 = dw_And2 * 2;
}
/************************/
/* Start the conversion */
/************************/
outl(0, devpriv->s_BoardInfos.
ui_Address + 8 +
(64 * b_ModulNbr));
do {
/*******************/
/* Read the status */
/*******************/
dw_StatusReg =
inl(devpriv->
s_BoardInfos.
ui_Address +
(64 * b_ModulNbr));
}
while ((dw_StatusReg & 0x1) != 0);
for (b_SSICpt = 0; b_SSICpt < 3;
b_SSICpt++) {
/******************************/
/* Read the SSI counter value */
/******************************/
dw_CounterValue =
inl(devpriv->
s_BoardInfos.
ui_Address + 4 +
(b_SSICpt * 4) +
(64 * b_ModulNbr));
b_Length =
devpriv->
s_ModuleInfo
[b_ModulNbr].
s_SSICounterInfo.
b_SSIProfile / 2;
if ((b_Length * 2) !=
devpriv->
s_ModuleInfo
[b_ModulNbr].
s_SSICounterInfo.
b_SSIProfile) {
b_Length++;
}
b_Schift =
b_Length -
devpriv->
s_ModuleInfo
[b_ModulNbr].
s_SSICounterInfo.
b_PositionTurnLength;
pul_Position[b_SSICpt] =
dw_CounterValue >>
b_Schift;
pul_Position[b_SSICpt] =
pul_Position[b_SSICpt] &
((dw_And1) - 1);
pul_TurnCpt[b_SSICpt] =
dw_CounterValue >>
b_Length;
pul_TurnCpt[b_SSICpt] =
pul_TurnCpt[b_SSICpt] &
((dw_And2) - 1);
}
break;
default:
printk("Read Type Inputs Wrong\n");
} // switch ending
} else {
/***********************/
/* SSI not initialised */
/***********************/
DPRINTK("SSI not initialised\n");
i_ReturnValue = -4;
}
} else {
/**********************************/
/* The module is not a SSI module */
/**********************************/
DPRINTK("The module is not a SSI module\n");
i_ReturnValue = -3;
}
} else {
/***********************/
/* Module number error */
/***********************/
DPRINTK("Module number error\n");
i_ReturnValue = -2;
}
return (i_ReturnValue);
}
/*
+----------------------------------------------------------------------------+
| Function Name : _INT_ i_APCI1710_ReadSSI1DigitalInput |
| (BYTE_ b_BoardHandle, |
| BYTE_ b_ModulNbr, |
| BYTE_ b_InputChannel, |
| PBYTE_ pb_ChannelStatus) |
+----------------------------------------------------------------------------+
| Task :
(0) Set the digital output from selected SSI moule |
| (b_ModuleNbr) ON
(1) Set the digital output from selected SSI moule |
| (b_ModuleNbr) OFF
(2)Read the status from selected SSI digital input |
| (b_InputChannel)
(3)Read the status from all SSI digital inputs from |
| selected SSI module (b_ModulNbr) |
+----------------------------------------------------------------------------+
| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710|
| BYTE_ b_ModulNbr CR_AREF : Module number to |
| configure (0 to 3) |
| BYTE_ b_InputChannel CR_CHAN : Selection from digital |
| data[0] which IOTYPE input ( 0 to 2) |
+----------------------------------------------------------------------------+
| Output Parameters : PBYTE_ pb_ChannelStatus : Digital input channel |
| data[0] status |
| 0 : Channle is not active|
| 1 : Channle is active |
+----------------------------------------------------------------------------+
| Return Value : 0: No error |
| -1: The handle parameter of the board is wrong |
| -2: The module parameter is wrong |
| -3: The module is not a SSI module |
| -4: The selected SSI digital input is wrong |
+----------------------------------------------------------------------------+
*/
INT i_APCI1710_InsnBitsSSIDigitalIO(struct comedi_device * dev, struct comedi_subdevice * s,
struct comedi_insn * insn, unsigned int * data)
{
INT i_ReturnValue = 0;
DWORD dw_StatusReg;
BYTE b_ModulNbr;
BYTE b_InputChannel;
PBYTE pb_ChannelStatus;
PBYTE pb_InputStatus;
BYTE b_IOType;
i_ReturnValue = insn->n;
b_ModulNbr = (BYTE) CR_AREF(insn->chanspec);
b_IOType = (BYTE) data[0];
/**************************/
/* Test the module number */
/**************************/
if (b_ModulNbr < 4) {
/***********************/
/* Test if SSI counter */
/***********************/
if ((devpriv->s_BoardInfos.
dw_MolduleConfiguration[b_ModulNbr] &
0xFFFF0000UL) == APCI1710_SSI_COUNTER) {
switch (b_IOType) {
case APCI1710_SSI_SET_CHANNELON:
/*****************************/
/* Set the digital output ON */
/*****************************/
outl(1, devpriv->s_BoardInfos.ui_Address + 16 +
(64 * b_ModulNbr));
break;
case APCI1710_SSI_SET_CHANNELOFF:
/******************************/
/* Set the digital output OFF */
/******************************/
outl(0, devpriv->s_BoardInfos.ui_Address + 16 +
(64 * b_ModulNbr));
break;
case APCI1710_SSI_READ_1CHANNEL:
/******************************************/
/* Test the digital imnput channel number */
/******************************************/
b_InputChannel = (BYTE) CR_CHAN(insn->chanspec);
pb_ChannelStatus = (PBYTE) & data[0];
if (b_InputChannel <= 2) {
/**************************/
/* Read all digital input */
/**************************/
dw_StatusReg =
inl(devpriv->s_BoardInfos.
ui_Address + (64 * b_ModulNbr));
*pb_ChannelStatus =
(BYTE) (((~dw_StatusReg) >> (4 +
b_InputChannel))
& 1);
} else {
/********************************/
/* Selected digital input error */
/********************************/
DPRINTK("Selected digital input error\n");
i_ReturnValue = -4;
}
break;
case APCI1710_SSI_READ_ALLCHANNEL:
/**************************/
/* Read all digital input */
/**************************/
pb_InputStatus = (PBYTE) & data[0];
dw_StatusReg =
inl(devpriv->s_BoardInfos.ui_Address +
(64 * b_ModulNbr));
*pb_InputStatus =
(BYTE) (((~dw_StatusReg) >> 4) & 7);
break;
default:
printk("IO type wrong\n");
} //switch end
} else {
/**********************************/
/* The module is not a SSI module */
/**********************************/
DPRINTK("The module is not a SSI module\n");
i_ReturnValue = -3;
}
} else {
/***********************/
/* Module number error */
/***********************/
DPRINTK("Module number error\n");
i_ReturnValue = -2;
}
return (i_ReturnValue);
}

View file

@ -0,0 +1,43 @@
/*
* Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
*
* ADDI-DATA GmbH
* Dieselstrasse 3
* D-77833 Ottersweier
* Tel: +19(0)7223/9493-0
* Fax: +49(0)7223/9493-92
* http://www.addi-data-com
* info@addi-data.com
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*/
#define APCI1710_30MHZ 30
#define APCI1710_33MHZ 33
#define APCI1710_40MHZ 40
#define APCI1710_BINARY_MODE 0x1
#define APCI1710_GRAY_MODE 0x0
#define APCI1710_SSI_READ1VALUE 1
#define APCI1710_SSI_READALLVALUE 2
#define APCI1710_SSI_SET_CHANNELON 0
#define APCI1710_SSI_SET_CHANNELOFF 1
#define APCI1710_SSI_READ_1CHANNEL 2
#define APCI1710_SSI_READ_ALLCHANNEL 3
/*
* SSI INISIALISATION FUNCTION
*/
INT i_APCI1710_InsnConfigInitSSI(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
INT i_APCI1710_InsnReadSSIValue(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
INT i_APCI1710_InsnBitsSSIDigitalIO(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,57 @@
/*
* Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
*
* ADDI-DATA GmbH
* Dieselstrasse 3
* D-77833 Ottersweier
* Tel: +19(0)7223/9493-0
* Fax: +49(0)7223/9493-92
* http://www.addi-data-com
* info@addi-data.com
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*/
#define APCI1710_30MHZ 30
#define APCI1710_33MHZ 33
#define APCI1710_40MHZ 40
#define APCI1710_GATE_INPUT 10
#define APCI1710_TOR_SIMPLE_MODE 2
#define APCI1710_TOR_DOUBLE_MODE 3
#define APCI1710_TOR_QUADRUPLE_MODE 4
#define APCI1710_SINGLE 0
#define APCI1710_CONTINUOUS 1
#define APCI1710_TOR_GETPROGRESSSTATUS 0
#define APCI1710_TOR_GETCOUNTERVALUE 1
#define APCI1710_TOR_READINTERRUPT 2
/*
* TOR_COUNTER INISIALISATION FUNCTION
*/
INT i_APCI1710_InsnConfigInitTorCounter(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
INT i_APCI1710_InsnWriteEnableDisableTorCounter(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data);
INT i_APCI1710_InsnReadGetTorCounterInitialisation(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data);
/*
* TOR_COUNTER READ FUNCTION
*/
INT i_APCI1710_InsnBitsGetTorCounterProgressStatusAndValue(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data);

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,44 @@
/*
* Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
*
* ADDI-DATA GmbH
* Dieselstrasse 3
* D-77833 Ottersweier
* Tel: +19(0)7223/9493-0
* Fax: +49(0)7223/9493-92
* http://www.addi-data-com
* info@addi-data.com
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*/
#define APCI1710_TTL_INIT 0
#define APCI1710_TTL_INITDIRECTION 1
#define APCI1710_TTL_READCHANNEL 0
#define APCI1710_TTL_READPORT 1
/*
* TTL INISIALISATION FUNCTION
*/
INT i_APCI1710_InsnConfigInitTTLIO(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
/*
* TTL INPUT FUNCTION
*/
INT i_APCI1710_InsnBitsReadTTLIO(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
INT i_APCI1710_InsnReadTTLIOAllPortValue(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
/*
* TTL OUTPUT FUNCTIONS
*/
INT i_APCI1710_InsnWriteSetTTLIOChlOnOff(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);

View file

@ -0,0 +1,203 @@
/**
@verbatim
Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
ADDI-DATA GmbH
Dieselstrasse 3
D-77833 Ottersweier
Tel: +19(0)7223/9493-0
Fax: +49(0)7223/9493-92
http://www.addi-data-com
info@addi-data.com
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
You shoud also find the complete GPL in the COPYING file accompanying this source code.
@endverbatim
*/
/*
+-----------------------------------------------------------------------+
| (C) ADDI-DATA GmbH Dieselstraße 3 D-77833 Ottersweier |
+-----------------------------------------------------------------------+
| Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com |
| Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com |
+-------------------------------+---------------------------------------+
| Project : ADDI HEADER READ WRITER | Compiler : Visual C++ |
| Module name : S5920.cpp | Version : 6.0 |
+-------------------------------+---------------------------------------+
| Author : E. LIBS Date : 02/05/2002 |
+-----------------------------------------------------------------------+
| Description : DLL with the S5920 PCI Controller functions |
+-----------------------------------------------------------------------+
| UPDATE'S |
+-----------------------------------------------------------------------+
| Date | Author | Description of updates |
+----------+-----------+------------------------------------------------+
| 28/08/02 | LIBS Eric | Add return codes each time a function of the |
| | | Addi Library is called |
+-----------------------------------------------------------------------+
| 31/07/03 | KRAUTH J. | Changes for the MSX-Box |
+-----------------------------------------------------------------------+
*/
#include "addi_amcc_S5920.h"
/*+----------------------------------------------------------------------------+*/
/*| Function Name : INT i_AddiHeaderRW_ReadEeprom |*/
/*| (INT i_NbOfWordsToRead, |*/
/*| DWORD dw_PCIBoardEepromAddress, |*/
/*| WORD w_EepromStartAddress, |*/
/*| PWORD pw_DataRead) |*/
/*+----------------------------------------------------------------------------+*/
/*| Task : Read word from the 5920 eeprom. |*/
/*+----------------------------------------------------------------------------+*/
/*| Input Parameters : INT i_NbOfWordsToRead : Nbr. of word to read |*/
/*| DWORD dw_PCIBoardEepromAddress : Address of the eeprom |*/
/*| WORD w_EepromStartAddress : Eeprom strat address |*/
/*+----------------------------------------------------------------------------+*/
/*| Output Parameters : PWORD pw_DataRead : Read data |*/
/*+----------------------------------------------------------------------------+*/
/*| Return Value : - |*/
/*+----------------------------------------------------------------------------+*/
INT i_AddiHeaderRW_ReadEeprom(INT i_NbOfWordsToRead,
DWORD dw_PCIBoardEepromAddress,
WORD w_EepromStartAddress, PWORD pw_DataRead)
{
DWORD dw_eeprom_busy = 0;
INT i_Counter = 0;
INT i_WordCounter;
INT i;
BYTE pb_ReadByte[1];
BYTE b_ReadLowByte = 0;
BYTE b_ReadHighByte = 0;
BYTE b_SelectedAddressLow = 0;
BYTE b_SelectedAddressHigh = 0;
WORD w_ReadWord = 0;
for (i_WordCounter = 0; i_WordCounter < i_NbOfWordsToRead;
i_WordCounter++) {
do {
dw_eeprom_busy =
inl(dw_PCIBoardEepromAddress +
AMCC_OP_REG_MCSR);
dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY;
}
while (dw_eeprom_busy == EEPROM_BUSY);
for (i_Counter = 0; i_Counter < 2; i_Counter++) {
b_SelectedAddressLow = (w_EepromStartAddress + i_Counter) % 256; //Read the low 8 bit part
b_SelectedAddressHigh = (w_EepromStartAddress + i_Counter) / 256; //Read the high 8 bit part
//Select the load low address mode
outb(NVCMD_LOAD_LOW,
dw_PCIBoardEepromAddress + AMCC_OP_REG_MCSR +
3);
//Wait on busy
do {
dw_eeprom_busy =
inl(dw_PCIBoardEepromAddress +
AMCC_OP_REG_MCSR);
dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY;
}
while (dw_eeprom_busy == EEPROM_BUSY);
//Load the low address
outb(b_SelectedAddressLow,
dw_PCIBoardEepromAddress + AMCC_OP_REG_MCSR +
2);
//Wait on busy
do {
dw_eeprom_busy =
inl(dw_PCIBoardEepromAddress +
AMCC_OP_REG_MCSR);
dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY;
}
while (dw_eeprom_busy == EEPROM_BUSY);
//Select the load high address mode
outb(NVCMD_LOAD_HIGH,
dw_PCIBoardEepromAddress + AMCC_OP_REG_MCSR +
3);
//Wait on busy
do {
dw_eeprom_busy =
inl(dw_PCIBoardEepromAddress +
AMCC_OP_REG_MCSR);
dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY;
}
while (dw_eeprom_busy == EEPROM_BUSY);
//Load the high address
outb(b_SelectedAddressHigh,
dw_PCIBoardEepromAddress + AMCC_OP_REG_MCSR +
2);
//Wait on busy
do {
dw_eeprom_busy =
inl(dw_PCIBoardEepromAddress +
AMCC_OP_REG_MCSR);
dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY;
}
while (dw_eeprom_busy == EEPROM_BUSY);
//Select the READ mode
outb(NVCMD_BEGIN_READ,
dw_PCIBoardEepromAddress + AMCC_OP_REG_MCSR +
3);
//Wait on busy
do {
dw_eeprom_busy =
inl(dw_PCIBoardEepromAddress +
AMCC_OP_REG_MCSR);
dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY;
}
while (dw_eeprom_busy == EEPROM_BUSY);
//Read data into the EEPROM
*pb_ReadByte =
inb(dw_PCIBoardEepromAddress +
AMCC_OP_REG_MCSR + 2);
//Wait on busy
do {
dw_eeprom_busy =
inl(dw_PCIBoardEepromAddress +
AMCC_OP_REG_MCSR);
dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY;
}
while (dw_eeprom_busy == EEPROM_BUSY);
//Select the upper address part
if (i_Counter == 0) {
b_ReadLowByte = pb_ReadByte[0];
} else {
b_ReadHighByte = pb_ReadByte[0];
}
//Sleep
for (i = 0; i < 10000; i++) ;
}
w_ReadWord =
(b_ReadLowByte | (((unsigned short)b_ReadHighByte) *
256));
pw_DataRead[i_WordCounter] = w_ReadWord;
w_EepromStartAddress += 2; // to read the next word
} // for (...) i_NbOfWordsToRead
return (0);
}

View file

@ -0,0 +1,27 @@
/*
* Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
*
* ADDI-DATA GmbH
* Dieselstrasse 3
* D-77833 Ottersweier
* Tel: +19(0)7223/9493-0
* Fax: +49(0)7223/9493-92
* http://www.addi-data-com
* info@addi-data.com
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*/
#define AMCC_OP_REG_MCSR 0x3c
#define EEPROM_BUSY 0x80000000
#define NVCMD_LOAD_LOW (0x4 << 5) /* nvRam load low command */
#define NVCMD_LOAD_HIGH (0x5 << 5) /* nvRam load high command */
#define NVCMD_BEGIN_READ (0x7 << 5) /* nvRam begin read command */
#define NVCMD_BEGIN_WRITE (0x6 << 5) /* EEPROM begin write command */
INT i_AddiHeaderRW_ReadEeprom(INT i_NbOfWordsToRead,
DWORD dw_PCIBoardEepromAddress,
WORD w_EepromStartAddress, PWORD pw_DataRead);

View file

@ -0,0 +1,476 @@
/*
* Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
*
* ADDI-DATA GmbH
* Dieselstrasse 3
* D-77833 Ottersweier
* Tel: +19(0)7223/9493-0
* Fax: +49(0)7223/9493-92
* http://www.addi-data-com
* info@addi-data.com
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*/
/* Header file for AMCC s 5933 */
#ifndef _AMCC_S5933_H_
#define _AMCC_S5933_H_
#include "../../comedidev.h"
#include "../comedi_pci.h"
#ifdef PCI_SUPPORT_VER1
#error No support for 2.1.55 and older
#endif
/* written on base0 */
#define FIFO_ADVANCE_ON_BYTE_2 0x20000000
/* added for step 6 dma written on base2 */
#define AMWEN_ENABLE 0x02
#define A2P_FIFO_WRITE_ENABLE 0x01
/* for transfer count enable bit */
#define AGCSTS_TC_ENABLE 0x10000000
/*
* ADDON RELATED ADDITIONS
*/
/* Constant */
#define APCI3120_ENABLE_TRANSFER_ADD_ON_LOW 0x00
#define APCI3120_ENABLE_TRANSFER_ADD_ON_HIGH 0x1200
#define APCI3120_A2P_FIFO_MANAGEMENT 0x04000400L
#define APCI3120_AMWEN_ENABLE 0x02
#define APCI3120_A2P_FIFO_WRITE_ENABLE 0x01
#define APCI3120_FIFO_ADVANCE_ON_BYTE_2 0x20000000L
#define APCI3120_ENABLE_WRITE_TC_INT 0x00004000L
#define APCI3120_CLEAR_WRITE_TC_INT 0x00040000L
#define APCI3120_DISABLE_AMWEN_AND_A2P_FIFO_WRITE 0x0
#define APCI3120_DISABLE_BUS_MASTER_ADD_ON 0x0
#define APCI3120_DISABLE_BUS_MASTER_PCI 0x0
/* ADD_ON ::: this needed since apci supports 16 bit interface to add on */
#define APCI3120_ADD_ON_AGCSTS_LOW 0x3C
#define APCI3120_ADD_ON_AGCSTS_HIGH (APCI3120_ADD_ON_AGCSTS_LOW + 2)
#define APCI3120_ADD_ON_MWAR_LOW 0x24
#define APCI3120_ADD_ON_MWAR_HIGH (APCI3120_ADD_ON_MWAR_LOW + 2)
#define APCI3120_ADD_ON_MWTC_LOW 0x058
#define APCI3120_ADD_ON_MWTC_HIGH (APCI3120_ADD_ON_MWTC_LOW + 2)
/* AMCC */
#define APCI3120_AMCC_OP_MCSR 0x3C
#define APCI3120_AMCC_OP_REG_INTCSR 0x38
/*
* AMCC Operation Register Offsets - PCI
*/
#define AMCC_OP_REG_OMB1 0x00
#define AMCC_OP_REG_OMB2 0x04
#define AMCC_OP_REG_OMB3 0x08
#define AMCC_OP_REG_OMB4 0x0c
#define AMCC_OP_REG_IMB1 0x10
#define AMCC_OP_REG_IMB2 0x14
#define AMCC_OP_REG_IMB3 0x18
#define AMCC_OP_REG_IMB4 0x1c
#define AMCC_OP_REG_FIFO 0x20
#define AMCC_OP_REG_MWAR 0x24
#define AMCC_OP_REG_MWTC 0x28
#define AMCC_OP_REG_MRAR 0x2c
#define AMCC_OP_REG_MRTC 0x30
#define AMCC_OP_REG_MBEF 0x34
#define AMCC_OP_REG_INTCSR 0x38
/* INT source */
#define AMCC_OP_REG_INTCSR_SRC (AMCC_OP_REG_INTCSR + 2)
/* FIFO ctrl */
#define AMCC_OP_REG_INTCSR_FEC (AMCC_OP_REG_INTCSR + 3)
#define AMCC_OP_REG_MCSR 0x3c
/* Data in byte 2 */
#define AMCC_OP_REG_MCSR_NVDATA (AMCC_OP_REG_MCSR + 2)
/* Command in byte 3 */
#define AMCC_OP_REG_MCSR_NVCMD (AMCC_OP_REG_MCSR + 3)
#define AMCC_FIFO_DEPTH_DWORD 8
#define AMCC_FIFO_DEPTH_BYTES (8 * sizeof(u32))
/*
* AMCC Operation Registers Size - PCI
*/
#define AMCC_OP_REG_SIZE 64 /* in bytes */
/*
* AMCC Operation Register Offsets - Add-on
*/
#define AMCC_OP_REG_AIMB1 0x00
#define AMCC_OP_REG_AIMB2 0x04
#define AMCC_OP_REG_AIMB3 0x08
#define AMCC_OP_REG_AIMB4 0x0c
#define AMCC_OP_REG_AOMB1 0x10
#define AMCC_OP_REG_AOMB2 0x14
#define AMCC_OP_REG_AOMB3 0x18
#define AMCC_OP_REG_AOMB4 0x1c
#define AMCC_OP_REG_AFIFO 0x20
#define AMCC_OP_REG_AMWAR 0x24
#define AMCC_OP_REG_APTA 0x28
#define AMCC_OP_REG_APTD 0x2c
#define AMCC_OP_REG_AMRAR 0x30
#define AMCC_OP_REG_AMBEF 0x34
#define AMCC_OP_REG_AINT 0x38
#define AMCC_OP_REG_AGCSTS 0x3c
#define AMCC_OP_REG_AMWTC 0x58
#define AMCC_OP_REG_AMRTC 0x5c
/*
* AMCC - Add-on General Control/Status Register
*/
#define AGCSTS_CONTROL_MASK 0xfffff000
#define AGCSTS_NV_ACC_MASK 0xe0000000
#define AGCSTS_RESET_MASK 0x0e000000
#define AGCSTS_NV_DA_MASK 0x00ff0000
#define AGCSTS_BIST_MASK 0x0000f000
#define AGCSTS_STATUS_MASK 0x000000ff
#define AGCSTS_TCZERO_MASK 0x000000c0
#define AGCSTS_FIFO_ST_MASK 0x0000003f
#define AGCSTS_RESET_MBFLAGS 0x08000000
#define AGCSTS_RESET_P2A_FIFO 0x04000000
#define AGCSTS_RESET_A2P_FIFO 0x02000000
#define AGCSTS_RESET_FIFOS (AGCSTS_RESET_A2P_FIFO | AGCSTS_RESET_P2A_FIFO)
#define AGCSTS_A2P_TCOUNT 0x00000080
#define AGCSTS_P2A_TCOUNT 0x00000040
#define AGCSTS_FS_P2A_EMPTY 0x00000020
#define AGCSTS_FS_P2A_HALF 0x00000010
#define AGCSTS_FS_P2A_FULL 0x00000008
#define AGCSTS_FS_A2P_EMPTY 0x00000004
#define AGCSTS_FS_A2P_HALF 0x00000002
#define AGCSTS_FS_A2P_FULL 0x00000001
/*
* AMCC - Add-on Interrupt Control/Status Register
*/
#define AINT_INT_MASK 0x00ff0000
#define AINT_SEL_MASK 0x0000ffff
#define AINT_IS_ENSEL_MASK 0x00001f1f
#define AINT_INT_ASSERTED 0x00800000
#define AINT_BM_ERROR 0x00200000
#define AINT_BIST_INT 0x00100000
#define AINT_RT_COMPLETE 0x00080000
#define AINT_WT_COMPLETE 0x00040000
#define AINT_OUT_MB_INT 0x00020000
#define AINT_IN_MB_INT 0x00010000
#define AINT_READ_COMPL 0x00008000
#define AINT_WRITE_COMPL 0x00004000
#define AINT_OMB_ENABLE 0x00001000
#define AINT_OMB_SELECT 0x00000c00
#define AINT_OMB_BYTE 0x00000300
#define AINT_IMB_ENABLE 0x00000010
#define AINT_IMB_SELECT 0x0000000c
#define AINT_IMB_BYTE 0x00000003
/* Enable Bus Mastering */
#define EN_A2P_TRANSFERS 0x00000400
/* FIFO Flag Reset */
#define RESET_A2P_FLAGS 0x04000000L
/* FIFO Relative Priority */
#define A2P_HI_PRIORITY 0x00000100L
/* Identify Interrupt Sources */
#define ANY_S593X_INT 0x00800000L
#define READ_TC_INT 0x00080000L
#define WRITE_TC_INT 0x00040000L
#define IN_MB_INT 0x00020000L
#define MASTER_ABORT_INT 0x00100000L
#define TARGET_ABORT_INT 0x00200000L
#define BUS_MASTER_INT 0x00200000L
/****************************************************************************/
struct pcilst_struct {
struct pcilst_struct *next;
int used;
struct pci_dev *pcidev;
unsigned short vendor;
unsigned short device;
unsigned char pci_bus;
unsigned char pci_slot;
unsigned char pci_func;
resource_size_t io_addr[5];
unsigned int irq;
};
/* ptr to root list of all amcc devices */
struct pcilst_struct *amcc_devices;
static const int i_ADDIDATADeviceID[] = { 0x15B8, 0x10E8 };
/****************************************************************************/
void v_pci_card_list_init(unsigned short pci_vendor, char display);
void v_pci_card_list_cleanup(unsigned short pci_vendor);
struct pcilst_struct *ptr_find_free_pci_card_by_device(unsigned short vendor_id,
unsigned short
device_id);
int i_find_free_pci_card_by_position(unsigned short vendor_id,
unsigned short device_id,
unsigned short pci_bus,
unsigned short pci_slot,
struct pcilst_struct **card);
struct pcilst_struct *ptr_select_and_alloc_pci_card(unsigned short vendor_id,
unsigned short device_id,
unsigned short pci_bus,
unsigned short pci_slot,
int i_Master);
int pci_card_alloc(struct pcilst_struct *amcc, int master);
int i_pci_card_free(struct pcilst_struct *amcc);
void v_pci_card_list_display(void);
int i_pci_card_data(struct pcilst_struct *amcc,
unsigned char *pci_bus, unsigned char *pci_slot,
unsigned char *pci_func, resource_size_t * io_addr,
unsigned int *irq);
/****************************************************************************/
/* build list of amcc cards in this system */
void v_pci_card_list_init(unsigned short pci_vendor, char display)
{
struct pci_dev *pcidev;
struct pcilst_struct *amcc, *last;
int i;
int i_Count = 0;
amcc_devices = NULL;
last = NULL;
for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
pcidev != NULL;
pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) {
for (i_Count = 0; i_Count < 2; i_Count++) {
pci_vendor = i_ADDIDATADeviceID[i_Count];
if (pcidev->vendor == pci_vendor) {
amcc = kmalloc(sizeof(*amcc), GFP_KERNEL);
memset(amcc, 0, sizeof(*amcc));
amcc->pcidev = pcidev;
if (last)
last->next = amcc;
else
amcc_devices = amcc;
last = amcc;
amcc->vendor = pcidev->vendor;
amcc->device = pcidev->device;
amcc->pci_bus = pcidev->bus->number;
amcc->pci_slot = PCI_SLOT(pcidev->devfn);
amcc->pci_func = PCI_FUNC(pcidev->devfn);
/* Note: resources may be invalid if PCI device
* not enabled, but they are corrected in
* pci_card_alloc. */
for (i = 0; i < 5; i++)
amcc->io_addr[i] =
pci_resource_start(pcidev, i);
amcc->irq = pcidev->irq;
}
}
}
if (display)
v_pci_card_list_display();
}
/****************************************************************************/
/* free up list of amcc cards in this system */
void v_pci_card_list_cleanup(unsigned short pci_vendor)
{
struct pcilst_struct *amcc, *next;
for (amcc = amcc_devices; amcc; amcc = next) {
next = amcc->next;
kfree(amcc);
}
amcc_devices = NULL;
}
/****************************************************************************/
/* find first unused card with this device_id */
struct pcilst_struct *ptr_find_free_pci_card_by_device(unsigned short vendor_id,
unsigned short device_id)
{
struct pcilst_struct *amcc, *next;
for (amcc = amcc_devices; amcc; amcc = next) {
next = amcc->next;
if ((!amcc->used) && (amcc->device == device_id)
&& (amcc->vendor == vendor_id))
return amcc;
}
return NULL;
}
/****************************************************************************/
/* find card on requested position */
int i_find_free_pci_card_by_position(unsigned short vendor_id,
unsigned short device_id,
unsigned short pci_bus,
unsigned short pci_slot,
struct pcilst_struct **card)
{
struct pcilst_struct *amcc, *next;
*card = NULL;
for (amcc = amcc_devices; amcc; amcc = next) {
next = amcc->next;
if ((amcc->vendor == vendor_id) && (amcc->device == device_id)
&& (amcc->pci_bus == pci_bus)
&& (amcc->pci_slot == pci_slot)) {
if (!(amcc->used)) {
*card = amcc;
return 0; /* ok, card is found */
} else {
rt_printk(" - \nCard on requested position is used b:s %d:%d!\n",
pci_bus, pci_slot);
return 2; /* card exist but is used */
}
}
}
/* no card found */
return 1;
}
/****************************************************************************/
/* mark card as used */
int pci_card_alloc(struct pcilst_struct *amcc, int master)
{
int i;
if (!amcc)
return -1;
if (amcc->used)
return 1;
if (comedi_pci_enable(amcc->pcidev, "addi_amcc_s5933"))
return -1;
/* Resources will be accurate now. */
for (i = 0; i < 5; i++)
amcc->io_addr[i] = pci_resource_start(amcc->pcidev, i);
if (master)
pci_set_master(amcc->pcidev);
amcc->used = 1;
return 0;
}
/****************************************************************************/
/* mark card as free */
int i_pci_card_free(struct pcilst_struct *amcc)
{
if (!amcc)
return -1;
if (!amcc->used)
return 1;
amcc->used = 0;
comedi_pci_disable(amcc->pcidev);
return 0;
}
/****************************************************************************/
/* display list of found cards */
void v_pci_card_list_display(void)
{
struct pcilst_struct *amcc, *next;
printk(KERN_DEBUG "List of pci cards\n");
printk(KERN_DEBUG "bus:slot:func vendor device io_amcc io_daq irq used\n");
for (amcc = amcc_devices; amcc; amcc = next) {
next = amcc->next;
printk
("%2d %2d %2d 0x%4x 0x%4x 0x%8llx 0x%8llx %2u %2d\n",
amcc->pci_bus, amcc->pci_slot, amcc->pci_func,
amcc->vendor, amcc->device,
(unsigned long long)amcc->io_addr[0],
(unsigned long long)amcc->io_addr[2], amcc->irq,
amcc->used);
}
}
/****************************************************************************/
/* return all card information for driver */
int i_pci_card_data(struct pcilst_struct *amcc,
unsigned char *pci_bus, unsigned char *pci_slot,
unsigned char *pci_func, resource_size_t * io_addr,
unsigned int *irq)
{
int i;
if (!amcc)
return -1;
*pci_bus = amcc->pci_bus;
*pci_slot = amcc->pci_slot;
*pci_func = amcc->pci_func;
for (i = 0; i < 5; i++)
io_addr[i] = amcc->io_addr[i];
*irq = amcc->irq;
return 0;
}
/****************************************************************************/
/* select and alloc card */
struct pcilst_struct *ptr_select_and_alloc_pci_card(unsigned short vendor_id,
unsigned short device_id,
unsigned short pci_bus,
unsigned short pci_slot,
int i_Master)
{
struct pcilst_struct *card;
if ((pci_bus < 1) & (pci_slot < 1)) {
/* use autodetection */
card = ptr_find_free_pci_card_by_device(vendor_id, device_id);
if (card == NULL) {
rt_printk(" - Unused card not found in system!\n");
return NULL;
}
} else {
switch (i_find_free_pci_card_by_position(vendor_id, device_id,
pci_bus, pci_slot,
&card)) {
case 1:
rt_printk(" - Card not found on requested position b:s %d:%d!\n",
pci_bus, pci_slot);
return NULL;
case 2:
rt_printk(" - Card on requested position is used b:s %d:%d!\n",
pci_bus, pci_slot);
return NULL;
}
}
if (pci_card_alloc(card, i_Master) != 0) {
rt_printk(" - Can't allocate card!\n");
return NULL;
}
return card;
}
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,462 @@
/*
* Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
*
* ADDI-DATA GmbH
* Dieselstrasse 3
* D-77833 Ottersweier
* Tel: +19(0)7223/9493-0
* Fax: +49(0)7223/9493-92
* http://www.addi-data-com
* info@addi-data.com
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/ioport.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/timex.h>
#include <linux/timer.h>
#include <linux/pci.h>
#include <linux/io.h>
#include <linux/kmod.h>
#include <linux/uaccess.h>
#include "../../comedidev.h"
#include "addi_amcc_s5933.h"
#define ERROR -1
#define SUCCESS 1
/* variable type definition */
typedef unsigned char BYTE, *PBYTE;
typedef short SHORT, *PSHORT;
typedef unsigned short USHORT, *PUSHORT;
typedef unsigned short WORD, *PWORD;
typedef int INT, *PINT;;
typedef unsigned int UINT, *PUINT;
typedef int LONG, *PLONG; /* 32-bit */
typedef unsigned int ULONG, *PULONG; /* 32-bit */
typedef unsigned int DWORD, *PDWORD; /* 32-bit */
typedef unsigned long ULONG_PTR;
typedef const struct comedi_lrange *PCRANGE;
#define LOBYTE(W) (BYTE)((W) & 0xFF)
#define HIBYTE(W) (BYTE)(((W) >> 8) & 0xFF)
#define MAKEWORD(H, L) (USHORT)((L) | ((H) << 8))
#define LOWORD(W) (USHORT)((W) & 0xFFFF)
#define HIWORD(W) (USHORT)(((W) >> 16) & 0xFFFF)
#define MAKEDWORD(H, L) (UINT)((L) | ((H) << 16))
#define ADDI_ENABLE 1
#define ADDI_DISABLE 0
#define APCI1710_SAVE_INTERRUPT 1
#define ADDIDATA_EEPROM 1
#define ADDIDATA_NO_EEPROM 0
#define ADDIDATA_93C76 "93C76"
#define ADDIDATA_S5920 "S5920"
#define ADDIDATA_S5933 "S5933"
#define ADDIDATA_9054 "9054"
/* ADDIDATA Enable Disable */
#define ADDIDATA_ENABLE 1
#define ADDIDATA_DISABLE 0
/* Structures */
/* structure for the boardtype */
typedef struct {
const char *pc_DriverName; // driver name
INT i_VendorId; //PCI vendor a device ID of card
INT i_DeviceId;
INT i_IorangeBase0;
INT i_IorangeBase1;
INT i_IorangeBase2; // base 2 range
INT i_IorangeBase3; // base 3 range
INT i_PCIEeprom; // eeprom present or not
char *pc_EepromChip; // type of chip
INT i_NbrAiChannel; // num of A/D chans
INT i_NbrAiChannelDiff; // num of A/D chans in diff mode
INT i_AiChannelList; // len of chanlist
INT i_NbrAoChannel; // num of D/A chans
INT i_AiMaxdata; // resolution of A/D
INT i_AoMaxdata; // resolution of D/A
PCRANGE pr_AiRangelist; // rangelist for A/D
PCRANGE pr_AoRangelist; // rangelist for D/A
INT i_NbrDiChannel; // Number of DI channels
INT i_NbrDoChannel; // Number of DO channels
INT i_DoMaxdata; // data to set all chanels high
INT i_NbrTTLChannel; // Number of TTL channels
PCRANGE pr_TTLRangelist; // rangelist for TTL
INT i_Dma; // dma present or not
INT i_Timer; // timer subdevice present or not
BYTE b_AvailableConvertUnit;
UINT ui_MinAcquisitiontimeNs; // Minimum Acquisition in Nano secs
UINT ui_MinDelaytimeNs; // Minimum Delay in Nano secs
/* interrupt and reset */
void (*v_hwdrv_Interrupt)(int irq, void *d);
int (*i_hwdrv_Reset)(struct comedi_device *dev);
/* Subdevice functions */
/* ANALOG INPUT */
int (*i_hwdrv_InsnConfigAnalogInput)(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data);
int (*i_hwdrv_InsnReadAnalogInput)(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data);
int (*i_hwdrv_InsnWriteAnalogInput)(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data);
int (*i_hwdrv_InsnBitsAnalogInput)(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data);
int (*i_hwdrv_CommandTestAnalogInput)(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_cmd *cmd);
int (*i_hwdrv_CommandAnalogInput)(struct comedi_device *dev,
struct comedi_subdevice *s);
int (*i_hwdrv_CancelAnalogInput)(struct comedi_device *dev,
struct comedi_subdevice *s);
/* Analog Output */
int (*i_hwdrv_InsnConfigAnalogOutput)(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data);
int (*i_hwdrv_InsnWriteAnalogOutput)(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data);
int (*i_hwdrv_InsnBitsAnalogOutput)(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data);
/* Digital Input */
int (*i_hwdrv_InsnConfigDigitalInput) (struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data);
int (*i_hwdrv_InsnReadDigitalInput) (struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data);
int (*i_hwdrv_InsnWriteDigitalInput) (struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data);
int (*i_hwdrv_InsnBitsDigitalInput) (struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data);
/* Digital Output */
int (*i_hwdrv_InsnConfigDigitalOutput)(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data);
int (*i_hwdrv_InsnWriteDigitalOutput)(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data);
int (*i_hwdrv_InsnBitsDigitalOutput)(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data);
int (*i_hwdrv_InsnReadDigitalOutput)(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data);
/* TIMER */
int (*i_hwdrv_InsnConfigTimer)(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
int (*i_hwdrv_InsnWriteTimer)(struct comedi_device *dev,
struct comedi_subdevice *s, struct comedi_insn *insn,
unsigned int *data);
int (*i_hwdrv_InsnReadTimer)(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
int (*i_hwdrv_InsnBitsTimer)(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
/* TTL IO */
int (*i_hwdr_ConfigInitTTLIO)(struct comedi_device *dev,
struct comedi_subdevice *s, struct comedi_insn *insn,
unsigned int *data);
int (*i_hwdr_ReadTTLIOBits)(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
int (*i_hwdr_ReadTTLIOAllPortValue)(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data);
int (*i_hwdr_WriteTTLIOChlOnOff)(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
} boardtype;
//MODULE INFO STRUCTURE
typedef union {
/* Incremental counter infos */
struct {
union {
struct {
BYTE b_ModeRegister1;
BYTE b_ModeRegister2;
BYTE b_ModeRegister3;
BYTE b_ModeRegister4;
} s_ByteModeRegister;
DWORD dw_ModeRegister1_2_3_4;
} s_ModeRegister;
struct {
unsigned int b_IndexInit:1;
unsigned int b_CounterInit:1;
unsigned int b_ReferenceInit:1;
unsigned int b_IndexInterruptOccur:1;
unsigned int b_CompareLogicInit:1;
unsigned int b_FrequencyMeasurementInit:1;
unsigned int b_FrequencyMeasurementEnable:1;
} s_InitFlag;
} s_SiemensCounterInfo;
/* SSI infos */
struct {
BYTE b_SSIProfile;
BYTE b_PositionTurnLength;
BYTE b_TurnCptLength;
BYTE b_SSIInit;
} s_SSICounterInfo;
/* TTL I/O infos */
struct {
BYTE b_TTLInit;
BYTE b_PortConfiguration[4];
} s_TTLIOInfo;
/* Digital I/O infos */
struct {
BYTE b_DigitalInit;
BYTE b_ChannelAMode;
BYTE b_ChannelBMode;
BYTE b_OutputMemoryEnabled;
DWORD dw_OutputMemory;
} s_DigitalIOInfo;
/*********************/
/* 82X54 timer infos */
/*********************/
struct {
struct {
BYTE b_82X54Init;
BYTE b_InputClockSelection;
BYTE b_InputClockLevel;
BYTE b_OutputLevel;
BYTE b_HardwareGateLevel;
DWORD dw_ConfigurationWord;
} s_82X54TimerInfo[3];
BYTE b_InterruptMask;
} s_82X54ModuleInfo;
/*********************/
/* Chronometer infos */
/*********************/
struct {
BYTE b_ChronoInit;
BYTE b_InterruptMask;
BYTE b_PCIInputClock;
BYTE b_TimingUnit;
BYTE b_CycleMode;
double d_TimingInterval;
DWORD dw_ConfigReg;
} s_ChronoModuleInfo;
/***********************/
/* Pulse encoder infos */
/***********************/
struct {
struct {
BYTE b_PulseEncoderInit;
} s_PulseEncoderInfo[4];
DWORD dw_SetRegister;
DWORD dw_ControlRegister;
DWORD dw_StatusRegister;
} s_PulseEncoderModuleInfo;
/* Tor conter infos */
struct {
struct {
BYTE b_TorCounterInit;
BYTE b_TimingUnit;
BYTE b_InterruptEnable;
double d_TimingInterval;
ULONG ul_RealTimingInterval;
} s_TorCounterInfo[2];
BYTE b_PCIInputClock;
} s_TorCounterModuleInfo;
/* PWM infos */
struct {
struct {
BYTE b_PWMInit;
BYTE b_TimingUnit;
BYTE b_InterruptEnable;
double d_LowTiming;
double d_HighTiming;
ULONG ul_RealLowTiming;
ULONG ul_RealHighTiming;
} s_PWMInfo[2];
BYTE b_ClockSelection;
} s_PWMModuleInfo;
/* ETM infos */
struct {
struct {
BYTE b_ETMEnable;
BYTE b_ETMInterrupt;
} s_ETMInfo[2];
BYTE b_ETMInit;
BYTE b_TimingUnit;
BYTE b_ClockSelection;
double d_TimingInterval;
ULONG ul_Timing;
} s_ETMModuleInfo;
/* CDA infos */
struct {
BYTE b_CDAEnable;
BYTE b_CDAInterrupt;
BYTE b_CDAInit;
BYTE b_FctSelection;
BYTE b_CDAReadFIFOOverflow;
} s_CDAModuleInfo;
} str_ModuleInfo;
/* Private structure for the addi_apci3120 driver */
typedef struct {
INT iobase;
INT i_IobaseAmcc; // base+size for AMCC chip
INT i_IobaseAddon; //addon base address
INT i_IobaseReserved;
ULONG_PTR dw_AiBase;
struct pcilst_struct *amcc; // ptr too AMCC data
BYTE allocated; // we have blocked card
BYTE b_ValidDriver; // driver is ok
BYTE b_AiContinuous; // we do unlimited AI
BYTE b_AiInitialisation;
UINT ui_AiActualScan; //how many scans we finished
UINT ui_AiBufferPtr; // data buffer ptr in samples
UINT ui_AiNbrofChannels; // how many channels is measured
UINT ui_AiScanLength; // Length of actual scanlist
UINT ui_AiActualScanPosition; // position in actual scan
PUINT pui_AiChannelList; // actual chanlist
UINT ui_AiChannelList[32]; // actual chanlist
BYTE b_AiChannelConfiguration[32]; // actual chanlist
UINT ui_AiReadData[32];
DWORD dw_AiInitialised;
UINT ui_AiTimer0; //Timer Constant for Timer0
UINT ui_AiTimer1; //Timer constant for Timer1
UINT ui_AiFlags;
UINT ui_AiDataLength;
short *AiData; // Pointer to sample data
UINT ui_AiNbrofScans; // number of scans to do
USHORT us_UseDma; // To use Dma or not
BYTE b_DmaDoubleBuffer; // we can use double buffering
UINT ui_DmaActualBuffer; // which buffer is used now
//*UPDATE-0.7.57->0.7.68
//ULONG ul_DmaBufferVirtual[2];// pointers to begin of DMA buffer
short *ul_DmaBufferVirtual[2]; // pointers to begin of DMA buffer
ULONG ul_DmaBufferHw[2]; // hw address of DMA buff
UINT ui_DmaBufferSize[2]; // size of dma buffer in bytes
UINT ui_DmaBufferUsesize[2]; // which size we may now used for transfer
UINT ui_DmaBufferSamples[2]; // size in samples
UINT ui_DmaBufferPages[2]; // number of pages in buffer
BYTE b_DigitalOutputRegister; // Digital Output Register
BYTE b_OutputMemoryStatus;
BYTE b_AnalogInputChannelNbr; // Analog input channel Nbr
BYTE b_AnalogOutputChannelNbr; // Analog input Output Nbr
BYTE b_TimerSelectMode; // Contain data written at iobase + 0C
BYTE b_ModeSelectRegister; // Contain data written at iobase + 0E
USHORT us_OutputRegister; // Contain data written at iobase + 0
BYTE b_InterruptState;
BYTE b_TimerInit; // Specify if InitTimerWatchdog was load
BYTE b_TimerStarted; // Specify if timer 2 is running or not
BYTE b_Timer2Mode; // Specify the timer 2 mode
BYTE b_Timer2Interrupt; //Timer2 interrupt enable or disable
BYTE b_AiCyclicAcquisition; // indicate cyclic acquisition
BYTE b_InterruptMode; // eoc eos or dma
BYTE b_EocEosInterrupt; // Enable disable eoc eos interrupt
UINT ui_EocEosConversionTime;
BYTE b_EocEosConversionTimeBase;
BYTE b_SingelDiff;
BYTE b_ExttrigEnable; /* To enable or disable external trigger */
/* Pointer to the current process */
struct task_struct *tsk_Current;
boardtype *ps_BoardInfo;
/* Hardware board infos for 1710 */
struct {
UINT ui_Address; /* Board address */
UINT ui_FlashAddress;
BYTE b_InterruptNbr; /* Board interrupt number */
BYTE b_SlotNumber; /* PCI slot number */
BYTE b_BoardVersion;
DWORD dw_MolduleConfiguration[4]; /* Module config */
} s_BoardInfos;
/* Interrupt infos */
struct {
ULONG ul_InterruptOccur; /* 0 : No interrupt occur */
/* > 0 : Interrupt occur */
UINT ui_Read; /* Read FIFO */
UINT ui_Write; /* Write FIFO */
struct {
BYTE b_OldModuleMask;
ULONG ul_OldInterruptMask; /* Interrupt mask */
ULONG ul_OldCounterLatchValue; /* Interrupt counter value */
} s_FIFOInterruptParameters[APCI1710_SAVE_INTERRUPT];
} s_InterruptParameters;
str_ModuleInfo s_ModuleInfo[4];
ULONG ul_TTLPortConfiguration[10];
} addi_private;
static unsigned short pci_list_builded; /* set to 1 when list of card is known */
/* Function declarations */
static int i_ADDI_Attach(struct comedi_device *dev, struct comedi_devconfig *it);
static int i_ADDI_Detach(struct comedi_device *dev);
static int i_ADDI_Reset(struct comedi_device *dev);
static irqreturn_t v_ADDI_Interrupt(int irq, void *d PT_REGS_ARG);
static int i_ADDIDATA_InsnReadEeprom(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,457 @@
/*
Modified by umesh on 16th may 2001
Modified by sarath on 22nd may 2001
*/
/*
comedi/drivers/amcc_s5933_v_58.h
Stuff for AMCC S5933 PCI Controller
Author: Michal Dobes <majkl@tesnet.cz>
Inspirated from general-purpose AMCC S5933 PCI Matchmaker driver
made by Andrea Cisternino <acister@pcape1.pi.infn.it>
and as result of espionage from MITE code made by David A. Schleef.
Thanks to AMCC for their on-line documentation and bus master DMA
example.
*/
#ifndef _AMCC_S5933_H_
#define _AMCC_S5933_H_
#include <linux/pci.h>
#include "../../comedidev.h"
#ifdef PCI_SUPPORT_VER1
#error Sorry, no support for 2.1.55 and older! :-((((
#endif
/***********Added by sarath for compatibility with APCI3120
*************************/
#define FIFO_ADVANCE_ON_BYTE_2 0x20000000 // written on base0
#define AMWEN_ENABLE 0x02 // added for step 6 dma written on base2
#define A2P_FIFO_WRITE_ENABLE 0x01
#define AGCSTS_TC_ENABLE 0x10000000 // Added for transfer count enable bit
// ADDON RELATED ADDITIONS
// Constant
#define APCI3120_ENABLE_TRANSFER_ADD_ON_LOW 0x00
#define APCI3120_ENABLE_TRANSFER_ADD_ON_HIGH 0x1200
#define APCI3120_A2P_FIFO_MANAGEMENT 0x04000400L
#define APCI3120_AMWEN_ENABLE 0x02
#define APCI3120_A2P_FIFO_WRITE_ENABLE 0x01
#define APCI3120_FIFO_ADVANCE_ON_BYTE_2 0x20000000L
#define APCI3120_ENABLE_WRITE_TC_INT 0x00004000L
#define APCI3120_CLEAR_WRITE_TC_INT 0x00040000L
#define APCI3120_DISABLE_AMWEN_AND_A2P_FIFO_WRITE 0x0
#define APCI3120_DISABLE_BUS_MASTER_ADD_ON 0x0
#define APCI3120_DISABLE_BUS_MASTER_PCI 0x0
// ADD_ON ::: this needed since apci supports 16 bit interface to add on
#define APCI3120_ADD_ON_AGCSTS_LOW 0x3C
#define APCI3120_ADD_ON_AGCSTS_HIGH APCI3120_ADD_ON_AGCSTS_LOW + 2
#define APCI3120_ADD_ON_MWAR_LOW 0x24
#define APCI3120_ADD_ON_MWAR_HIGH APCI3120_ADD_ON_MWAR_LOW + 2
#define APCI3120_ADD_ON_MWTC_LOW 0x058
#define APCI3120_ADD_ON_MWTC_HIGH APCI3120_ADD_ON_MWTC_LOW + 2
// AMCC
#define APCI3120_AMCC_OP_MCSR 0x3C
#define APCI3120_AMCC_OP_REG_INTCSR 0x38
/*******from here all upward definitions are added by sarath */
/****************************************************************************/
/* AMCC Operation Register Offsets - PCI */
/****************************************************************************/
#define AMCC_OP_REG_OMB1 0x00
#define AMCC_OP_REG_OMB2 0x04
#define AMCC_OP_REG_OMB3 0x08
#define AMCC_OP_REG_OMB4 0x0c
#define AMCC_OP_REG_IMB1 0x10
#define AMCC_OP_REG_IMB2 0x14
#define AMCC_OP_REG_IMB3 0x18
#define AMCC_OP_REG_IMB4 0x1c
#define AMCC_OP_REG_FIFO 0x20
#define AMCC_OP_REG_MWAR 0x24
#define AMCC_OP_REG_MWTC 0x28
#define AMCC_OP_REG_MRAR 0x2c
#define AMCC_OP_REG_MRTC 0x30
#define AMCC_OP_REG_MBEF 0x34
#define AMCC_OP_REG_INTCSR 0x38
#define AMCC_OP_REG_INTCSR_SRC (AMCC_OP_REG_INTCSR + 2) /* INT source */
#define AMCC_OP_REG_INTCSR_FEC (AMCC_OP_REG_INTCSR + 3) /* FIFO ctrl */
#define AMCC_OP_REG_MCSR 0x3c
#define AMCC_OP_REG_MCSR_NVDATA (AMCC_OP_REG_MCSR + 2) /* Data in byte 2 */
#define AMCC_OP_REG_MCSR_NVCMD (AMCC_OP_REG_MCSR + 3) /* Command in byte 3 */
#define AMCC_FIFO_DEPTH_DWORD 8
#define AMCC_FIFO_DEPTH_BYTES (8 * sizeof (u32))
/****************************************************************************/
/* AMCC Operation Registers Size - PCI */
/****************************************************************************/
#define AMCC_OP_REG_SIZE 64 /* in bytes */
/****************************************************************************/
/* AMCC Operation Register Offsets - Add-on */
/****************************************************************************/
#define AMCC_OP_REG_AIMB1 0x00
#define AMCC_OP_REG_AIMB2 0x04
#define AMCC_OP_REG_AIMB3 0x08
#define AMCC_OP_REG_AIMB4 0x0c
#define AMCC_OP_REG_AOMB1 0x10
#define AMCC_OP_REG_AOMB2 0x14
#define AMCC_OP_REG_AOMB3 0x18
#define AMCC_OP_REG_AOMB4 0x1c
#define AMCC_OP_REG_AFIFO 0x20
#define AMCC_OP_REG_AMWAR 0x24
#define AMCC_OP_REG_APTA 0x28
#define AMCC_OP_REG_APTD 0x2c
#define AMCC_OP_REG_AMRAR 0x30
#define AMCC_OP_REG_AMBEF 0x34
#define AMCC_OP_REG_AINT 0x38
#define AMCC_OP_REG_AGCSTS 0x3c
#define AMCC_OP_REG_AMWTC 0x58
#define AMCC_OP_REG_AMRTC 0x5c
/****************************************************************************/
/* AMCC - Add-on General Control/Status Register */
/****************************************************************************/
#define AGCSTS_CONTROL_MASK 0xfffff000
#define AGCSTS_NV_ACC_MASK 0xe0000000
#define AGCSTS_RESET_MASK 0x0e000000
#define AGCSTS_NV_DA_MASK 0x00ff0000
#define AGCSTS_BIST_MASK 0x0000f000
#define AGCSTS_STATUS_MASK 0x000000ff
#define AGCSTS_TCZERO_MASK 0x000000c0
#define AGCSTS_FIFO_ST_MASK 0x0000003f
#define AGCSTS_RESET_MBFLAGS 0x08000000
#define AGCSTS_RESET_P2A_FIFO 0x04000000
#define AGCSTS_RESET_A2P_FIFO 0x02000000
#define AGCSTS_RESET_FIFOS (AGCSTS_RESET_A2P_FIFO | AGCSTS_RESET_P2A_FIFO)
#define AGCSTS_A2P_TCOUNT 0x00000080
#define AGCSTS_P2A_TCOUNT 0x00000040
#define AGCSTS_FS_P2A_EMPTY 0x00000020
#define AGCSTS_FS_P2A_HALF 0x00000010
#define AGCSTS_FS_P2A_FULL 0x00000008
#define AGCSTS_FS_A2P_EMPTY 0x00000004
#define AGCSTS_FS_A2P_HALF 0x00000002
#define AGCSTS_FS_A2P_FULL 0x00000001
/****************************************************************************/
/* AMCC - Add-on Interrupt Control/Status Register */
/****************************************************************************/
#define AINT_INT_MASK 0x00ff0000
#define AINT_SEL_MASK 0x0000ffff
#define AINT_IS_ENSEL_MASK 0x00001f1f
#define AINT_INT_ASSERTED 0x00800000
#define AINT_BM_ERROR 0x00200000
#define AINT_BIST_INT 0x00100000
#define AINT_RT_COMPLETE 0x00080000
#define AINT_WT_COMPLETE 0x00040000
#define AINT_OUT_MB_INT 0x00020000
#define AINT_IN_MB_INT 0x00010000
#define AINT_READ_COMPL 0x00008000
#define AINT_WRITE_COMPL 0x00004000
#define AINT_OMB_ENABLE 0x00001000
#define AINT_OMB_SELECT 0x00000c00
#define AINT_OMB_BYTE 0x00000300
#define AINT_IMB_ENABLE 0x00000010
#define AINT_IMB_SELECT 0x0000000c
#define AINT_IMB_BYTE 0x00000003
/* Enable Bus Mastering */
#define EN_A2P_TRANSFERS 0x00000400
/* FIFO Flag Reset */
#define RESET_A2P_FLAGS 0x04000000L
/* FIFO Relative Priority */
#define A2P_HI_PRIORITY 0x00000100L
/* Identify Interrupt Sources */
#define ANY_S593X_INT 0x00800000L
#define READ_TC_INT 0x00080000L
#define WRITE_TC_INT 0x00040000L
#define IN_MB_INT 0x00020000L
#define MASTER_ABORT_INT 0x00100000L
#define TARGET_ABORT_INT 0x00200000L
#define BUS_MASTER_INT 0x00200000L
/****************************************************************************/
struct pcilst_struct {
struct pcilst_struct *next;
int used;
struct pci_dev *pcidev;
unsigned short vendor;
unsigned short device;
unsigned int master;
unsigned char pci_bus;
unsigned char pci_slot;
unsigned char pci_func;
unsigned int io_addr[5];
unsigned int irq;
};
struct pcilst_struct *amcc_devices; // ptr to root list of all amcc devices
/****************************************************************************/
void v_pci_card_list_init(unsigned short pci_vendor, char display);
void v_pci_card_list_cleanup(unsigned short pci_vendor);
struct pcilst_struct *ptr_find_free_pci_card_by_device(unsigned short vendor_id,
unsigned short
device_id);
int i_find_free_pci_card_by_position(unsigned short vendor_id,
unsigned short device_id,
unsigned short pci_bus,
unsigned short pci_slot,
struct pcilst_struct **card);
struct pcilst_struct *ptr_select_and_alloc_pci_card(unsigned short vendor_id,
unsigned short device_id,
unsigned short pci_bus,
unsigned short pci_slot);
int i_pci_card_alloc(struct pcilst_struct *amcc);
int i_pci_card_free(struct pcilst_struct *amcc);
void v_pci_card_list_display(void);
int i_pci_card_data(struct pcilst_struct *amcc,
unsigned char *pci_bus, unsigned char *pci_slot,
unsigned char *pci_func, unsigned short *io_addr,
unsigned short *irq, unsigned short *master);
/****************************************************************************/
/* build list of amcc cards in this system */
void v_pci_card_list_init(unsigned short pci_vendor, char display)
{
struct pci_dev *pcidev;
struct pcilst_struct *amcc, *last;
int i;
amcc_devices = NULL;
last = NULL;
pci_for_each_dev(pcidev) {
if (pcidev->vendor == pci_vendor) {
amcc = kmalloc(sizeof(*amcc), GFP_KERNEL);
memset(amcc, 0, sizeof(*amcc));
amcc->pcidev = pcidev;
if (last) {
last->next = amcc;
} else {
amcc_devices = amcc;
}
last = amcc;
amcc->vendor = pcidev->vendor;
amcc->device = pcidev->device;
#if 0
amcc->master = pcidev->master; // how get this information under 2.4 kernels?
#endif
amcc->pci_bus = pcidev->bus->number;
amcc->pci_slot = PCI_SLOT(pcidev->devfn);
amcc->pci_func = PCI_FUNC(pcidev->devfn);
for (i = 0; i < 5; i++)
amcc->io_addr[i] =
pcidev->resource[i].start & ~3UL;
amcc->irq = pcidev->irq;
}
}
if (display)
v_pci_card_list_display();
}
/****************************************************************************/
/* free up list of amcc cards in this system */
void v_pci_card_list_cleanup(unsigned short pci_vendor)
{
struct pcilst_struct *amcc, *next;
for (amcc = amcc_devices; amcc; amcc = next) {
next = amcc->next;
kfree(amcc);
}
amcc_devices = NULL;
}
/****************************************************************************/
/* find first unused card with this device_id */
struct pcilst_struct *ptr_find_free_pci_card_by_device(unsigned short vendor_id,
unsigned short device_id)
{
struct pcilst_struct *amcc, *next;
for (amcc = amcc_devices; amcc; amcc = next) {
next = amcc->next;
if ((!amcc->used) && (amcc->device == device_id)
&& (amcc->vendor == vendor_id))
return amcc;
}
return NULL;
}
/****************************************************************************/
/* find card on requested position */
int i_find_free_pci_card_by_position(unsigned short vendor_id,
unsigned short device_id,
unsigned short pci_bus,
unsigned short pci_slot,
struct pcilst_struct **card)
{
struct pcilst_struct *amcc, *next;
*card = NULL;
for (amcc = amcc_devices; amcc; amcc = next) {
next = amcc->next;
if ((amcc->vendor == vendor_id) && (amcc->device == device_id)
&& (amcc->pci_bus == pci_bus)
&& (amcc->pci_slot == pci_slot)) {
if (!(amcc->used)) {
*card = amcc;
return 0; // ok, card is found
} else {
rt_printk
(" - \nCard on requested position is used b:s %d:%d!\n",
pci_bus, pci_slot);
return 2; // card exist but is used
}
}
}
return 1; // no card found
}
/****************************************************************************/
/* mark card as used */
int i_pci_card_alloc(struct pcilst_struct *amcc)
{
if (!amcc)
return -1;
if (amcc->used)
return 1;
amcc->used = 1;
return 0;
}
/****************************************************************************/
/* mark card as free */
int i_pci_card_free(struct pcilst_struct *amcc)
{
if (!amcc)
return -1;
if (!amcc->used)
return 1;
amcc->used = 0;
return 0;
}
/****************************************************************************/
/* display list of found cards */
void v_pci_card_list_display(void)
{
struct pcilst_struct *amcc, *next;
printk("List of pci cards\n");
printk("bus:slot:func vendor device master io_amcc io_daq irq used\n");
for (amcc = amcc_devices; amcc; amcc = next) {
next = amcc->next;
printk
("%2d %2d %2d 0x%4x 0x%4x %3s 0x%4x 0x%4x %2d %2d\n",
amcc->pci_bus, amcc->pci_slot, amcc->pci_func,
amcc->vendor, amcc->device, amcc->master ? "yes" : "no",
amcc->io_addr[0], amcc->io_addr[2], amcc->irq, amcc->used);
}
}
/****************************************************************************/
/* return all card information for driver */
int i_pci_card_data(struct pcilst_struct *amcc,
unsigned char *pci_bus, unsigned char *pci_slot,
unsigned char *pci_func, unsigned short *io_addr,
unsigned short *irq, unsigned short *master)
{
int i;
if (!amcc)
return -1;
*pci_bus = amcc->pci_bus;
*pci_slot = amcc->pci_slot;
*pci_func = amcc->pci_func;
for (i = 0; i < 5; i++)
io_addr[i] = amcc->io_addr[i];
*irq = amcc->irq;
*master = amcc->master;
return 0;
}
/****************************************************************************/
/* select and alloc card */
struct pcilst_struct *ptr_select_and_alloc_pci_card(unsigned short vendor_id,
unsigned short device_id,
unsigned short pci_bus,
unsigned short pci_slot)
{
struct pcilst_struct *card;
if ((pci_bus < 1) & (pci_slot < 1)) { // use autodetection
if ((card = ptr_find_free_pci_card_by_device(vendor_id,
device_id)) ==
NULL) {
rt_printk(" - Unused card not found in system!\n");
return NULL;
}
} else {
switch (i_find_free_pci_card_by_position(vendor_id, device_id,
pci_bus, pci_slot,
&card)) {
case 1:
rt_printk
(" - Card not found on requested position b:s %d:%d!\n",
pci_bus, pci_slot);
return NULL;
case 2:
rt_printk
(" - Card on requested position is used b:s %d:%d!\n",
pci_bus, pci_slot);
return NULL;
}
}
if (i_pci_card_alloc(card) != 0) {
rt_printk(" - Can't allocate card!\n");
return NULL;
}
return card;
}
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,71 @@
/*
* Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
*
* ADDI-DATA GmbH
* Dieselstrasse 3
* D-77833 Ottersweier
* Tel: +19(0)7223/9493-0
* Fax: +49(0)7223/9493-92
* http://www.addi-data-com
* info@addi-data.com
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*/
#define COMEDI_SUBD_TTLIO 11 /* Digital Input Output But TTL */
#define COMEDI_SUBD_PWM 12 /* Pulse width Measurement */
#define COMEDI_SUBD_SSI 13 /* Synchronous serial interface */
#define COMEDI_SUBD_TOR 14 /* Tor counter */
#define COMEDI_SUBD_CHRONO 15 /* Chrono meter */
#define COMEDI_SUBD_PULSEENCODER 16 /* Pulse Encoder INP CPT */
#define COMEDI_SUBD_INCREMENTALCOUNTER 17 /* Incremental Counter */
#define APCI1710_BOARD_NAME "apci1710"
#define APCI1710_BOARD_VENDOR_ID 0x10E8
#define APCI1710_BOARD_DEVICE_ID 0x818F
#define APCI1710_ADDRESS_RANGE 256
#define APCI1710_CONFIG_ADDRESS_RANGE 8
#define APCI1710_INCREMENTAL_COUNTER 0x53430000UL
#define APCI1710_SSI_COUNTER 0x53490000UL
#define APCI1710_TTL_IO 0x544C0000UL
#define APCI1710_DIGITAL_IO 0x44490000UL
#define APCI1710_82X54_TIMER 0x49430000UL
#define APCI1710_CHRONOMETER 0x43480000UL
#define APCI1710_PULSE_ENCODER 0x495A0000UL
#define APCI1710_TOR_COUNTER 0x544F0000UL
#define APCI1710_PWM 0x50570000UL
#define APCI1710_ETM 0x45540000UL
#define APCI1710_CDA 0x43440000UL
#define APCI1710_DISABLE 0
#define APCI1710_ENABLE 1
#define APCI1710_SYNCHRONOUS_MODE 1
#define APCI1710_ASYNCHRONOUS_MODE 0
//MODULE INFO STRUCTURE
static const struct comedi_lrange range_apci1710_ttl = { 4, {
BIP_RANGE(10),
BIP_RANGE(5),
BIP_RANGE(2),
BIP_RANGE(1)
}
};
static const struct comedi_lrange range_apci1710_ssi = { 4, {
BIP_RANGE(10),
BIP_RANGE(5),
BIP_RANGE(2),
BIP_RANGE(1)
}
};
static const struct comedi_lrange range_apci1710_inccpt = { 4, {
BIP_RANGE(10),
BIP_RANGE(5),
BIP_RANGE(2),
BIP_RANGE(1)
}
};

View file

@ -0,0 +1,600 @@
/**
@verbatim
Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
ADDI-DATA GmbH
Dieselstrasse 3
D-77833 Ottersweier
Tel: +19(0)7223/9493-0
Fax: +49(0)7223/9493-92
http://www.addi-data-com
info@addi-data.com
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
You shoud also find the complete GPL in the COPYING file accompanying this source code.
@endverbatim
*/
/*
+-----------------------------------------------------------------------+
| (C) ADDI-DATA GmbH Dieselstraße 3 D-77833 Ottersweier |
+-----------------------------------------------------------------------+
| Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com |
| Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com |
+-------------------------------+---------------------------------------+
| Project : APCI-035 | Compiler : GCC |
| Module name : hwdrv_apci035.c | Version : 2.96 |
+-------------------------------+---------------------------------------+
| Project manager: Eric Stolz | Date : 02/12/2002 |
+-------------------------------+---------------------------------------+
| Description : Hardware Layer Acces For APCI-035 |
+-----------------------------------------------------------------------+
| UPDATES |
+----------+-----------+------------------------------------------------+
| Date | Author | Description of updates |
+----------+-----------+------------------------------------------------+
| | | |
| | | |
| | | |
+----------+-----------+------------------------------------------------+
*/
/*
+----------------------------------------------------------------------------+
| Included files |
+----------------------------------------------------------------------------+
*/
#include "hwdrv_apci035.h"
INT i_WatchdogNbr = 0;
INT i_Temp = 0;
INT i_Flag = 1;
/*
+----------------------------------------------------------------------------+
| Function Name : int i_APCI035_ConfigTimerWatchdog |
| (struct comedi_device *dev,struct comedi_subdevice *s, |
| struct comedi_insn *insn,unsigned int *data) |
+----------------------------------------------------------------------------+
| Task : Configures The Timer , Counter or Watchdog |
+----------------------------------------------------------------------------+
| Input Parameters : struct comedi_device *dev : Driver handle |
| UINT *data : Data Pointer contains |
| configuration parameters as below |
| |
| data[0] : 0 Configure As Timer |
| 1 Configure As Watchdog |
data[1] : Watchdog number
| data[2] : Time base Unit |
| data[3] : Reload Value |
data[4] : External Trigger |
1:Enable
0:Disable
data[5] :External Trigger Level
00 Trigger Disabled
01 Trigger Enabled (Low level)
10 Trigger Enabled (High Level)
11 Trigger Enabled (High/Low level)
data[6] : External Gate |
1:Enable
0:Disable
data[7] : External Gate level
00 Gate Disabled
01 Gate Enabled (Low level)
10 Gate Enabled (High Level)
data[8] :Warning Relay
1: ENABLE
0: DISABLE
data[9] :Warning Delay available
data[10] :Warning Relay Time unit
data[11] :Warning Relay Time Reload value
data[12] :Reset Relay
1 : ENABLE
0 : DISABLE
data[13] :Interrupt
1 : ENABLE
0 : DISABLE
|
+----------------------------------------------------------------------------+
| Output Parameters : -- |
+----------------------------------------------------------------------------+
| Return Value : TRUE : No error occur |
| : FALSE : Error occur. Return the error |
| |
+----------------------------------------------------------------------------+
*/
INT i_APCI035_ConfigTimerWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
struct comedi_insn * insn, unsigned int * data)
{
UINT ui_Status = 0;
UINT ui_Command = 0;
UINT ui_Mode = 0;
i_Temp = 0;
devpriv->tsk_Current = current;
devpriv->b_TimerSelectMode = data[0];
i_WatchdogNbr = data[1];
if (data[0] == 0) {
ui_Mode = 2;
} else {
ui_Mode = 0;
}
//ui_Command = inl(devpriv->iobase+((i_WatchdogNbr-1)*32)+12);
ui_Command = 0;
//ui_Command = ui_Command & 0xFFFFF9FEUL;
outl(ui_Command, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
ui_Command = 0;
ui_Command = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
/************************/
/* Set the reload value */
/************************/
outl(data[3], devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 4);
/*********************/
/* Set the time unit */
/*********************/
outl(data[2], devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 8);
if (data[0] == ADDIDATA_TIMER) {
/******************************/
/* Set the mode : */
/* - Disable the hardware */
/* - Disable the counter mode */
/* - Disable the warning */
/* - Disable the reset */
/* - Enable the timer mode */
/* - Set the timer mode */
/******************************/
ui_Command =
(ui_Command & 0xFFF719E2UL) | ui_Mode << 13UL | 0x10UL;
} //if (data[0] == ADDIDATA_TIMER)
else {
if (data[0] == ADDIDATA_WATCHDOG) {
/******************************/
/* Set the mode : */
/* - Disable the hardware */
/* - Disable the counter mode */
/* - Disable the warning */
/* - Disable the reset */
/* - Disable the timer mode */
/******************************/
ui_Command = ui_Command & 0xFFF819E2UL;
} else {
printk("\n The parameter for Timer/watchdog selection is in error\n");
return -EINVAL;
}
}
outl(ui_Command, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
ui_Command = 0;
ui_Command = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
/********************************/
/* Disable the hardware trigger */
/********************************/
ui_Command = ui_Command & 0xFFFFF89FUL;
if (data[4] == ADDIDATA_ENABLE) {
/**********************************/
/* Set the hardware trigger level */
/**********************************/
ui_Command = ui_Command | (data[5] << 5);
}
outl(ui_Command, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
ui_Command = 0;
ui_Command = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
/*****************************/
/* Disable the hardware gate */
/*****************************/
ui_Command = ui_Command & 0xFFFFF87FUL;
if (data[6] == ADDIDATA_ENABLE) {
/*******************************/
/* Set the hardware gate level */
/*******************************/
ui_Command = ui_Command | (data[7] << 7);
}
outl(ui_Command, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
ui_Command = 0;
ui_Command = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
/*******************************/
/* Disable the hardware output */
/*******************************/
ui_Command = ui_Command & 0xFFFFF9FBUL;
/*********************************/
/* Set the hardware output level */
/*********************************/
ui_Command = ui_Command | (data[8] << 2);
outl(ui_Command, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
if (data[9] == ADDIDATA_ENABLE) {
/************************/
/* Set the reload value */
/************************/
outl(data[11],
devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 24);
/**********************/
/* Set the time unite */
/**********************/
outl(data[10],
devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 28);
}
ui_Command = 0;
ui_Command = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
/*******************************/
/* Disable the hardware output */
/*******************************/
ui_Command = ui_Command & 0xFFFFF9F7UL;
/*********************************/
/* Set the hardware output level */
/*********************************/
ui_Command = ui_Command | (data[12] << 3);
outl(ui_Command, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
/*************************************/
/** Enable the watchdog interrupt **/
/*************************************/
ui_Command = 0;
ui_Command = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
/*******************************/
/* Set the interrupt selection */
/*******************************/
ui_Status = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 16);
ui_Command = (ui_Command & 0xFFFFF9FDUL) | (data[13] << 1);
outl(ui_Command, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
return insn->n;
}
/*
+----------------------------------------------------------------------------+
| Function Name : int i_APCI035_StartStopWriteTimerWatchdog |
| (struct comedi_device *dev,struct comedi_subdevice *s, |
| struct comedi_insn *insn,unsigned int *data) |
+----------------------------------------------------------------------------+
| Task : Start / Stop The Selected Timer , or Watchdog |
+----------------------------------------------------------------------------+
| Input Parameters : struct comedi_device *dev : Driver handle |
| UINT *data : Data Pointer contains |
| configuration parameters as below |
| |
| data[0] : 0 - Stop Selected Timer/Watchdog |
| 1 - Start Selected Timer/Watchdog |
| 2 - Trigger Selected Timer/Watchdog |
| 3 - Stop All Timer/Watchdog |
| 4 - Start All Timer/Watchdog |
| 5 - Trigger All Timer/Watchdog |
| |
+----------------------------------------------------------------------------+
| Output Parameters : -- |
+----------------------------------------------------------------------------+
| Return Value : TRUE : No error occur |
| : FALSE : Error occur. Return the error |
| |
+----------------------------------------------------------------------------+
*/
INT i_APCI035_StartStopWriteTimerWatchdog(struct comedi_device * dev,
struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
{
UINT ui_Command = 0;
INT i_Count = 0;
if (data[0] == 1) {
ui_Command =
inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
/**********************/
/* Start the hardware */
/**********************/
ui_Command = (ui_Command & 0xFFFFF9FFUL) | 0x1UL;
outl(ui_Command,
devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
} // if (data[0]==1)
if (data[0] == 2) {
ui_Command =
inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
/***************************/
/* Set the trigger command */
/***************************/
ui_Command = (ui_Command & 0xFFFFF9FFUL) | 0x200UL;
outl(ui_Command,
devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
}
if (data[0] == 0) //Stop The Watchdog
{
//Stop The Watchdog
ui_Command = 0;
//ui_Command = inl(devpriv->iobase+((i_WatchdogNbr-1)*32)+12);
//ui_Command = ui_Command & 0xFFFFF9FEUL;
outl(ui_Command,
devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
} // if (data[1]==0)
if (data[0] == 3) //stop all Watchdogs
{
ui_Command = 0;
for (i_Count = 1; i_Count <= 4; i_Count++) {
if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) {
ui_Command = 0x2UL;
} else {
ui_Command = 0x10UL;
}
i_WatchdogNbr = i_Count;
outl(ui_Command,
devpriv->iobase + ((i_WatchdogNbr - 1) * 32) +
0);
}
}
if (data[0] == 4) //start all Watchdogs
{
ui_Command = 0;
for (i_Count = 1; i_Count <= 4; i_Count++) {
if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) {
ui_Command = 0x1UL;
} else {
ui_Command = 0x8UL;
}
i_WatchdogNbr = i_Count;
outl(ui_Command,
devpriv->iobase + ((i_WatchdogNbr - 1) * 32) +
0);
}
}
if (data[0] == 5) //trigger all Watchdogs
{
ui_Command = 0;
for (i_Count = 1; i_Count <= 4; i_Count++) {
if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) {
ui_Command = 0x4UL;
} else {
ui_Command = 0x20UL;
}
i_WatchdogNbr = i_Count;
outl(ui_Command,
devpriv->iobase + ((i_WatchdogNbr - 1) * 32) +
0);
}
i_Temp = 1;
}
return insn->n;
}
/*
+----------------------------------------------------------------------------+
| Function Name : int i_APCI035_ReadTimerWatchdog |
| (struct comedi_device *dev,struct comedi_subdevice *s, |
| struct comedi_insn *insn,unsigned int *data) |
+----------------------------------------------------------------------------+
| Task : Read The Selected Timer , Counter or Watchdog |
+----------------------------------------------------------------------------+
| Input Parameters : struct comedi_device *dev : Driver handle |
| UINT *data : Data Pointer contains |
| configuration parameters as below |
| |
| |
+----------------------------------------------------------------------------+
| Output Parameters : data[0] : software trigger status
data[1] : hardware trigger status
| data[2] : Software clear status
data[3] : Overflow status
data[4] : Timer actual value
+----------------------------------------------------------------------------+
| Return Value : TRUE : No error occur |
| : FALSE : Error occur. Return the error |
| |
+----------------------------------------------------------------------------+
*/
INT i_APCI035_ReadTimerWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
struct comedi_insn * insn, unsigned int * data)
{
UINT ui_Status = 0; // Status register
i_WatchdogNbr = insn->unused[0];
/******************/
/* Get the status */
/******************/
ui_Status = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 16);
/***********************************/
/* Get the software trigger status */
/***********************************/
data[0] = ((ui_Status >> 1) & 1);
/***********************************/
/* Get the hardware trigger status */
/***********************************/
data[1] = ((ui_Status >> 2) & 1);
/*********************************/
/* Get the software clear status */
/*********************************/
data[2] = ((ui_Status >> 3) & 1);
/***************************/
/* Get the overflow status */
/***************************/
data[3] = ((ui_Status >> 0) & 1);
if (devpriv->b_TimerSelectMode == ADDIDATA_TIMER) {
data[4] = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 0);
} // if (devpriv->b_TimerSelectMode==ADDIDATA_TIMER)
return insn->n;
}
/*
+----------------------------------------------------------------------------+
| Function Name : INT i_APCI035_ConfigAnalogInput |
| (struct comedi_device *dev,struct comedi_subdevice *s, |
| struct comedi_insn *insn,unsigned int *data) |
+----------------------------------------------------------------------------+
| Task : Configures The Analog Input Subdevice |
+----------------------------------------------------------------------------+
| Input Parameters : struct comedi_device *dev : Driver handle |
| struct comedi_subdevice *s : Subdevice Pointer |
| struct comedi_insn *insn : Insn Structure Pointer |
| unsigned int *data : Data Pointer contains |
| configuration parameters as below |
| data[0] : Warning delay value
| |
+----------------------------------------------------------------------------+
| Output Parameters : -- |
+----------------------------------------------------------------------------+
| Return Value : TRUE : No error occur |
| : FALSE : Error occur. Return the error |
| |
+----------------------------------------------------------------------------+
*/
INT i_APCI035_ConfigAnalogInput(struct comedi_device * dev, struct comedi_subdevice * s,
struct comedi_insn * insn, unsigned int * data)
{
devpriv->tsk_Current = current;
outl(0x200 | 0, devpriv->iobase + 128 + 0x4);
outl(0, devpriv->iobase + 128 + 0);
/********************************/
/* Initialise the warning value */
/********************************/
outl(0x300 | 0, devpriv->iobase + 128 + 0x4);
outl((data[0] << 8), devpriv->iobase + 128 + 0);
outl(0x200000UL, devpriv->iobase + 128 + 12);
return insn->n;
}
/*
+----------------------------------------------------------------------------+
| Function Name : int i_APCI035_ReadAnalogInput |
| (struct comedi_device *dev,struct comedi_subdevice *s, |
| struct comedi_insn *insn,unsigned int *data) |
+----------------------------------------------------------------------------+
| Task : Read value of the selected channel |
+----------------------------------------------------------------------------+
| Input Parameters : struct comedi_device *dev : Driver handle |
| UINT ui_NoOfChannels : No Of Channels To read |
| UINT *data : Data Pointer to read status |
+----------------------------------------------------------------------------+
| Output Parameters : -- |
| data[0] : Digital Value Of Input |
| |
+----------------------------------------------------------------------------+
| Return Value : TRUE : No error occur |
| : FALSE : Error occur. Return the error |
| |
+----------------------------------------------------------------------------+
*/
INT i_APCI035_ReadAnalogInput(struct comedi_device * dev, struct comedi_subdevice * s,
struct comedi_insn * insn, unsigned int * data)
{
UINT ui_CommandRegister = 0;
/******************/
/* Set the start */
/******************/
ui_CommandRegister = 0x80000;
/******************************/
/* Write the command register */
/******************************/
outl(ui_CommandRegister, devpriv->iobase + 128 + 8);
/***************************************/
/* Read the digital value of the input */
/***************************************/
data[0] = inl(devpriv->iobase + 128 + 28);
return insn->n;
}
/*
+----------------------------------------------------------------------------+
| Function Name : int i_APCI035_Reset(struct comedi_device *dev) |
| |
+----------------------------------------------------------------------------+
| Task :Resets the registers of the card |
+----------------------------------------------------------------------------+
| Input Parameters : |
+----------------------------------------------------------------------------+
| Output Parameters : -- |
+----------------------------------------------------------------------------+
| Return Value : |
| |
+----------------------------------------------------------------------------+
*/
INT i_APCI035_Reset(struct comedi_device * dev)
{
INT i_Count = 0;
for (i_Count = 1; i_Count <= 4; i_Count++) {
i_WatchdogNbr = i_Count;
outl(0x0, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 0); //stop all timers
}
outl(0x0, devpriv->iobase + 128 + 12); //Disable the warning delay
return 0;
}
/*
+----------------------------------------------------------------------------+
| Function Name : static void v_APCI035_Interrupt |
| (int irq , void *d) |
+----------------------------------------------------------------------------+
| Task : Interrupt processing Routine |
+----------------------------------------------------------------------------+
| Input Parameters : int irq : irq number |
| void *d : void pointer |
+----------------------------------------------------------------------------+
| Output Parameters : -- |
+----------------------------------------------------------------------------+
| Return Value : TRUE : No error occur |
| : FALSE : Error occur. Return the error |
| |
+----------------------------------------------------------------------------+
*/
static void v_APCI035_Interrupt(int irq, void *d)
{
struct comedi_device *dev = d;
UINT ui_StatusRegister1 = 0;
UINT ui_StatusRegister2 = 0;
UINT ui_ReadCommand = 0;
UINT ui_ChannelNumber = 0;
UINT ui_DigitalTemperature = 0;
if (i_Temp == 1) {
i_WatchdogNbr = i_Flag;
i_Flag = i_Flag + 1;
}
/**************************************/
/* Read the interrupt status register of temperature Warning */
/**************************************/
ui_StatusRegister1 = inl(devpriv->iobase + 128 + 16);
/**************************************/
/* Read the interrupt status register for Watchdog/timer */
/**************************************/
ui_StatusRegister2 =
inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 20);
if ((((ui_StatusRegister1) & 0x8) == 0x8)) //Test if warning relay interrupt
{
/**********************************/
/* Disable the temperature warning */
/**********************************/
ui_ReadCommand = inl(devpriv->iobase + 128 + 12);
ui_ReadCommand = ui_ReadCommand & 0xFFDF0000UL;
outl(ui_ReadCommand, devpriv->iobase + 128 + 12);
/***************************/
/* Read the channel number */
/***************************/
ui_ChannelNumber = inl(devpriv->iobase + 128 + 60);
/**************************************/
/* Read the digital temperature value */
/**************************************/
ui_DigitalTemperature = inl(devpriv->iobase + 128 + 60);
send_sig(SIGIO, devpriv->tsk_Current, 0); // send signal to the sample
} //if (((ui_StatusRegister1 & 0x8) == 0x8))
else {
if ((ui_StatusRegister2 & 0x1) == 0x1) {
send_sig(SIGIO, devpriv->tsk_Current, 0); // send signal to the sample
}
} //else if (((ui_StatusRegister1 & 0x8) == 0x8))
return;
}

View file

@ -0,0 +1,123 @@
/*
* Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
*
* ADDI-DATA GmbH
* Dieselstrasse 3
* D-77833 Ottersweier
* Tel: +19(0)7223/9493-0
* Fax: +49(0)7223/9493-92
* http://www.addi-data-com
* info@addi-data.com
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*/
/* Card Specific information */
#define APCI035_BOARD_VENDOR_ID 0x15B8
#define APCI035_ADDRESS_RANGE 255
INT i_TW_Number;
struct {
INT i_Gain;
INT i_Polarity;
INT i_OffsetRange;
INT i_Coupling;
INT i_SingleDiff;
INT i_AutoCalibration;
UINT ui_ReloadValue;
UINT ui_TimeUnitReloadVal;
INT i_Interrupt;
INT i_ModuleSelection;
} Config_Parameters_Main;
/* ANALOG INPUT RANGE */
struct comedi_lrange range_apci035_ai = { 8, {
BIP_RANGE(10),
BIP_RANGE(5),
BIP_RANGE(2),
BIP_RANGE(1),
UNI_RANGE(10),
UNI_RANGE(5),
UNI_RANGE(2),
UNI_RANGE(1)
}
};
/* Timer / Watchdog Related Defines */
#define APCI035_TCW_SYNC_ENABLEDISABLE 0
#define APCI035_TCW_RELOAD_VALUE 4
#define APCI035_TCW_TIMEBASE 8
#define APCI035_TCW_PROG 12
#define APCI035_TCW_TRIG_STATUS 16
#define APCI035_TCW_IRQ 20
#define APCI035_TCW_WARN_TIMEVAL 24
#define APCI035_TCW_WARN_TIMEBASE 28
#define ADDIDATA_TIMER 0
/* #define ADDIDATA_WATCHDOG 1 */
#define APCI035_TW1 0
#define APCI035_TW2 32
#define APCI035_TW3 64
#define APCI035_TW4 96
#define APCI035_AI_OFFSET 0
#define APCI035_TEMP 128
#define APCI035_ALR_SEQ 4
#define APCI035_START_STOP_INDEX 8
#define APCI035_ALR_START_STOP 12
#define APCI035_ALR_IRQ 16
#define APCI035_EOS 20
#define APCI035_CHAN_NO 24
#define APCI035_CHAN_VAL 28
#define APCI035_CONV_TIME_TIME_BASE 36
#define APCI035_RELOAD_CONV_TIME_VAL 32
#define APCI035_DELAY_TIME_TIME_BASE 44
#define APCI035_RELOAD_DELAY_TIME_VAL 40
#define ENABLE_EXT_TRIG 1
#define ENABLE_EXT_GATE 2
#define ENABLE_EXT_TRIG_GATE 3
#define ANALOG_INPUT 0
#define TEMPERATURE 1
#define RESISTANCE 2
#define ADDIDATA_GREATER_THAN_TEST 0
#define ADDIDATA_LESS_THAN_TEST 1
#define APCI035_MAXVOLT 2.5
#define ADDIDATA_UNIPOLAR 1
#define ADDIDATA_BIPOLAR 2
/* ADDIDATA Enable Disable */
#define ADDIDATA_ENABLE 1
#define ADDIDATA_DISABLE 0
/* Hardware Layer functions for Apci035 */
/* TIMER */
/* timer value is passed as u seconds */
INT i_APCI035_ConfigTimerWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
INT i_APCI035_StartStopWriteTimerWatchdog(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
INT i_APCI035_ReadTimerWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
/* Temperature Related Defines (Analog Input Subdevice) */
INT i_APCI035_ConfigAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
INT i_APCI035_ReadAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
/* Interrupt */
static void v_APCI035_Interrupt(int irq, void *d);
/* Reset functions */
INT i_APCI035_Reset(struct comedi_device *dev);

View file

@ -0,0 +1,285 @@
/**
@verbatim
Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
ADDI-DATA GmbH
Dieselstrasse 3
D-77833 Ottersweier
Tel: +19(0)7223/9493-0
Fax: +49(0)7223/9493-92
http://www.addi-data-com
info@addi-data.com
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
You shoud also find the complete GPL in the COPYING file accompanying this source code.
@endverbatim
*/
/*
+-----------------------------------------------------------------------+
| (C) ADDI-DATA GmbH Dieselstraße 3 D-77833 Ottersweier |
+-----------------------------------------------------------------------+
| Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com |
| Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com |
+-------------------------------+---------------------------------------+
| Project : APCI-1032 | Compiler : GCC |
| Module name : hwdrv_apci1032.c| Version : 2.96 |
+-------------------------------+---------------------------------------+
| Project manager: Eric Stolz | Date : 02/12/2002 |
+-------------------------------+---------------------------------------+
| Description : Hardware Layer Acces For APCI-1032 |
+-----------------------------------------------------------------------+
| UPDATES |
+----------+-----------+------------------------------------------------+
| Date | Author | Description of updates |
+----------+-----------+------------------------------------------------+
| | | |
| | | |
| | | |
+----------+-----------+------------------------------------------------+
*/
/*
+----------------------------------------------------------------------------+
| Included files |
+----------------------------------------------------------------------------+
*/
#include "hwdrv_apci1032.h"
#include <linux/delay.h>
//Global variables
UINT ui_InterruptStatus = 0;
/*
+----------------------------------------------------------------------------+
| Function Name : int i_APCI1032_ConfigDigitalInput |
| (struct comedi_device *dev,struct comedi_subdevice *s, |
| struct comedi_insn *insn,unsigned int *data) |
+----------------------------------------------------------------------------+
| Task : Configures the digital input Subdevice |
+----------------------------------------------------------------------------+
| Input Parameters : struct comedi_device *dev : Driver handle |
| unsigned int *data : Data Pointer contains |
| configuration parameters as below |
| |
| data[0] : 1 Enable Digital Input Interrupt |
| 0 Disable Digital Input Interrupt |
| data[1] : 0 ADDIDATA Interrupt OR LOGIC |
| : 1 ADDIDATA Interrupt AND LOGIC |
| data[2] : Interrupt mask for the mode 1 |
| data[3] : Interrupt mask for the mode 2 |
| |
+----------------------------------------------------------------------------+
| Output Parameters : -- |
+----------------------------------------------------------------------------+
| Return Value : TRUE : No error occur |
| : FALSE : Error occur. Return the error |
| |
+----------------------------------------------------------------------------+
*/
INT i_APCI1032_ConfigDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
struct comedi_insn * insn, unsigned int * data)
{
UINT ui_TmpValue;
ULONG ul_Command1 = 0;
ULONG ul_Command2 = 0;
devpriv->tsk_Current = current;
/*******************************/
/* Set the digital input logic */
/*******************************/
if (data[0] == ADDIDATA_ENABLE) {
ul_Command1 = ul_Command1 | data[2];
ul_Command2 = ul_Command2 | data[3];
outl(ul_Command1,
devpriv->iobase + APCI1032_DIGITAL_IP_INTERRUPT_MODE1);
outl(ul_Command2,
devpriv->iobase + APCI1032_DIGITAL_IP_INTERRUPT_MODE2);
if (data[1] == ADDIDATA_OR) {
outl(0x4, devpriv->iobase + APCI1032_DIGITAL_IP_IRQ);
ui_TmpValue =
inl(devpriv->iobase + APCI1032_DIGITAL_IP_IRQ);
} //if (data[1] == ADDIDATA_OR)
else {
outl(0x6, devpriv->iobase + APCI1032_DIGITAL_IP_IRQ);
} //else if(data[1] == ADDIDATA_OR)
} // if( data[0] == ADDIDATA_ENABLE)
else {
ul_Command1 = ul_Command1 & 0xFFFF0000;
ul_Command2 = ul_Command2 & 0xFFFF0000;
outl(ul_Command1,
devpriv->iobase + APCI1032_DIGITAL_IP_INTERRUPT_MODE1);
outl(ul_Command2,
devpriv->iobase + APCI1032_DIGITAL_IP_INTERRUPT_MODE2);
outl(0x0, devpriv->iobase + APCI1032_DIGITAL_IP_IRQ);
} //else if ( data[0] == ADDIDATA_ENABLE)
return insn->n;
}
/*
+----------------------------------------------------------------------------+
| Function Name : int i_APCI1032_Read1DigitalInput |
| (struct comedi_device *dev,struct comedi_subdevice *s, |
| struct comedi_insn *insn,unsigned int *data) |
+----------------------------------------------------------------------------+
| Task : Return the status of the digital input |
+----------------------------------------------------------------------------+
| Input Parameters : struct comedi_device *dev : Driver handle |
| UINT ui_Channel : Channel number to read |
| unsigned int *data : Data Pointer to read status |
+----------------------------------------------------------------------------+
| Output Parameters : -- |
+----------------------------------------------------------------------------+
| Return Value : TRUE : No error occur |
| : FALSE : Error occur. Return the error |
| |
+----------------------------------------------------------------------------+
*/
INT i_APCI1032_Read1DigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
struct comedi_insn * insn, unsigned int * data)
{
UINT ui_TmpValue = 0;
UINT ui_Channel;
ui_Channel = CR_CHAN(insn->chanspec);
if (ui_Channel >= 0 && ui_Channel <= 31) {
ui_TmpValue = (UINT) inl(devpriv->iobase + APCI1032_DIGITAL_IP);
// since only 1 channel reqd to bring it to last bit it is rotated
// 8 +(chan - 1) times then ANDed with 1 for last bit.
*data = (ui_TmpValue >> ui_Channel) & 0x1;
} //if(ui_Channel >= 0 && ui_Channel <=31)
else {
//comedi_error(dev," \n chan spec wrong\n");
return -EINVAL; // "sorry channel spec wrong "
} //else if(ui_Channel >= 0 && ui_Channel <=31)
return insn->n;
}
/*
+----------------------------------------------------------------------------+
| Function Name : int i_APCI1032_ReadMoreDigitalInput |
| (struct comedi_device *dev,struct comedi_subdevice *s, |
| struct comedi_insn *insn,unsigned int *data) |
+----------------------------------------------------------------------------+
| Task : Return the status of the Requested digital inputs |
+----------------------------------------------------------------------------+
| Input Parameters : struct comedi_device *dev : Driver handle |
| UINT ui_NoOfChannels : No Of Channels To be Read |
| UINT *data : Data Pointer to read status |
+----------------------------------------------------------------------------+
| Output Parameters : -- |
+----------------------------------------------------------------------------+
| Return Value : TRUE : No error occur |
| : FALSE : Error occur. Return the error |
| |
+----------------------------------------------------------------------------+
*/
INT i_APCI1032_ReadMoreDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
struct comedi_insn * insn, unsigned int * data)
{
UINT ui_PortValue = data[0];
UINT ui_Mask = 0;
UINT ui_NoOfChannels;
ui_NoOfChannels = CR_CHAN(insn->chanspec);
if (data[1] == 0) {
*data = (UINT) inl(devpriv->iobase + APCI1032_DIGITAL_IP);
switch (ui_NoOfChannels) {
case 2:
ui_Mask = 3;
*data = (*data >> (2 * ui_PortValue)) & ui_Mask;
break;
case 4:
ui_Mask = 15;
*data = (*data >> (4 * ui_PortValue)) & ui_Mask;
break;
case 8:
ui_Mask = 255;
*data = (*data >> (8 * ui_PortValue)) & ui_Mask;
break;
case 16:
ui_Mask = 65535;
*data = (*data >> (16 * ui_PortValue)) & ui_Mask;
break;
case 31:
break;
default:
//comedi_error(dev," \nchan spec wrong\n");
return -EINVAL; // "sorry channel spec wrong "
break;
} //switch(ui_NoOfChannels)
} //if(data[1]==0)
else {
if (data[1] == 1) {
*data = ui_InterruptStatus;
} //if(data[1]==1)
} //else if(data[1]==0)
return insn->n;
}
/*
+----------------------------------------------------------------------------+
| Function Name : static void v_APCI1032_Interrupt |
| (int irq , void *d) |
+----------------------------------------------------------------------------+
| Task : Interrupt handler for the interruptible digital inputs |
+----------------------------------------------------------------------------+
| Input Parameters : int irq : irq number |
| void *d : void pointer |
+----------------------------------------------------------------------------+
| Output Parameters : -- |
+----------------------------------------------------------------------------+
| Return Value : TRUE : No error occur |
| : FALSE : Error occur. Return the error |
| |
+----------------------------------------------------------------------------+
*/
static void v_APCI1032_Interrupt(int irq, void *d)
{
struct comedi_device *dev = d;
UINT ui_Temp;
//disable the interrupt
ui_Temp = inl(devpriv->iobase + APCI1032_DIGITAL_IP_IRQ);
outl(ui_Temp & APCI1032_DIGITAL_IP_INTERRUPT_DISABLE,
devpriv->iobase + APCI1032_DIGITAL_IP_IRQ);
ui_InterruptStatus =
inl(devpriv->iobase + APCI1032_DIGITAL_IP_INTERRUPT_STATUS);
ui_InterruptStatus = ui_InterruptStatus & 0X0000FFFF;
send_sig(SIGIO, devpriv->tsk_Current, 0); // send signal to the sample
outl(ui_Temp, devpriv->iobase + APCI1032_DIGITAL_IP_IRQ); //enable the interrupt
return;
}
/*
+----------------------------------------------------------------------------+
| Function Name : int i_APCI1032_Reset(struct comedi_device *dev) | |
+----------------------------------------------------------------------------+
| Task :resets all the registers |
+----------------------------------------------------------------------------+
| Input Parameters : struct comedi_device *dev
+----------------------------------------------------------------------------+
| Output Parameters : -- |
+----------------------------------------------------------------------------+
| Return Value : |
| |
+----------------------------------------------------------------------------+
*/
INT i_APCI1032_Reset(struct comedi_device * dev)
{
outl(0x0, devpriv->iobase + APCI1032_DIGITAL_IP_IRQ); //disable the interrupts
inl(devpriv->iobase + APCI1032_DIGITAL_IP_INTERRUPT_STATUS); //Reset the interrupt status register
outl(0x0, devpriv->iobase + APCI1032_DIGITAL_IP_INTERRUPT_MODE1); //Disable the and/or interrupt
outl(0x0, devpriv->iobase + APCI1032_DIGITAL_IP_INTERRUPT_MODE2);
return 0;
}

View file

@ -0,0 +1,63 @@
/*
* Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
*
* ADDI-DATA GmbH
* Dieselstrasse 3
* D-77833 Ottersweier
* Tel: +19(0)7223/9493-0
* Fax: +49(0)7223/9493-92
* http://www.addi-data-com
* info@addi-data.com
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*/
/********* Definitions for APCI-1032 card *****/
#define APCI1032_BOARD_VENDOR_ID 0x15B8
#define APCI1032_ADDRESS_RANGE 20
//DIGITAL INPUT DEFINE
#define APCI1032_DIGITAL_IP 0
#define APCI1032_DIGITAL_IP_INTERRUPT_MODE1 4
#define APCI1032_DIGITAL_IP_INTERRUPT_MODE2 8
#define APCI1032_DIGITAL_IP_IRQ 16
//Digital Input IRQ Function Selection
#define ADDIDATA_OR 0
#define ADDIDATA_AND 1
//Digital Input Interrupt Status
#define APCI1032_DIGITAL_IP_INTERRUPT_STATUS 12
//Digital Input Interrupt Enable Disable.
#define APCI1032_DIGITAL_IP_INTERRUPT_ENABLE 0x4
#define APCI1032_DIGITAL_IP_INTERRUPT_DISABLE 0xFFFFFFFB
//ADDIDATA Enable Disable
#define ADDIDATA_ENABLE 1
#define ADDIDATA_DISABLE 0
// Hardware Layer functions for Apci1032
//DI
// for di read
INT i_APCI1032_ConfigDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
INT i_APCI1032_Read1DigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
INT i_APCI1032_ReadMoreDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
// Interrupt functions.....
static void v_APCI1032_Interrupt(int irq, void *d);
//Reset
INT i_APCI1032_Reset(struct comedi_device *dev);

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,165 @@
/*
* Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
*
* ADDI-DATA GmbH
* Dieselstrasse 3
* D-77833 Ottersweier
* Tel: +19(0)7223/9493-0
* Fax: +49(0)7223/9493-92
* http://www.addi-data-com
* info@addi-data.com
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*/
/********* Definitions for APCI-1500 card *****/
// Card Specific information
#define APCI1500_BOARD_VENDOR_ID 0x10e8
#define APCI1500_ADDRESS_RANGE 4
//DIGITAL INPUT-OUTPUT DEFINE
#define APCI1500_DIGITAL_OP 2
#define APCI1500_DIGITAL_IP 0
#define APCI1500_AND 2
#define APCI1500_OR 4
#define APCI1500_OR_PRIORITY 6
#define APCI1500_CLK_SELECT 0
#define COUNTER1 0
#define COUNTER2 1
#define COUNTER3 2
#define APCI1500_COUNTER 0x20
#define APCI1500_TIMER 0
#define APCI1500_WATCHDOG 0
#define APCI1500_SINGLE 0
#define APCI1500_CONTINUOUS 0x80
#define APCI1500_DISABLE 0
#define APCI1500_ENABLE 1
#define APCI1500_SOFTWARE_TRIGGER 0x4
#define APCI1500_HARDWARE_TRIGGER 0x10
#define APCI1500_SOFTWARE_GATE 0
#define APCI1500_HARDWARE_GATE 0x8
#define START 0
#define STOP 1
#define TRIGGER 2
/*
* Zillog I/O enumeration
*/
enum {
APCI1500_Z8536_PORT_C,
APCI1500_Z8536_PORT_B,
APCI1500_Z8536_PORT_A,
APCI1500_Z8536_CONTROL_REGISTER
};
/*
* Z8536 CIO Internal Address
*/
enum {
APCI1500_RW_MASTER_INTERRUPT_CONTROL,
APCI1500_RW_MASTER_CONFIGURATION_CONTROL,
APCI1500_RW_PORT_A_INTERRUPT_CONTROL,
APCI1500_RW_PORT_B_INTERRUPT_CONTROL,
APCI1500_RW_TIMER_COUNTER_INTERRUPT_VECTOR,
APCI1500_RW_PORT_C_DATA_PCITCH_POLARITY,
APCI1500_RW_PORT_C_DATA_DIRECTION,
APCI1500_RW_PORT_C_SPECIAL_IO_CONTROL,
APCI1500_RW_PORT_A_COMMAND_AND_STATUS,
APCI1500_RW_PORT_B_COMMAND_AND_STATUS,
APCI1500_RW_CPT_TMR1_CMD_STATUS,
APCI1500_RW_CPT_TMR2_CMD_STATUS,
APCI1500_RW_CPT_TMR3_CMD_STATUS,
APCI1500_RW_PORT_A_DATA,
APCI1500_RW_PORT_B_DATA,
APCI1500_RW_PORT_C_DATA,
APCI1500_R_CPT_TMR1_VALUE_HIGH,
APCI1500_R_CPT_TMR1_VALUE_LOW,
APCI1500_R_CPT_TMR2_VALUE_HIGH,
APCI1500_R_CPT_TMR2_VALUE_LOW,
APCI1500_R_CPT_TMR3_VALUE_HIGH,
APCI1500_R_CPT_TMR3_VALUE_LOW,
APCI1500_RW_CPT_TMR1_TIME_CST_HIGH,
APCI1500_RW_CPT_TMR1_TIME_CST_LOW,
APCI1500_RW_CPT_TMR2_TIME_CST_HIGH,
APCI1500_RW_CPT_TMR2_TIME_CST_LOW,
APCI1500_RW_CPT_TMR3_TIME_CST_HIGH,
APCI1500_RW_CPT_TMR3_TIME_CST_LOW,
APCI1500_RW_CPT_TMR1_MODE_SPECIFICATION,
APCI1500_RW_CPT_TMR2_MODE_SPECIFICATION,
APCI1500_RW_CPT_TMR3_MODE_SPECIFICATION,
APCI1500_R_CURRENT_VECTOR,
APCI1500_RW_PORT_A_SPECIFICATION,
APCI1500_RW_PORT_A_HANDSHAKE_SPECIFICATION,
APCI1500_RW_PORT_A_DATA_PCITCH_POLARITY,
APCI1500_RW_PORT_A_DATA_DIRECTION,
APCI1500_RW_PORT_A_SPECIAL_IO_CONTROL,
APCI1500_RW_PORT_A_PATTERN_POLARITY,
APCI1500_RW_PORT_A_PATTERN_TRANSITION,
APCI1500_RW_PORT_A_PATTERN_MASK,
APCI1500_RW_PORT_B_SPECIFICATION,
APCI1500_RW_PORT_B_HANDSHAKE_SPECIFICATION,
APCI1500_RW_PORT_B_DATA_PCITCH_POLARITY,
APCI1500_RW_PORT_B_DATA_DIRECTION,
APCI1500_RW_PORT_B_SPECIAL_IO_CONTROL,
APCI1500_RW_PORT_B_PATTERN_POLARITY,
APCI1500_RW_PORT_B_PATTERN_TRANSITION,
APCI1500_RW_PORT_B_PATTERN_MASK
};
/*----------DIGITAL INPUT----------------*/
static int i_APCI1500_Initialisation(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
static int i_APCI1500_ConfigDigitalInputEvent(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data);
static int i_APCI1500_StartStopInputEvent(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
static int i_APCI1500_ReadMoreDigitalInput(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
/*---------- DIGITAL OUTPUT------------*/
static int i_APCI1500_ConfigDigitalOutputErrorInterrupt(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data);
static int i_APCI1500_WriteDigitalOutput(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
/*----------TIMER----------------*/
static int i_APCI1500_ConfigCounterTimerWatchdog(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data);
static int i_APCI1500_StartStopTriggerTimerCounterWatchdog(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data);
static int i_APCI1500_ReadCounterTimerWatchdog(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data);
static int i_APCI1500_ReadInterruptMask(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
/*----------INTERRUPT HANDLER------*/
static void v_APCI1500_Interrupt(int irq, void *d);
static int i_APCI1500_ConfigureInterrupt(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
/*----------RESET---------------*/
static int i_APCI1500_Reset(struct comedi_device *dev);

View file

@ -0,0 +1,542 @@
/**
@verbatim
Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
ADDI-DATA GmbH
Dieselstrasse 3
D-77833 Ottersweier
Tel: +19(0)7223/9493-0
Fax: +49(0)7223/9493-92
http://www.addi-data-com
info@addi-data.com
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
You shoud also find the complete GPL in the COPYING file accompanying this source code.
@endverbatim
*/
/*
+-----------------------------------------------------------------------+
| (C) ADDI-DATA GmbH Dieselstraße 3 D-77833 Ottersweier |
+-----------------------------------------------------------------------+
| Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com |
| Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com |
+-------------------------------+---------------------------------------+
| Project : APCI-1516 | Compiler : GCC |
| Module name : hwdrv_apci1516.c| Version : 2.96 |
+-------------------------------+---------------------------------------+
| Project manager: Eric Stolz | Date : 02/12/2002 |
+-------------------------------+---------------------------------------+
| Description : Hardware Layer Acces For APCI-1516 |
+-----------------------------------------------------------------------+
| UPDATES |
+----------+-----------+------------------------------------------------+
| Date | Author | Description of updates |
+----------+-----------+------------------------------------------------+
| | | |
| | | |
| | | |
+----------+-----------+------------------------------------------------+
*/
/*
+----------------------------------------------------------------------------+
| Included files |
+----------------------------------------------------------------------------+
*/
#include "hwdrv_apci1516.h"
/*
+----------------------------------------------------------------------------+
| Function Name : int i_APCI1516_Read1DigitalInput |
| (struct comedi_device *dev,struct comedi_subdevice *s, |
| struct comedi_insn *insn,unsigned int *data) |
+----------------------------------------------------------------------------+
| Task : Return the status of the digital input |
+----------------------------------------------------------------------------+
| Input Parameters : struct comedi_device *dev : Driver handle |
| struct comedi_subdevice *s, :pointer to subdevice structure
struct comedi_insn *insn :pointer to insn structure |
| unsigned int *data : Data Pointer to read status |
+----------------------------------------------------------------------------+
| Output Parameters : -- |
+----------------------------------------------------------------------------+
| Return Value : TRUE : No error occur |
| : FALSE : Error occur. Return the error |
| |
+----------------------------------------------------------------------------+
*/
INT i_APCI1516_Read1DigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
struct comedi_insn * insn, unsigned int * data)
{
UINT ui_TmpValue = 0;
UINT ui_Channel;
ui_Channel = CR_CHAN(insn->chanspec);
if (ui_Channel >= 0 && ui_Channel <= 7) {
ui_TmpValue = (UINT) inw(devpriv->iobase + APCI1516_DIGITAL_IP);
// since only 1 channel reqd to bring it to last bit it is rotated
// 8 +(chan - 1) times then ANDed with 1 for last bit.
*data = (ui_TmpValue >> ui_Channel) & 0x1;
} //if(ui_Channel >= 0 && ui_Channel <=7)
else {
//comedi_error(dev," \n chan spec wrong\n");
return -EINVAL; // "sorry channel spec wrong "
} //else if(ui_Channel >= 0 && ui_Channel <=7)
return insn->n;
}
/*
+----------------------------------------------------------------------------+
| Function Name : int i_APCI1516_ReadMoreDigitalInput |
| (struct comedi_device *dev,struct comedi_subdevice *s, |
| struct comedi_insn *insn,unsigned int *data) |
+----------------------------------------------------------------------------+
| Task : Return the status of the Requested digital inputs |
+----------------------------------------------------------------------------+
| Input Parameters : struct comedi_device *dev : Driver handle |
| struct comedi_subdevice *s, :pointer to subdevice structure
struct comedi_insn *insn :pointer to insn structure |
| unsigned int *data : Data Pointer to read status |
+----------------------------------------------------------------------------+
| Output Parameters : -- |
+----------------------------------------------------------------------------+
| Return Value : TRUE : No error occur |
| : FALSE : Error occur. Return the error |
| |
+----------------------------------------------------------------------------+
*/
INT i_APCI1516_ReadMoreDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
struct comedi_insn * insn, unsigned int * data)
{
UINT ui_PortValue = data[0];
UINT ui_Mask = 0;
UINT ui_NoOfChannels;
ui_NoOfChannels = CR_CHAN(insn->chanspec);
*data = (UINT) inw(devpriv->iobase + APCI1516_DIGITAL_IP);
switch (ui_NoOfChannels) {
case 2:
ui_Mask = 3;
*data = (*data >> (2 * ui_PortValue)) & ui_Mask;
break;
case 4:
ui_Mask = 15;
*data = (*data >> (4 * ui_PortValue)) & ui_Mask;
break;
case 7:
break;
default:
printk("\nWrong parameters\n");
return -EINVAL; // "sorry channel spec wrong "
break;
} //switch(ui_NoOfChannels)
return insn->n;
}
/*
+----------------------------------------------------------------------------+
| Function Name : int i_APCI1516_ConfigDigitalOutput (struct comedi_device *dev,
struct comedi_subdevice *s struct comedi_insn *insn,unsigned int *data) |
| |
+----------------------------------------------------------------------------+
| Task : Configures The Digital Output Subdevice. |
+----------------------------------------------------------------------------+
| Input Parameters : struct comedi_device *dev : Driver handle |
| unsigned int *data : Data Pointer contains |
| configuration parameters as below |
| struct comedi_subdevice *s, :pointer to subdevice structure
struct comedi_insn *insn :pointer to insn structure |
| data[0] :1:Memory on |
| 0:Memory off |
| |
| |
+----------------------------------------------------------------------------+
| Output Parameters : -- |
+----------------------------------------------------------------------------+
| Return Value : TRUE : No error occur |
| : FALSE : Error occur. Return the error |
| |
+----------------------------------------------------------------------------+
*/
int i_APCI1516_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
struct comedi_insn * insn, unsigned int * data)
{
devpriv->b_OutputMemoryStatus = data[0];
return insn->n;
}
/*
+----------------------------------------------------------------------------+
| Function Name : int i_APCI1516_WriteDigitalOutput |
| (struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,
unsigned int *data) |
+----------------------------------------------------------------------------+
| Task : Writes port value To the selected port |
+----------------------------------------------------------------------------+
| Input Parameters : struct comedi_device *dev : Driver handle |
| struct comedi_subdevice *s, :pointer to subdevice structure
struct comedi_insn *insn :pointer to insn structure |
| unsigned int *data : Data Pointer to read status |
+----------------------------------------------------------------------------+
| Output Parameters : -- |
+----------------------------------------------------------------------------+
| Return Value : TRUE : No error occur |
| : FALSE : Error occur. Return the error |
| |
+----------------------------------------------------------------------------+
*/
INT i_APCI1516_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
struct comedi_insn * insn, unsigned int * data)
{
UINT ui_Temp, ui_Temp1;
UINT ui_NoOfChannel = CR_CHAN(insn->chanspec); // get the channel
printk("EL311003 : @=%x\n", devpriv->iobase + APCI1516_DIGITAL_OP);
if (devpriv->b_OutputMemoryStatus) {
ui_Temp = inw(devpriv->iobase + APCI1516_DIGITAL_OP);
} //if(devpriv->b_OutputMemoryStatus )
else {
ui_Temp = 0;
} //if(devpriv->b_OutputMemoryStatus )
if (data[3] == 0) {
if (data[1] == 0) {
data[0] = (data[0] << ui_NoOfChannel) | ui_Temp;
outw(data[0], devpriv->iobase + APCI1516_DIGITAL_OP);
printk("EL311003 : d=%d @=%x\n", data[0],
devpriv->iobase + APCI1516_DIGITAL_OP);
} //if(data[1]==0)
else {
if (data[1] == 1) {
switch (ui_NoOfChannel) {
case 2:
data[0] =
(data[0] << (2 *
data[2])) | ui_Temp;
break;
case 4:
data[0] =
(data[0] << (4 *
data[2])) | ui_Temp;
break;
case 7:
data[0] = data[0] | ui_Temp;
break;
default:
comedi_error(dev, " chan spec wrong");
return -EINVAL; // "sorry channel spec wrong "
} //switch(ui_NoOfChannels)
outw(data[0],
devpriv->iobase + APCI1516_DIGITAL_OP);
printk("EL311003 : d=%d @=%x\n", data[0],
devpriv->iobase + APCI1516_DIGITAL_OP);
} // if(data[1]==1)
else {
printk("\nSpecified channel not supported\n");
} //else if(data[1]==1)
} //elseif(data[1]==0)
} //if(data[3]==0)
else {
if (data[3] == 1) {
if (data[1] == 0) {
data[0] = ~data[0] & 0x1;
ui_Temp1 = 1;
ui_Temp1 = ui_Temp1 << ui_NoOfChannel;
ui_Temp = ui_Temp | ui_Temp1;
data[0] = (data[0] << ui_NoOfChannel) ^ 0xff;
data[0] = data[0] & ui_Temp;
outw(data[0],
devpriv->iobase + APCI1516_DIGITAL_OP);
printk("EL311003 : d=%d @=%x\n", data[0],
devpriv->iobase + APCI1516_DIGITAL_OP);
} //if(data[1]==0)
else {
if (data[1] == 1) {
switch (ui_NoOfChannel) {
case 2:
data[0] = ~data[0] & 0x3;
ui_Temp1 = 3;
ui_Temp1 =
ui_Temp1 << 2 * data[2];
ui_Temp = ui_Temp | ui_Temp1;
data[0] =
((data[0] << (2 *
data
[2])) ^
0xff) & ui_Temp;
break;
case 4:
data[0] = ~data[0] & 0xf;
ui_Temp1 = 15;
ui_Temp1 =
ui_Temp1 << 4 * data[2];
ui_Temp = ui_Temp | ui_Temp1;
data[0] =
((data[0] << (4 *
data
[2])) ^
0xff) & ui_Temp;
break;
case 7:
break;
default:
comedi_error(dev,
" chan spec wrong");
return -EINVAL; // "sorry channel spec wrong "
} //switch(ui_NoOfChannels)
outw(data[0],
devpriv->iobase +
APCI1516_DIGITAL_OP);
printk("EL311003 : d=%d @=%x\n",
data[0],
devpriv->iobase +
APCI1516_DIGITAL_OP);
} // if(data[1]==1)
else {
printk("\nSpecified channel not supported\n");
} //else if(data[1]==1)
} //elseif(data[1]==0)
} //if(data[3]==1);
else {
printk("\nSpecified functionality does not exist\n");
return -EINVAL;
} //if else data[3]==1)
} //if else data[3]==0)
return (insn->n);;
}
/*
+----------------------------------------------------------------------------+
| Function Name : int i_APCI1516_ReadDigitalOutput |
| (struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,
unsigned int *data) |
+----------------------------------------------------------------------------+
| Task : Read value of the selected channel or port |
+----------------------------------------------------------------------------+
| Input Parameters : struct comedi_device *dev : Driver handle |
| struct comedi_subdevice *s, :pointer to subdevice structure
struct comedi_insn *insn :pointer to insn structure |
| unsigned int *data : Data Pointer to read status |
+----------------------------------------------------------------------------+
| Output Parameters : -- |
+----------------------------------------------------------------------------+
| Return Value : TRUE : No error occur |
| : FALSE : Error occur. Return the error |
| |
+----------------------------------------------------------------------------+
*/
INT i_APCI1516_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
struct comedi_insn * insn, unsigned int * data)
{
UINT ui_Temp;
UINT ui_NoOfChannel = CR_CHAN(insn->chanspec); // get the channel
ui_Temp = data[0];
*data = inw(devpriv->iobase + APCI1516_DIGITAL_OP_RW);
if (ui_Temp == 0) {
*data = (*data >> ui_NoOfChannel) & 0x1;
} //if(ui_Temp==0)
else {
if (ui_Temp == 1) {
switch (ui_NoOfChannel) {
case 2:
*data = (*data >> (2 * data[1])) & 3;
break;
case 4:
*data = (*data >> (4 * data[1])) & 15;
break;
case 7:
break;
default:
comedi_error(dev, " chan spec wrong");
return -EINVAL; // "sorry channel spec wrong "
} //switch(ui_NoOfChannels)
} //if(ui_Temp==1)
else {
printk("\nSpecified channel not supported \n");
} //elseif(ui_Temp==1)
} //elseif(ui_Temp==0)
return insn->n;
}
/*
+----------------------------------------------------------------------------+
| Function Name : int i_APCI1516_ConfigWatchdog(struct comedi_device *dev,
struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data) |
| |
+----------------------------------------------------------------------------+
| Task : Configures The Watchdog |
+----------------------------------------------------------------------------+
| Input Parameters : struct comedi_device *dev : Driver handle |
| struct comedi_subdevice *s, :pointer to subdevice structure
struct comedi_insn *insn :pointer to insn structure |
| unsigned int *data : Data Pointer to read status |
+----------------------------------------------------------------------------+
| Output Parameters : -- |
+----------------------------------------------------------------------------+
| Return Value : TRUE : No error occur |
| : FALSE : Error occur. Return the error |
| |
+----------------------------------------------------------------------------+
*/
int i_APCI1516_ConfigWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
struct comedi_insn * insn, unsigned int * data)
{
if (data[0] == 0) {
//Disable the watchdog
outw(0x0,
devpriv->i_IobaseAddon +
APCI1516_WATCHDOG_ENABLEDISABLE);
//Loading the Reload value
outw(data[1],
devpriv->i_IobaseAddon +
APCI1516_WATCHDOG_RELOAD_VALUE);
data[1] = data[1] >> 16;
outw(data[1],
devpriv->i_IobaseAddon +
APCI1516_WATCHDOG_RELOAD_VALUE + 2);
} //if(data[0]==0)
else {
printk("\nThe input parameters are wrong\n");
return -EINVAL;
} //elseif(data[0]==0)
return insn->n;
}
/*
+----------------------------------------------------------------------------+
| Function Name : int i_APCI1516_StartStopWriteWatchdog |
| (struct comedi_device *dev,struct comedi_subdevice *s,
struct comedi_insn *insn,unsigned int *data); |
+----------------------------------------------------------------------------+
| Task : Start / Stop The Watchdog |
+----------------------------------------------------------------------------+
| Input Parameters : struct comedi_device *dev : Driver handle |
| struct comedi_subdevice *s, :pointer to subdevice structure
struct comedi_insn *insn :pointer to insn structure |
| unsigned int *data : Data Pointer to read status |
+----------------------------------------------------------------------------+
| Output Parameters : -- |
+----------------------------------------------------------------------------+
| Return Value : TRUE : No error occur |
| : FALSE : Error occur. Return the error |
| |
+----------------------------------------------------------------------------+
*/
int i_APCI1516_StartStopWriteWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
struct comedi_insn * insn, unsigned int * data)
{
switch (data[0]) {
case 0: //stop the watchdog
outw(0x0, devpriv->i_IobaseAddon + APCI1516_WATCHDOG_ENABLEDISABLE); //disable the watchdog
break;
case 1: //start the watchdog
outw(0x0001,
devpriv->i_IobaseAddon +
APCI1516_WATCHDOG_ENABLEDISABLE);
break;
case 2: //Software trigger
outw(0x0201,
devpriv->i_IobaseAddon +
APCI1516_WATCHDOG_ENABLEDISABLE);
break;
default:
printk("\nSpecified functionality does not exist\n");
return -EINVAL;
} // switch(data[0])
return insn->n;
}
/*
+----------------------------------------------------------------------------+
| Function Name : int i_APCI1516_ReadWatchdog |
| (struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,
unsigned int *data); |
+----------------------------------------------------------------------------+
| Task : Read The Watchdog |
+----------------------------------------------------------------------------+
| Input Parameters : struct comedi_device *dev : Driver handle |
| struct comedi_subdevice *s, :pointer to subdevice structure
struct comedi_insn *insn :pointer to insn structure |
| unsigned int *data : Data Pointer to read status |
+----------------------------------------------------------------------------+
| Output Parameters : -- |
+----------------------------------------------------------------------------+
| Return Value : TRUE : No error occur |
| : FALSE : Error occur. Return the error |
| |
+----------------------------------------------------------------------------+
*/
int i_APCI1516_ReadWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
struct comedi_insn * insn, unsigned int * data)
{
data[0] = inw(devpriv->i_IobaseAddon + APCI1516_WATCHDOG_STATUS) & 0x1;
return insn->n;
}
/*
+----------------------------------------------------------------------------+
| Function Name : int i_APCI1516_Reset(struct comedi_device *dev) | |
+----------------------------------------------------------------------------+
| Task :resets all the registers |
+----------------------------------------------------------------------------+
| Input Parameters : struct comedi_device *dev
+----------------------------------------------------------------------------+
| Output Parameters : -- |
+----------------------------------------------------------------------------+
| Return Value : |
| |
+----------------------------------------------------------------------------+
*/
INT i_APCI1516_Reset(struct comedi_device * dev)
{
outw(0x0, devpriv->iobase + APCI1516_DIGITAL_OP); //RESETS THE DIGITAL OUTPUTS
outw(0x0, devpriv->i_IobaseAddon + APCI1516_WATCHDOG_ENABLEDISABLE);
outw(0x0, devpriv->i_IobaseAddon + APCI1516_WATCHDOG_RELOAD_VALUE);
outw(0x0, devpriv->i_IobaseAddon + APCI1516_WATCHDOG_RELOAD_VALUE + 2);
return 0;
}

View file

@ -0,0 +1,64 @@
/*
* Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
*
* ADDI-DATA GmbH
* Dieselstrasse 3
* D-77833 Ottersweier
* Tel: +19(0)7223/9493-0
* Fax: +49(0)7223/9493-92
* http://www.addi-data-com
* info@addi-data.com
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*/
/********* Definitions for APCI-1516 card *****/
// Card Specific information
#define APCI1516_BOARD_VENDOR_ID 0x15B8
#define APCI1516_ADDRESS_RANGE 8
//DIGITAL INPUT-OUTPUT DEFINE
#define APCI1516_DIGITAL_OP 4
#define APCI1516_DIGITAL_OP_RW 4
#define APCI1516_DIGITAL_IP 0
// TIMER COUNTER WATCHDOG DEFINES
#define ADDIDATA_WATCHDOG 2
#define APCI1516_DIGITAL_OP_WATCHDOG 0
#define APCI1516_WATCHDOG_ENABLEDISABLE 12
#define APCI1516_WATCHDOG_RELOAD_VALUE 4
#define APCI1516_WATCHDOG_STATUS 16
// Hardware Layer functions for Apci1516
//Digital Input
INT i_APCI1516_ReadMoreDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
INT i_APCI1516_Read1DigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
//Digital Output
int i_APCI1516_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
INT i_APCI1516_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
INT i_APCI1516_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
// TIMER
// timer value is passed as u seconds
int i_APCI1516_ConfigWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
int i_APCI1516_StartStopWriteWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
int i_APCI1516_ReadWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
//reset
INT i_APCI1516_Reset(struct comedi_device *dev);

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,119 @@
/*
* Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
*
* ADDI-DATA GmbH
* Dieselstrasse 3
* D-77833 Ottersweier
* Tel: +19(0)7223/9493-0
* Fax: +49(0)7223/9493-92
* http://www.addi-data-com
* info@addi-data.com
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*/
/********* Definitions for APCI-1564 card *****/
#define APCI1564_BOARD_VENDOR_ID 0x15B8
#define APCI1564_ADDRESS_RANGE 128
//DIGITAL INPUT-OUTPUT DEFINE
// Input defines
#define APCI1564_DIGITAL_IP 0x04
#define APCI1564_DIGITAL_IP_INTERRUPT_MODE1 4
#define APCI1564_DIGITAL_IP_INTERRUPT_MODE2 8
#define APCI1564_DIGITAL_IP_IRQ 16
// Output defines
#define APCI1564_DIGITAL_OP 0x18
#define APCI1564_DIGITAL_OP_RW 0
#define APCI1564_DIGITAL_OP_INTERRUPT 4
#define APCI1564_DIGITAL_OP_IRQ 12
//Digital Input IRQ Function Selection
#define ADDIDATA_OR 0
#define ADDIDATA_AND 1
//Digital Input Interrupt Status
#define APCI1564_DIGITAL_IP_INTERRUPT_STATUS 12
//Digital Output Interrupt Status
#define APCI1564_DIGITAL_OP_INTERRUPT_STATUS 8
//Digital Input Interrupt Enable Disable.
#define APCI1564_DIGITAL_IP_INTERRUPT_ENABLE 0x4
#define APCI1564_DIGITAL_IP_INTERRUPT_DISABLE 0xFFFFFFFB
//Digital Output Interrupt Enable Disable.
#define APCI1564_DIGITAL_OP_VCC_INTERRUPT_ENABLE 0x1
#define APCI1564_DIGITAL_OP_VCC_INTERRUPT_DISABLE 0xFFFFFFFE
#define APCI1564_DIGITAL_OP_CC_INTERRUPT_ENABLE 0x2
#define APCI1564_DIGITAL_OP_CC_INTERRUPT_DISABLE 0xFFFFFFFD
//ADDIDATA Enable Disable
#define ADDIDATA_ENABLE 1
#define ADDIDATA_DISABLE 0
// TIMER COUNTER WATCHDOG DEFINES
#define ADDIDATA_TIMER 0
#define ADDIDATA_COUNTER 1
#define ADDIDATA_WATCHDOG 2
#define APCI1564_DIGITAL_OP_WATCHDOG 0x28
#define APCI1564_TIMER 0x48
#define APCI1564_COUNTER1 0x0
#define APCI1564_COUNTER2 0x20
#define APCI1564_COUNTER3 0x40
#define APCI1564_COUNTER4 0x60
#define APCI1564_TCW_SYNC_ENABLEDISABLE 0
#define APCI1564_TCW_RELOAD_VALUE 4
#define APCI1564_TCW_TIMEBASE 8
#define APCI1564_TCW_PROG 12
#define APCI1564_TCW_TRIG_STATUS 16
#define APCI1564_TCW_IRQ 20
#define APCI1564_TCW_WARN_TIMEVAL 24
#define APCI1564_TCW_WARN_TIMEBASE 28
// Hardware Layer functions for Apci1564
//DI
// for di read
INT i_APCI1564_ConfigDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
INT i_APCI1564_Read1DigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
INT i_APCI1564_ReadMoreDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
//DO
int i_APCI1564_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
INT i_APCI1564_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
INT i_APCI1564_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
int i_APCI1564_ReadInterruptStatus(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
// TIMER
// timer value is passed as u seconds
INT i_APCI1564_ConfigTimerCounterWatchdog(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
int i_APCI1564_StartStopWriteTimerCounterWatchdog(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data);
int i_APCI1564_ReadTimerCounterWatchdog(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
// INTERRUPT
static void v_APCI1564_Interrupt(int irq, void *d);
// RESET
INT i_APCI1564_Reset(struct comedi_device *dev);

View file

@ -0,0 +1,780 @@
/**
@verbatim
Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
ADDI-DATA GmbH
Dieselstrasse 3
D-77833 Ottersweier
Tel: +19(0)7223/9493-0
Fax: +49(0)7223/9493-92
http://www.addi-data-com
info@addi-data.com
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
You shoud also find the complete GPL in the COPYING file accompanying this source code.
@endverbatim
*/
/*
+-----------------------------------------------------------------------+
| (C) ADDI-DATA GmbH Dieselstraße 3 D-77833 Ottersweier |
+-----------------------------------------------------------------------+
| Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com |
| Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com |
+-----------------------------------------------------------------------+
| Project : API APCI1648 | Compiler : gcc |
| Module name : TTL.C | Version : 2.96 |
+-------------------------------+---------------------------------------+
| Project manager: S. Weber | Date : 25/05/2005 |
+-----------------------------------------------------------------------+
| Description : APCI-16XX TTL I/O module |
| |
| |
+-----------------------------------------------------------------------+
| UPDATES |
+-----------------------------------------------------------------------+
| Date | Author | Description of updates |
+----------+-----------+------------------------------------------------+
|25.05.2005| S.Weber | Creation |
| | | |
+-----------------------------------------------------------------------+
*/
/*
+----------------------------------------------------------------------------+
| Included files |
+----------------------------------------------------------------------------+
*/
#include "hwdrv_apci16xx.h"
/*
+----------------------------------------------------------------------------+
| Function Name : INT i_APCI16XX_InsnConfigInitTTLIO |
| (struct comedi_device *dev, |
| struct comedi_subdevice *s, |
| struct comedi_insn *insn, |
| unsigned int *data) |
+----------------------------------------------------------------------------+
| Task APCI16XX_TTL_INIT (using defaults) : |
| Configure the TTL I/O operating mode from all ports |
| You must calling this function be |
| for you call any other function witch access of TTL. |
| APCI16XX_TTL_INITDIRECTION(user inputs for direction) |
+----------------------------------------------------------------------------+
| Input Parameters : b_InitType = (BYTE) data[0]; |
| b_Port0Mode = (BYTE) data[1]; |
| b_Port1Mode = (BYTE) data[2]; |
| b_Port2Mode = (BYTE) data[3]; |
| b_Port3Mode = (BYTE) data[4]; |
| ........ |
+----------------------------------------------------------------------------+
| Output Parameters : - |
+----------------------------------------------------------------------------+
| Return Value :>0: No error |
| -1: Port 0 mode selection is wrong |
| -2: Port 1 mode selection is wrong |
| -3: Port 2 mode selection is wrong |
| -4: Port 3 mode selection is wrong |
| -X: Port X-1 mode selection is wrong |
| .... |
| -100 : Config command error |
| -101 : Data size error |
+----------------------------------------------------------------------------+
*/
int i_APCI16XX_InsnConfigInitTTLIO(struct comedi_device * dev,
struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
{
INT i_ReturnValue = insn->n;
BYTE b_Command = 0;
BYTE b_Cpt = 0;
BYTE b_NumberOfPort =
(BYTE) (devpriv->ps_BoardInfo->i_NbrTTLChannel / 8);
/************************/
/* Test the buffer size */
/************************/
if (insn->n >= 1) {
/*******************/
/* Get the command */
/* **************** */
b_Command = (BYTE) data[0];
/********************/
/* Test the command */
/********************/
if ((b_Command == APCI16XX_TTL_INIT) ||
(b_Command == APCI16XX_TTL_INITDIRECTION) ||
(b_Command == APCI16XX_TTL_OUTPUTMEMORY)) {
/***************************************/
/* Test the initialisation buffer size */
/***************************************/
if ((b_Command == APCI16XX_TTL_INITDIRECTION)
&& ((BYTE) (insn->n - 1) != b_NumberOfPort)) {
/*******************/
/* Data size error */
/*******************/
printk("\nBuffer size error");
i_ReturnValue = -101;
}
if ((b_Command == APCI16XX_TTL_OUTPUTMEMORY)
&& ((BYTE) (insn->n) != 2)) {
/*******************/
/* Data size error */
/*******************/
printk("\nBuffer size error");
i_ReturnValue = -101;
}
} else {
/************************/
/* Config command error */
/************************/
printk("\nCommand selection error");
i_ReturnValue = -100;
}
} else {
/*******************/
/* Data size error */
/*******************/
printk("\nBuffer size error");
i_ReturnValue = -101;
}
/**************************************************************************/
/* Test if no error occur and APCI16XX_TTL_INITDIRECTION command selected */
/**************************************************************************/
if ((i_ReturnValue >= 0) && (b_Command == APCI16XX_TTL_INITDIRECTION)) {
memset(devpriv->ul_TTLPortConfiguration, 0,
sizeof(devpriv->ul_TTLPortConfiguration));
/*************************************/
/* Test the port direction selection */
/*************************************/
for (b_Cpt = 1;
(b_Cpt <= b_NumberOfPort) && (i_ReturnValue >= 0);
b_Cpt++) {
/**********************/
/* Test the direction */
/**********************/
if ((data[b_Cpt] != 0) && (data[b_Cpt] != 0xFF)) {
/************************/
/* Port direction error */
/************************/
printk("\nPort %d direction selection error",
(INT) b_Cpt);
i_ReturnValue = -(INT) b_Cpt;
}
/**************************/
/* Save the configuration */
/**************************/
devpriv->ul_TTLPortConfiguration[(b_Cpt - 1) / 4] =
devpriv->ul_TTLPortConfiguration[(b_Cpt -
1) / 4] | (data[b_Cpt] << (8 * ((b_Cpt -
1) % 4)));
}
}
/**************************/
/* Test if no error occur */
/**************************/
if (i_ReturnValue >= 0) {
/***********************************/
/* Test if TTL port initilaisation */
/***********************************/
if ((b_Command == APCI16XX_TTL_INIT)
|| (b_Command == APCI16XX_TTL_INITDIRECTION)) {
/******************************/
/* Set all port configuration */
/******************************/
for (b_Cpt = 0; b_Cpt <= b_NumberOfPort; b_Cpt++) {
if ((b_Cpt % 4) == 0) {
/*************************/
/* Set the configuration */
/*************************/
outl(devpriv->
ul_TTLPortConfiguration[b_Cpt /
4],
devpriv->iobase + 32 + b_Cpt);
}
}
}
}
/************************************************/
/* Test if output memory initialisation command */
/************************************************/
if (b_Command == APCI16XX_TTL_OUTPUTMEMORY) {
if (data[1]) {
devpriv->b_OutputMemoryStatus = ADDIDATA_ENABLE;
} else {
devpriv->b_OutputMemoryStatus = ADDIDATA_DISABLE;
}
}
return (i_ReturnValue);
}
/*
+----------------------------------------------------------------------------+
| INPUT FUNCTIONS |
+----------------------------------------------------------------------------+
*/
/*
+----------------------------------------------------------------------------+
| Function Name : INT i_APCI16XX_InsnBitsReadTTLIO |
| (struct comedi_device *dev, |
| struct comedi_subdevice *s, |
| struct comedi_insn *insn, |
| unsigned int *data) |
+----------------------------------------------------------------------------+
| Task : Read the status from selected TTL digital input |
| (b_InputChannel) |
+----------------------------------------------------------------------------+
| Task : Read the status from digital input port |
| (b_SelectedPort) |
+----------------------------------------------------------------------------+
| Input Parameters : |
| APCI16XX_TTL_READCHANNEL |
| b_SelectedPort= CR_RANGE(insn->chanspec); |
| b_InputChannel= CR_CHAN(insn->chanspec); |
| b_ReadType = (BYTE) data[0]; |
| |
| APCI16XX_TTL_READPORT |
| b_SelectedPort= CR_RANGE(insn->chanspec); |
| b_ReadType = (BYTE) data[0]; |
+----------------------------------------------------------------------------+
| Output Parameters : data[0] 0 : Channle is not active |
| 1 : Channle is active |
+----------------------------------------------------------------------------+
| Return Value : >0 : No error |
| -100 : Config command error |
| -101 : Data size error |
| -102 : The selected TTL input port is wrong |
| -103 : The selected TTL digital input is wrong |
+----------------------------------------------------------------------------+
*/
int i_APCI16XX_InsnBitsReadTTLIO(struct comedi_device * dev,
struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
{
INT i_ReturnValue = insn->n;
BYTE b_Command = 0;
BYTE b_NumberOfPort =
(BYTE) (devpriv->ps_BoardInfo->i_NbrTTLChannel / 8);
BYTE b_SelectedPort = CR_RANGE(insn->chanspec);
BYTE b_InputChannel = CR_CHAN(insn->chanspec);
BYTE *pb_Status;
DWORD dw_Status;
/************************/
/* Test the buffer size */
/************************/
if (insn->n >= 1) {
/*******************/
/* Get the command */
/* **************** */
b_Command = (BYTE) data[0];
/********************/
/* Test the command */
/********************/
if ((b_Command == APCI16XX_TTL_READCHANNEL)
|| (b_Command == APCI16XX_TTL_READPORT)) {
/**************************/
/* Test the selected port */
/**************************/
if (b_SelectedPort < b_NumberOfPort) {
/**********************/
/* Test if input port */
/**********************/
if (((devpriv->ul_TTLPortConfiguration
[b_SelectedPort /
4] >> (8 *
(b_SelectedPort
%
4))) &
0xFF) == 0) {
/***************************/
/* Test the channel number */
/***************************/
if ((b_Command ==
APCI16XX_TTL_READCHANNEL)
&& (b_InputChannel > 7)) {
/*******************************************/
/* The selected TTL digital input is wrong */
/*******************************************/
printk("\nChannel selection error");
i_ReturnValue = -103;
}
} else {
/****************************************/
/* The selected TTL input port is wrong */
/****************************************/
printk("\nPort selection error");
i_ReturnValue = -102;
}
} else {
/****************************************/
/* The selected TTL input port is wrong */
/****************************************/
printk("\nPort selection error");
i_ReturnValue = -102;
}
} else {
/************************/
/* Config command error */
/************************/
printk("\nCommand selection error");
i_ReturnValue = -100;
}
} else {
/*******************/
/* Data size error */
/*******************/
printk("\nBuffer size error");
i_ReturnValue = -101;
}
/**************************/
/* Test if no error occur */
/**************************/
if (i_ReturnValue >= 0) {
pb_Status = (PBYTE) & data[0];
/*******************************/
/* Get the digital inpu status */
/*******************************/
dw_Status =
inl(devpriv->iobase + 8 + ((b_SelectedPort / 4) * 4));
dw_Status = (dw_Status >> (8 * (b_SelectedPort % 4))) & 0xFF;
/***********************/
/* Save the port value */
/***********************/
*pb_Status = (BYTE) dw_Status;
/***************************************/
/* Test if read channel status command */
/***************************************/
if (b_Command == APCI16XX_TTL_READCHANNEL) {
*pb_Status = (*pb_Status >> b_InputChannel) & 1;
}
}
return (i_ReturnValue);
}
/*
+----------------------------------------------------------------------------+
| Function Name : INT i_APCI16XX_InsnReadTTLIOAllPortValue |
| (struct comedi_device *dev, |
| struct comedi_subdevice *s, |
| struct comedi_insn *insn, |
| unsigned int *data) |
+----------------------------------------------------------------------------+
| Task : Read the status from all digital input ports |
+----------------------------------------------------------------------------+
| Input Parameters : - |
+----------------------------------------------------------------------------+
| Output Parameters : data[0] : Port 0 to 3 data |
| data[1] : Port 4 to 7 data |
| .... |
+----------------------------------------------------------------------------+
| Return Value : 0: No error |
| -100 : Read command error |
| -101 : Data size error |
+----------------------------------------------------------------------------+
*/
int i_APCI16XX_InsnReadTTLIOAllPortValue(struct comedi_device * dev,
struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
{
BYTE b_Command = (BYTE) CR_AREF(insn->chanspec);
INT i_ReturnValue = insn->n;
BYTE b_Cpt = 0;
BYTE b_NumberOfPort = 0;
unsigned int *pls_ReadData = data;
/********************/
/* Test the command */
/********************/
if ((b_Command == APCI16XX_TTL_READ_ALL_INPUTS)
|| (b_Command == APCI16XX_TTL_READ_ALL_OUTPUTS)) {
/**********************************/
/* Get the number of 32-Bit ports */
/**********************************/
b_NumberOfPort =
(BYTE) (devpriv->ps_BoardInfo->i_NbrTTLChannel / 32);
if ((b_NumberOfPort * 32) <
devpriv->ps_BoardInfo->i_NbrTTLChannel) {
b_NumberOfPort = b_NumberOfPort + 1;
}
/************************/
/* Test the buffer size */
/************************/
if (insn->n >= b_NumberOfPort) {
if (b_Command == APCI16XX_TTL_READ_ALL_INPUTS) {
/**************************/
/* Read all digital input */
/**************************/
for (b_Cpt = 0; b_Cpt < b_NumberOfPort; b_Cpt++) {
/************************/
/* Read the 32-Bit port */
/************************/
pls_ReadData[b_Cpt] =
inl(devpriv->iobase + 8 +
(b_Cpt * 4));
/**************************************/
/* Mask all channels used als outputs */
/**************************************/
pls_ReadData[b_Cpt] =
pls_ReadData[b_Cpt] &
(~devpriv->
ul_TTLPortConfiguration[b_Cpt]);
}
} else {
/****************************/
/* Read all digital outputs */
/****************************/
for (b_Cpt = 0; b_Cpt < b_NumberOfPort; b_Cpt++) {
/************************/
/* Read the 32-Bit port */
/************************/
pls_ReadData[b_Cpt] =
inl(devpriv->iobase + 20 +
(b_Cpt * 4));
/**************************************/
/* Mask all channels used als outputs */
/**************************************/
pls_ReadData[b_Cpt] =
pls_ReadData[b_Cpt] & devpriv->
ul_TTLPortConfiguration[b_Cpt];
}
}
} else {
/*******************/
/* Data size error */
/*******************/
printk("\nBuffer size error");
i_ReturnValue = -101;
}
} else {
/*****************/
/* Command error */
/*****************/
printk("\nCommand selection error");
i_ReturnValue = -100;
}
return (i_ReturnValue);
}
/*
+----------------------------------------------------------------------------+
| OUTPUT FUNCTIONS |
+----------------------------------------------------------------------------+
*/
/*
+----------------------------------------------------------------------------+
| Function Name : INT i_APCI16XX_InsnBitsWriteTTLIO |
| (struct comedi_device *dev, |
| struct comedi_subdevice *s, |
| struct comedi_insn *insn, |
| unsigned int *data) |
+----------------------------------------------------------------------------+
| Task : Set the state from selected TTL digital output |
| (b_OutputChannel) |
+----------------------------------------------------------------------------+
| Task : Set the state from digital output port |
| (b_SelectedPort) |
+----------------------------------------------------------------------------+
| Input Parameters : |
| APCI16XX_TTL_WRITECHANNEL_ON | APCI16XX_TTL_WRITECHANNEL_OFF |
| b_SelectedPort = CR_RANGE(insn->chanspec); |
| b_OutputChannel= CR_CHAN(insn->chanspec); |
| b_Command = (BYTE) data[0]; |
| |
| APCI16XX_TTL_WRITEPORT_ON | APCI16XX_TTL_WRITEPORT_OFF |
| b_SelectedPort = CR_RANGE(insn->chanspec); |
| b_Command = (BYTE) data[0]; |
+----------------------------------------------------------------------------+
| Output Parameters : data[0] : TTL output port 0 to 3 data |
| data[1] : TTL output port 4 to 7 data |
| .... |
+----------------------------------------------------------------------------+
| Return Value : >0 : No error |
| -100 : Command error |
| -101 : Data size error |
| -102 : The selected TTL output port is wrong |
| -103 : The selected TTL digital output is wrong |
| -104 : Output memory disabled |
+----------------------------------------------------------------------------+
*/
int i_APCI16XX_InsnBitsWriteTTLIO(struct comedi_device * dev,
struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
{
INT i_ReturnValue = insn->n;
BYTE b_Command = 0;
BYTE b_NumberOfPort =
(BYTE) (devpriv->ps_BoardInfo->i_NbrTTLChannel / 8);
BYTE b_SelectedPort = CR_RANGE(insn->chanspec);
BYTE b_OutputChannel = CR_CHAN(insn->chanspec);
DWORD dw_Status = 0;
/************************/
/* Test the buffer size */
/************************/
if (insn->n >= 1) {
/*******************/
/* Get the command */
/* **************** */
b_Command = (BYTE) data[0];
/********************/
/* Test the command */
/********************/
if ((b_Command == APCI16XX_TTL_WRITECHANNEL_ON) ||
(b_Command == APCI16XX_TTL_WRITEPORT_ON) ||
(b_Command == APCI16XX_TTL_WRITECHANNEL_OFF) ||
(b_Command == APCI16XX_TTL_WRITEPORT_OFF)) {
/**************************/
/* Test the selected port */
/**************************/
if (b_SelectedPort < b_NumberOfPort) {
/***********************/
/* Test if output port */
/***********************/
if (((devpriv->ul_TTLPortConfiguration
[b_SelectedPort /
4] >> (8 *
(b_SelectedPort
%
4))) &
0xFF) == 0xFF) {
/***************************/
/* Test the channel number */
/***************************/
if (((b_Command == APCI16XX_TTL_WRITECHANNEL_ON) || (b_Command == APCI16XX_TTL_WRITECHANNEL_OFF)) && (b_OutputChannel > 7)) {
/********************************************/
/* The selected TTL digital output is wrong */
/********************************************/
printk("\nChannel selection error");
i_ReturnValue = -103;
}
if (((b_Command == APCI16XX_TTL_WRITECHANNEL_OFF) || (b_Command == APCI16XX_TTL_WRITEPORT_OFF)) && (devpriv->b_OutputMemoryStatus == ADDIDATA_DISABLE)) {
/********************************************/
/* The selected TTL digital output is wrong */
/********************************************/
printk("\nOutput memory disabled");
i_ReturnValue = -104;
}
/************************/
/* Test the buffer size */
/************************/
if (((b_Command == APCI16XX_TTL_WRITEPORT_ON) || (b_Command == APCI16XX_TTL_WRITEPORT_OFF)) && (insn->n < 2)) {
/*******************/
/* Data size error */
/*******************/
printk("\nBuffer size error");
i_ReturnValue = -101;
}
} else {
/*****************************************/
/* The selected TTL output port is wrong */
/*****************************************/
printk("\nPort selection error %lX",
(unsigned long)devpriv->
ul_TTLPortConfiguration[0]);
i_ReturnValue = -102;
}
} else {
/****************************************/
/* The selected TTL output port is wrong */
/****************************************/
printk("\nPort selection error %d %d",
b_SelectedPort, b_NumberOfPort);
i_ReturnValue = -102;
}
} else {
/************************/
/* Config command error */
/************************/
printk("\nCommand selection error");
i_ReturnValue = -100;
}
} else {
/*******************/
/* Data size error */
/*******************/
printk("\nBuffer size error");
i_ReturnValue = -101;
}
/**************************/
/* Test if no error occur */
/**************************/
if (i_ReturnValue >= 0) {
/********************************/
/* Get the digital output state */
/********************************/
dw_Status =
inl(devpriv->iobase + 20 + ((b_SelectedPort / 4) * 4));
/**********************************/
/* Test if output memory not used */
/**********************************/
if (devpriv->b_OutputMemoryStatus == ADDIDATA_DISABLE) {
/*********************************/
/* Clear the selected port value */
/*********************************/
dw_Status =
dw_Status & (0xFFFFFFFFUL -
(0xFFUL << (8 * (b_SelectedPort % 4))));
}
/******************************/
/* Test if setting channel ON */
/******************************/
if (b_Command == APCI16XX_TTL_WRITECHANNEL_ON) {
dw_Status =
dw_Status | (1UL << ((8 * (b_SelectedPort %
4)) + b_OutputChannel));
}
/***************************/
/* Test if setting port ON */
/***************************/
if (b_Command == APCI16XX_TTL_WRITEPORT_ON) {
dw_Status =
dw_Status | ((data[1] & 0xFF) << (8 *
(b_SelectedPort % 4)));
}
/*******************************/
/* Test if setting channel OFF */
/*******************************/
if (b_Command == APCI16XX_TTL_WRITECHANNEL_OFF) {
dw_Status =
dw_Status & (0xFFFFFFFFUL -
(1UL << ((8 * (b_SelectedPort % 4)) +
b_OutputChannel)));
}
/****************************/
/* Test if setting port OFF */
/****************************/
if (b_Command == APCI16XX_TTL_WRITEPORT_OFF) {
dw_Status =
dw_Status & (0xFFFFFFFFUL -
((data[1] & 0xFF) << (8 * (b_SelectedPort %
4))));
}
outl(dw_Status,
devpriv->iobase + 20 + ((b_SelectedPort / 4) * 4));
}
return (i_ReturnValue);
}
/*
+----------------------------------------------------------------------------+
| Function Name : int i_APCI2200_Reset(struct comedi_device *dev) | +----------------------------------------------------------------------------+
| Task :resets all the registers |
+----------------------------------------------------------------------------+
| Input Parameters : struct comedi_device *dev |
+----------------------------------------------------------------------------+
| Output Parameters : - |
+----------------------------------------------------------------------------+
| Return Value : - |
+----------------------------------------------------------------------------+
*/
int i_APCI16XX_Reset(struct comedi_device * dev)
{
return 0;
}

View file

@ -0,0 +1,94 @@
/*
* Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
*
* ADDI-DATA GmbH
* Dieselstrasse 3
* D-77833 Ottersweier
* Tel: +19(0)7223/9493-0
* Fax: +49(0)7223/9493-92
* http://www.addi-data-com
* info@addi-data.com
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*/
#ifndef COMEDI_SUBD_TTLIO
#define COMEDI_SUBD_TTLIO 11 /* Digital Input Output But TTL */
#endif
#ifndef ADDIDATA_ENABLE
#define ADDIDATA_ENABLE 1
#define ADDIDATA_DISABLE 0
#endif
#define APCI16XX_TTL_INIT 0
#define APCI16XX_TTL_INITDIRECTION 1
#define APCI16XX_TTL_OUTPUTMEMORY 2
#define APCI16XX_TTL_READCHANNEL 0
#define APCI16XX_TTL_READPORT 1
#define APCI16XX_TTL_WRITECHANNEL_ON 0
#define APCI16XX_TTL_WRITECHANNEL_OFF 1
#define APCI16XX_TTL_WRITEPORT_ON 2
#define APCI16XX_TTL_WRITEPORT_OFF 3
#define APCI16XX_TTL_READ_ALL_INPUTS 0
#define APCI16XX_TTL_READ_ALL_OUTPUTS 1
#ifdef __KERNEL__
static const struct comedi_lrange range_apci16xx_ttl = { 12,
{BIP_RANGE(1),
BIP_RANGE(1),
BIP_RANGE(1),
BIP_RANGE(1),
BIP_RANGE(1),
BIP_RANGE(1),
BIP_RANGE(1),
BIP_RANGE(1),
BIP_RANGE(1),
BIP_RANGE(1),
BIP_RANGE(1),
BIP_RANGE(1)}
};
/*
+----------------------------------------------------------------------------+
| TTL INISIALISATION FUNCTION |
+----------------------------------------------------------------------------+
*/
int i_APCI16XX_InsnConfigInitTTLIO(struct comedi_device *dev,
struct comedi_subdevice *s, struct comedi_insn *insn,
unsigned int *data);
/*
+----------------------------------------------------------------------------+
| TTL INPUT FUNCTION |
+----------------------------------------------------------------------------+
*/
int i_APCI16XX_InsnBitsReadTTLIO(struct comedi_device *dev,
struct comedi_subdevice *s, struct comedi_insn *insn,
unsigned int *data);
int i_APCI16XX_InsnReadTTLIOAllPortValue(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
/*
+----------------------------------------------------------------------------+
| TTL OUTPUT FUNCTIONS |
+----------------------------------------------------------------------------+
*/
int i_APCI16XX_InsnBitsWriteTTLIO(struct comedi_device *dev,
struct comedi_subdevice *s, struct comedi_insn *insn,
unsigned int *data);
int i_APCI16XX_Reset(struct comedi_device *dev);
#endif

View file

@ -0,0 +1,460 @@
/**
@verbatim
Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
ADDI-DATA GmbH
Dieselstrasse 3
D-77833 Ottersweier
Tel: +19(0)7223/9493-0
Fax: +49(0)7223/9493-92
http://www.addi-data-com
info@addi-data.com
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
You shoud also find the complete GPL in the COPYING file accompanying this source code.
@endverbatim
*/
/*
+-----------------------------------------------------------------------+
| (C) ADDI-DATA GmbH Dieselstraße 3 D-77833 Ottersweier |
+-----------------------------------------------------------------------+
| Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com |
| Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com |
+-------------------------------+---------------------------------------+
| Project : APCI-2016 | Compiler : GCC |
| Module name : hwdrv_apci2016.c| Version : 2.96 |
+-------------------------------+---------------------------------------+
| Project manager: Eric Stolz | Date : 02/12/2002 |
+-------------------------------+---------------------------------------+
| Description : Hardware Layer Acces For APCI-2016 |
+-----------------------------------------------------------------------+
| UPDATES |
+----------+-----------+------------------------------------------------+
| Date | Author | Description of updates |
+----------+-----------+------------------------------------------------+
| | | |
| | | |
| | | |
+----------+-----------+------------------------------------------------+
*/
/*
+----------------------------------------------------------------------------+
| Included files |
+----------------------------------------------------------------------------+
*/
#include "hwdrv_apci2016.h"
/*
+----------------------------------------------------------------------------+
| Function Name : int i_APCI2016_ConfigDigitalOutput |
| (struct comedi_device *dev,struct comedi_subdevice *s, |
| struct comedi_insn *insn,unsigned int *data) |
+----------------------------------------------------------------------------+
| Task : Configures The Digital Output Subdevice. |
+----------------------------------------------------------------------------+
| Input Parameters : struct comedi_device *dev : Driver handle |
| UINT *data : Data Pointer contains |
| configuration parameters as below |
| |
| data[0] : 1 Digital Memory On |
| 0 Digital Memory Off |
+----------------------------------------------------------------------------+
| Output Parameters : -- |
+----------------------------------------------------------------------------+
| Return Value : TRUE : No error occur |
| : FALSE : Error occur. Return the error |
| |
+----------------------------------------------------------------------------+
*/
int i_APCI2016_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
struct comedi_insn * insn, unsigned int * data)
{
if ((data[0] != 0) && (data[0] != 1)) {
comedi_error(dev,
"Not a valid Data !!! ,Data should be 1 or 0\n");
return -EINVAL;
} // if ((data[0]!=0) && (data[0]!=1))
if (data[0]) {
devpriv->b_OutputMemoryStatus = ADDIDATA_ENABLE;
} // if (data[0]
else {
devpriv->b_OutputMemoryStatus = ADDIDATA_DISABLE;
} // else if (data[0]
return insn->n;
}
/*
+----------------------------------------------------------------------------+
| Function Name : int i_APCI2016_WriteDigitalOutput |
| (struct comedi_device *dev,struct comedi_subdevice *s, |
| struct comedi_insn *insn,unsigned int *data) |
+----------------------------------------------------------------------------+
| Task : Writes port value To the selected port |
+----------------------------------------------------------------------------+
| Input Parameters : struct comedi_device *dev : Driver handle |
| UINT ui_NoOfChannels : No Of Channels To Write |
| UINT *data : Data Pointer to read status |
+----------------------------------------------------------------------------+
| Output Parameters : -- |
+----------------------------------------------------------------------------+
| Return Value : TRUE : No error occur |
| : FALSE : Error occur. Return the error |
| |
+----------------------------------------------------------------------------+
*/
int i_APCI2016_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
struct comedi_insn * insn, unsigned int * data)
{
UINT ui_NoOfChannel;
UINT ui_Temp, ui_Temp1;
ui_NoOfChannel = CR_CHAN(insn->chanspec);
if ((ui_NoOfChannel < 0) || (ui_NoOfChannel > 15)) {
comedi_error(dev,
"Invalid Channel Numbers !!!, Channel Numbers must be between 0 and 15\n");
return -EINVAL;
} // if ((ui_NoOfChannel<0) || (ui_NoOfChannel>15))
if (devpriv->b_OutputMemoryStatus) {
ui_Temp = inw(devpriv->iobase + APCI2016_DIGITAL_OP);
} // if (devpriv->b_OutputMemoryStatus )
else {
ui_Temp = 0;
} // else if (devpriv->b_OutputMemoryStatus )
if ((data[1] != 0) && (data[1] != 1)) {
comedi_error(dev,
"Invalid Data[1] value !!!, Data[1] should be 0 or 1\n");
return -EINVAL;
} // if ((data[1]!=0) && (data[1]!=1))
if (data[3] == 0) {
if (data[1] == 0) {
data[0] = (data[0] << ui_NoOfChannel) | ui_Temp;
outw(data[0], devpriv->iobase + APCI2016_DIGITAL_OP);
} // if (data[1]==0)
else {
if (data[1] == 1) {
switch (ui_NoOfChannel) {
case 2:
data[0] =
(data[0] << (2 *
data[2])) | ui_Temp;
break;
case 4:
data[0] =
(data[0] << (4 *
data[2])) | ui_Temp;
break;
case 8:
data[0] =
(data[0] << (8 *
data[2])) | ui_Temp;
break;
case 15:
data[0] = data[0] | ui_Temp;
break;
default:
comedi_error(dev, " chan spec wrong");
return -EINVAL; // "sorry channel spec wrong "
} //switch(ui_NoOfChannels)
outw(data[0],
devpriv->iobase + APCI2016_DIGITAL_OP);
} // if (data[1]==1)
else {
printk("\nSpecified channel not supported\n");
} // else if (data[1]==1)
} // else if (data[1]==0)
} // if (data[3]==0)
else {
if (data[3] == 1) {
if (data[1] == 0) {
data[0] = ~data[0] & 0x1;
ui_Temp1 = 1;
ui_Temp1 = ui_Temp1 << ui_NoOfChannel;
ui_Temp = ui_Temp | ui_Temp1;
data[0] = (data[0] << ui_NoOfChannel) ^ 0xffff;
data[0] = data[0] & ui_Temp;
outw(data[0],
devpriv->iobase + APCI2016_DIGITAL_OP);
} // if (data[1]==0)
else {
if (data[1] == 1) {
switch (ui_NoOfChannel) {
case 2:
data[0] = ~data[0] & 0x3;
ui_Temp1 = 3;
ui_Temp1 =
ui_Temp1 << 2 * data[2];
ui_Temp = ui_Temp | ui_Temp1;
data[0] =
((data[0] << (2 *
data
[2])) ^
0xffff) & ui_Temp;
break;
case 4:
data[0] = ~data[0] & 0xf;
ui_Temp1 = 15;
ui_Temp1 =
ui_Temp1 << 4 * data[2];
ui_Temp = ui_Temp | ui_Temp1;
data[0] =
((data[0] << (4 *
data
[2])) ^
0xffff) & ui_Temp;
break;
case 8:
data[0] = ~data[0] & 0xff;
ui_Temp1 = 255;
ui_Temp1 =
ui_Temp1 << 8 * data[2];
ui_Temp = ui_Temp | ui_Temp1;
data[0] =
((data[0] << (8 *
data
[2])) ^
0xffff) & ui_Temp;
break;
case 15:
break;
default:
comedi_error(dev,
" chan spec wrong");
return -EINVAL; // "sorry channel spec wrong "
} //switch(ui_NoOfChannels)
outw(data[0],
devpriv->iobase +
APCI2016_DIGITAL_OP);
} // if(data[1]==1)
else {
printk("\nSpecified channel not supported\n");
} //else if(data[1]==1)
} //elseif(data[1]==0)
} //if(data[3]==1);
else {
printk("\nSpecified functionality does not exist\n");
return -EINVAL;
} //if else data[3]==1)
} //if else data[3]==0)
return insn->n;
}
/*
+----------------------------------------------------------------------------+
| Function Name : int i_APCI2016_BitsDigitalOutput |
| (struct comedi_device *dev,struct comedi_subdevice *s, |
| struct comedi_insn *insn,unsigned int *data) |
+----------------------------------------------------------------------------+
| Task : Read value of the selected channel or port |
+----------------------------------------------------------------------------+
| Input Parameters : struct comedi_device *dev : Driver handle |
| UINT ui_NoOfChannels : No Of Channels To read |
| UINT *data : Data Pointer to read status |
+----------------------------------------------------------------------------+
| Output Parameters : -- |
+----------------------------------------------------------------------------+
| Return Value : TRUE : No error occur |
| : FALSE : Error occur. Return the error |
| |
+----------------------------------------------------------------------------+
*/
int i_APCI2016_BitsDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
struct comedi_insn * insn, unsigned int * data)
{
UINT ui_Temp;
UINT ui_NoOfChannel;
ui_NoOfChannel = CR_CHAN(insn->chanspec);
if ((ui_NoOfChannel < 0) || (ui_NoOfChannel > 15)) {
comedi_error(dev,
"Invalid Channel Numbers !!!, Channel Numbers must be between 0 and 15\n");
return -EINVAL;
} // if ((ui_NoOfChannel<0) || (ui_NoOfChannel>15))
if ((data[0] != 0) && (data[0] != 1)) {
comedi_error(dev,
"Invalid Data[0] value !!!, Data[0] should be 0 or 1\n");
return -EINVAL;
} // if ((data[0]!=0) && (data[0]!=1))
ui_Temp = data[0];
*data = inw(devpriv->iobase + APCI2016_DIGITAL_OP_RW);
if (ui_Temp == 0) {
*data = (*data >> ui_NoOfChannel) & 0x1;
} // if (ui_Temp==0)
else {
if (ui_Temp == 1) {
switch (ui_NoOfChannel) {
case 2:
*data = (*data >> (2 * data[1])) & 3;
break;
case 4:
*data = (*data >> (4 * data[1])) & 15;
break;
case 8:
*data = (*data >> (8 * data[1])) & 255;
break;
case 15:
break;
default:
comedi_error(dev, " chan spec wrong");
return -EINVAL; // "sorry channel spec wrong "
} //switch(ui_NoOfChannel)
} // if (ui_Temp==1)
else {
printk("\nSpecified channel not supported \n");
} // else if (ui_Temp==1)
} // if (ui_Temp==0)
return insn->n;
}
/*
+----------------------------------------------------------------------------+
| Function Name : int i_APCI2016_ConfigWatchdog |
| (struct comedi_device *dev,struct comedi_subdevice *s, |
| struct comedi_insn *insn,unsigned int *data) |
+----------------------------------------------------------------------------+
| Task : Configures The Watchdog |
+----------------------------------------------------------------------------+
| Input Parameters : struct comedi_device *dev : Driver handle |
| struct comedi_subdevice *s, :pointer to subdevice structure |
| struct comedi_insn *insn :pointer to insn structure |
| unsigned int *data : Data Pointer to read status |
+----------------------------------------------------------------------------+
| Output Parameters : -- |
+----------------------------------------------------------------------------+
| Return Value : TRUE : No error occur |
| : FALSE : Error occur. Return the error |
| |
+----------------------------------------------------------------------------+
*/
int i_APCI2016_ConfigWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
struct comedi_insn * insn, unsigned int * data)
{
if (data[0] == 0) {
//Disable the watchdog
outw(0x0,
devpriv->i_IobaseAddon +
APCI2016_WATCHDOG_ENABLEDISABLE);
//Loading the Reload value
outw(data[1],
devpriv->i_IobaseAddon +
APCI2016_WATCHDOG_RELOAD_VALUE);
data[1] = data[1] >> 16;
outw(data[1],
devpriv->i_IobaseAddon +
APCI2016_WATCHDOG_RELOAD_VALUE + 2);
} else {
printk("\nThe input parameters are wrong\n");
}
return insn->n;
}
/*
+----------------------------------------------------------------------------+
| Function Name : int i_APCI2016_StartStopWriteWatchdog |
| (struct comedi_device *dev,struct comedi_subdevice *s, |
| struct comedi_insn *insn,unsigned int *data) |
+----------------------------------------------------------------------------+
| Task : Start / Stop The Watchdog |
+----------------------------------------------------------------------------+
| Input Parameters : struct comedi_device *dev : Driver handle |
| struct comedi_subdevice *s, :pointer to subdevice structure |
| struct comedi_insn *insn :pointer to insn structure |
| unsigned int *data : Data Pointer to read status |
+----------------------------------------------------------------------------+
| Output Parameters : -- |
+----------------------------------------------------------------------------+
| Return Value : TRUE : No error occur |
| : FALSE : Error occur. Return the error |
| |
+----------------------------------------------------------------------------+
*/
int i_APCI2016_StartStopWriteWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
struct comedi_insn * insn, unsigned int * data)
{
switch (data[0]) {
case 0: //stop the watchdog
outw(0x0, devpriv->i_IobaseAddon + APCI2016_WATCHDOG_ENABLEDISABLE); //disable the watchdog
break;
case 1: //start the watchdog
outw(0x0001,
devpriv->i_IobaseAddon +
APCI2016_WATCHDOG_ENABLEDISABLE);
break;
case 2: //Software trigger
outw(0x0201,
devpriv->i_IobaseAddon +
APCI2016_WATCHDOG_ENABLEDISABLE);
break;
default:
printk("\nSpecified functionality does not exist\n");
return -EINVAL;
} // switch(data[0])
return insn->n;
}
/*
+----------------------------------------------------------------------------+
| Function Name : int i_APCI2016_ReadWatchdog |
| (struct comedi_device *dev,struct comedi_subdevice *s, |
| struct comedi_insn *insn,unsigned int *data) |
+----------------------------------------------------------------------------+
| Task : Read The Watchdog |
+----------------------------------------------------------------------------+
| Input Parameters : struct comedi_device *dev : Driver handle |
| struct comedi_subdevice *s, :pointer to subdevice structure |
| struct comedi_insn *insn :pointer to insn structure |
| unsigned int *data : Data Pointer to read status |
+----------------------------------------------------------------------------+
| Output Parameters : -- |
+----------------------------------------------------------------------------+
| Return Value : TRUE : No error occur |
| : FALSE : Error occur. Return the error |
| |
+----------------------------------------------------------------------------+
*/
int i_APCI2016_ReadWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
struct comedi_insn * insn, unsigned int * data)
{
udelay(5);
data[0] = inw(devpriv->i_IobaseAddon + APCI2016_WATCHDOG_STATUS) & 0x1;
return insn->n;
}
/*
+----------------------------------------------------------------------------+
| Function Name : int i_APCI2016_Reset(struct comedi_device *dev) | |
+----------------------------------------------------------------------------+
| Task :resets all the registers |
+----------------------------------------------------------------------------+
| Input Parameters : struct comedi_device *dev
+----------------------------------------------------------------------------+
| Output Parameters : -- |
+----------------------------------------------------------------------------+
| Return Value : |
| |
+----------------------------------------------------------------------------+
*/
INT i_APCI2016_Reset(struct comedi_device * dev)
{
outw(0x0, devpriv->iobase + APCI2016_DIGITAL_OP); // Resets the digital output channels
outw(0x0, devpriv->i_IobaseAddon + APCI2016_WATCHDOG_ENABLEDISABLE);
outw(0x0, devpriv->i_IobaseAddon + APCI2016_WATCHDOG_RELOAD_VALUE);
outw(0x0, devpriv->i_IobaseAddon + APCI2016_WATCHDOG_RELOAD_VALUE + 2);
return 0;
}

View file

@ -0,0 +1,70 @@
/*
* Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
*
* ADDI-DATA GmbH
* Dieselstrasse 3
* D-77833 Ottersweier
* Tel: +19(0)7223/9493-0
* Fax: +49(0)7223/9493-92
* http://www.addi-data-com
* info@addi-data.com
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*/
/********* Definitions for APCI-2016 card *****/
#define APCI2016_BOARD_VENDOR_ID 0x15B8
#define APCI2016_ADDRESS_RANGE 8
//DIGITAL INPUT-OUTPUT DEFINE
#define APCI2016_DIGITAL_OP 0x04
#define APCI2016_DIGITAL_OP_RW 4
//ADDIDATA Enable Disable
#define ADDIDATA_ENABLE 1
#define ADDIDATA_DISABLE 0
// TIMER COUNTER WATCHDOG DEFINES
#define ADDIDATA_WATCHDOG 2
#define APCI2016_DIGITAL_OP_WATCHDOG 0
#define APCI2016_WATCHDOG_ENABLEDISABLE 12
#define APCI2016_WATCHDOG_RELOAD_VALUE 4
#define APCI2016_WATCHDOG_STATUS 16
// Hardware Layer functions for Apci2016
//DO
int i_APCI2016_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
int i_APCI2016_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
int i_APCI2016_BitsDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
// TIMER
// timer value is passed as u seconds
int i_APCI2016_ConfigWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
int i_APCI2016_StartStopWriteWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
int i_APCI2016_ReadWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
// Interrupt functions.....
// void v_APCI2016_Interrupt(int irq, void *d) ;
//void v_APCI2016_Interrupt(int irq, void *d);
// RESET
INT i_APCI2016_Reset(struct comedi_device *dev);

View file

@ -0,0 +1,579 @@
/**
@verbatim
Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
ADDI-DATA GmbH
Dieselstrasse 3
D-77833 Ottersweier
Tel: +19(0)7223/9493-0
Fax: +49(0)7223/9493-92
http://www.addi-data-com
info@addi-data.com
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
You shoud also find the complete GPL in the COPYING file accompanying this source code.
@endverbatim
*/
/*
+-----------------------------------------------------------------------+
| (C) ADDI-DATA GmbH Dieselstraße 3 D-77833 Ottersweier |
+-----------------------------------------------------------------------+
| Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com |
| Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com |
+-------------------------------+---------------------------------------+
| Project : APCI-2032 | Compiler : GCC |
| Module name : hwdrv_apci2032.c| Version : 2.96 |
+-------------------------------+---------------------------------------+
| Project manager: Eric Stolz | Date : 02/12/2002 |
+-------------------------------+---------------------------------------+
| Description : Hardware Layer Acces For APCI-2032 |
+-----------------------------------------------------------------------+
| UPDATES |
+----------+-----------+------------------------------------------------+
| Date | Author | Description of updates |
+----------+-----------+------------------------------------------------+
| | | |
| | | |
| | | |
+----------+-----------+------------------------------------------------+
*/
/*
+----------------------------------------------------------------------------+
| Included files |
+----------------------------------------------------------------------------+
*/
#include "hwdrv_apci2032.h"
UINT ui_InterruptData, ui_Type;
/*
+----------------------------------------------------------------------------+
| Function Name : int i_APCI2032_ConfigDigitalOutput |
| (struct comedi_device *dev,struct comedi_subdevice *s, |
| struct comedi_insn *insn,unsigned int *data) |
+----------------------------------------------------------------------------+
| Task : Configures The Digital Output Subdevice. |
+----------------------------------------------------------------------------+
| Input Parameters : struct comedi_device *dev : Driver handle |
| UINT *data : Data Pointer contains |
| configuration parameters as below |
| |
| data[1] : 1 Enable VCC Interrupt |
| 0 Disable VCC Interrupt |
| data[2] : 1 Enable CC Interrupt |
| 0 Disable CC Interrupt |
| |
+----------------------------------------------------------------------------+
| Output Parameters : -- |
+----------------------------------------------------------------------------+
| Return Value : TRUE : No error occur |
| : FALSE : Error occur. Return the error |
| |
+----------------------------------------------------------------------------+
*/
int i_APCI2032_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
struct comedi_insn * insn, unsigned int * data)
{
ULONG ul_Command = 0;
devpriv->tsk_Current = current;
if ((data[0] != 0) && (data[0] != 1)) {
comedi_error(dev,
"Not a valid Data !!! ,Data should be 1 or 0\n");
return -EINVAL;
} //if ( (data[0]!=0) && (data[0]!=1) )
if (data[0]) {
devpriv->b_OutputMemoryStatus = ADDIDATA_ENABLE;
} // if (data[0])
else {
devpriv->b_OutputMemoryStatus = ADDIDATA_DISABLE;
} //else if (data[0])
if (data[1] == ADDIDATA_ENABLE) {
ul_Command = ul_Command | 0x1;
} //if (data[1] == ADDIDATA_ENABLE)
else {
ul_Command = ul_Command & 0xFFFFFFFE;
} //elseif (data[1] == ADDIDATA_ENABLE)
if (data[2] == ADDIDATA_ENABLE) {
ul_Command = ul_Command | 0x2;
} //if (data[2] == ADDIDATA_ENABLE)
else {
ul_Command = ul_Command & 0xFFFFFFFD;
} //elseif (data[2] == ADDIDATA_ENABLE)
outl(ul_Command, devpriv->iobase + APCI2032_DIGITAL_OP_INTERRUPT);
ui_InterruptData = inl(devpriv->iobase + APCI2032_DIGITAL_OP_INTERRUPT);
return insn->n;
}
/*
+----------------------------------------------------------------------------+
| Function Name : int i_APCI2032_WriteDigitalOutput |
| (struct comedi_device *dev,struct comedi_subdevice *s, |
| struct comedi_insn *insn,unsigned int *data) |
+----------------------------------------------------------------------------+
| Task : Writes port value To the selected port |
+----------------------------------------------------------------------------+
| Input Parameters : struct comedi_device *dev : Driver handle |
| UINT ui_NoOfChannels : No Of Channels To Write |
| UINT *data : Data Pointer to read status |
+----------------------------------------------------------------------------+
| Output Parameters : -- |
+----------------------------------------------------------------------------+
| Return Value : TRUE : No error occur |
| : FALSE : Error occur. Return the error |
| |
+----------------------------------------------------------------------------+
*/
INT i_APCI2032_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
struct comedi_insn * insn, unsigned int * data)
{
UINT ui_Temp, ui_Temp1;
UINT ui_NoOfChannel = CR_CHAN(insn->chanspec); // get the channel
if (devpriv->b_OutputMemoryStatus) {
ui_Temp = inl(devpriv->iobase + APCI2032_DIGITAL_OP);
} //if(devpriv->b_OutputMemoryStatus )
else {
ui_Temp = 0;
} //if(devpriv->b_OutputMemoryStatus )
if (data[3] == 0) {
if (data[1] == 0) {
data[0] = (data[0] << ui_NoOfChannel) | ui_Temp;
outl(data[0], devpriv->iobase + APCI2032_DIGITAL_OP);
} //if(data[1]==0)
else {
if (data[1] == 1) {
switch (ui_NoOfChannel) {
case 2:
data[0] =
(data[0] << (2 *
data[2])) | ui_Temp;
break;
case 4:
data[0] =
(data[0] << (4 *
data[2])) | ui_Temp;
break;
case 8:
data[0] =
(data[0] << (8 *
data[2])) | ui_Temp;
break;
case 16:
data[0] =
(data[0] << (16 *
data[2])) | ui_Temp;
break;
case 31:
data[0] = data[0] | ui_Temp;
break;
default:
comedi_error(dev, " chan spec wrong");
return -EINVAL; // "sorry channel spec wrong "
} //switch(ui_NoOfChannels)
outl(data[0],
devpriv->iobase + APCI2032_DIGITAL_OP);
} // if(data[1]==1)
else {
printk("\nSpecified channel not supported\n");
} //else if(data[1]==1)
} //elseif(data[1]==0)
} //if(data[3]==0)
else {
if (data[3] == 1) {
if (data[1] == 0) {
data[0] = ~data[0] & 0x1;
ui_Temp1 = 1;
ui_Temp1 = ui_Temp1 << ui_NoOfChannel;
ui_Temp = ui_Temp | ui_Temp1;
data[0] =
(data[0] << ui_NoOfChannel) ^
0xffffffff;
data[0] = data[0] & ui_Temp;
outl(data[0],
devpriv->iobase + APCI2032_DIGITAL_OP);
} //if(data[1]==0)
else {
if (data[1] == 1) {
switch (ui_NoOfChannel) {
case 2:
data[0] = ~data[0] & 0x3;
ui_Temp1 = 3;
ui_Temp1 =
ui_Temp1 << 2 * data[2];
ui_Temp = ui_Temp | ui_Temp1;
data[0] =
((data[0] << (2 *
data
[2])) ^
0xffffffff) & ui_Temp;
break;
case 4:
data[0] = ~data[0] & 0xf;
ui_Temp1 = 15;
ui_Temp1 =
ui_Temp1 << 4 * data[2];
ui_Temp = ui_Temp | ui_Temp1;
data[0] =
((data[0] << (4 *
data
[2])) ^
0xffffffff) & ui_Temp;
break;
case 8:
data[0] = ~data[0] & 0xff;
ui_Temp1 = 255;
ui_Temp1 =
ui_Temp1 << 8 * data[2];
ui_Temp = ui_Temp | ui_Temp1;
data[0] =
((data[0] << (8 *
data
[2])) ^
0xffffffff) & ui_Temp;
break;
case 16:
data[0] = ~data[0] & 0xffff;
ui_Temp1 = 65535;
ui_Temp1 =
ui_Temp1 << 16 *
data[2];
ui_Temp = ui_Temp | ui_Temp1;
data[0] =
((data[0] << (16 *
data
[2])) ^
0xffffffff) & ui_Temp;
break;
case 31:
break;
default:
comedi_error(dev,
" chan spec wrong");
return -EINVAL; // "sorry channel spec wrong "
} //switch(ui_NoOfChannels)
outl(data[0],
devpriv->iobase +
APCI2032_DIGITAL_OP);
} // if(data[1]==1)
else {
printk("\nSpecified channel not supported\n");
} //else if(data[1]==1)
} //elseif(data[1]==0)
} //if(data[3]==1);
else {
printk("\nSpecified functionality does not exist\n");
return -EINVAL;
} //if else data[3]==1)
} //if else data[3]==0)
return (insn->n);;
}
/*
+----------------------------------------------------------------------------+
| Function Name : int i_APCI2032_ReadDigitalOutput |
| (struct comedi_device *dev,struct comedi_subdevice *s, |
| struct comedi_insn *insn,unsigned int *data) |
+----------------------------------------------------------------------------+
| Task : Read value of the selected channel or port |
+----------------------------------------------------------------------------+
| Input Parameters : struct comedi_device *dev : Driver handle |
| UINT ui_NoOfChannels : No Of Channels To read |
| UINT *data : Data Pointer to read status |
+----------------------------------------------------------------------------+
| Output Parameters : -- |
+----------------------------------------------------------------------------+
| Return Value : TRUE : No error occur |
| : FALSE : Error occur. Return the error |
| |
+----------------------------------------------------------------------------+
*/
INT i_APCI2032_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
struct comedi_insn * insn, unsigned int * data)
{
UINT ui_Temp;
UINT ui_NoOfChannel;
ui_NoOfChannel = CR_CHAN(insn->chanspec);
ui_Temp = data[0];
*data = inl(devpriv->iobase + APCI2032_DIGITAL_OP_RW);
if (ui_Temp == 0) {
*data = (*data >> ui_NoOfChannel) & 0x1;
} //if (ui_Temp==0)
else {
if (ui_Temp == 1) {
switch (ui_NoOfChannel) {
case 2:
*data = (*data >> (2 * data[1])) & 3;
break;
case 4:
*data = (*data >> (4 * data[1])) & 15;
break;
case 8:
*data = (*data >> (8 * data[1])) & 255;
break;
case 16:
*data = (*data >> (16 * data[1])) & 65535;
break;
case 31:
break;
default:
comedi_error(dev, " chan spec wrong");
return -EINVAL; // "sorry channel spec wrong "
} //switch(ui_NoOfChannels)
} //if (ui_Temp==1)
else {
printk("\nSpecified channel not supported \n");
} //elseif (ui_Temp==1)
}
return insn->n;
}
/*
+----------------------------------------------------------------------------+
| Function Name : INT i_APCI2032_ConfigWatchdog(comedi_device
*dev,struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data)|
| |
+----------------------------------------------------------------------------+
| Task : Configures The Watchdog |
+----------------------------------------------------------------------------+
| Input Parameters : struct comedi_device *dev : Driver handle |
| struct comedi_subdevice *s, :pointer to subdevice structure
struct comedi_insn *insn :pointer to insn structure |
| unsigned int *data : Data Pointer to read status |
+----------------------------------------------------------------------------+
| Output Parameters : -- |
+----------------------------------------------------------------------------+
| Return Value : TRUE : No error occur |
| : FALSE : Error occur. Return the error |
| |
+----------------------------------------------------------------------------+
*/
INT i_APCI2032_ConfigWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
struct comedi_insn * insn, unsigned int * data)
{
if (data[0] == 0) {
//Disable the watchdog
outl(0x0,
devpriv->iobase + APCI2032_DIGITAL_OP_WATCHDOG +
APCI2032_TCW_PROG);
//Loading the Reload value
outl(data[1],
devpriv->iobase + APCI2032_DIGITAL_OP_WATCHDOG +
APCI2032_TCW_RELOAD_VALUE);
} else {
printk("\nThe input parameters are wrong\n");
return -EINVAL;
}
return insn->n;
}
/*
+----------------------------------------------------------------------------+
| Function Name : int i_APCI2032_StartStopWriteWatchdog |
| (struct comedi_device *dev,struct comedi_subdevice *s,
struct comedi_insn *insn,unsigned int *data); |
+----------------------------------------------------------------------------+
| Task : Start / Stop The Watchdog |
+----------------------------------------------------------------------------+
| Input Parameters : struct comedi_device *dev : Driver handle |
| struct comedi_subdevice *s, :pointer to subdevice structure
struct comedi_insn *insn :pointer to insn structure |
| unsigned int *data : Data Pointer to read status |
+----------------------------------------------------------------------------+
| Output Parameters : -- |
+----------------------------------------------------------------------------+
| Return Value : TRUE : No error occur |
| : FALSE : Error occur. Return the error |
| |
+----------------------------------------------------------------------------+
*/
int i_APCI2032_StartStopWriteWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
struct comedi_insn * insn, unsigned int * data)
{
switch (data[0]) {
case 0: //stop the watchdog
outl(0x0, devpriv->iobase + APCI2032_DIGITAL_OP_WATCHDOG + APCI2032_TCW_PROG); //disable the watchdog
break;
case 1: //start the watchdog
outl(0x0001,
devpriv->iobase + APCI2032_DIGITAL_OP_WATCHDOG +
APCI2032_TCW_PROG);
break;
case 2: //Software trigger
outl(0x0201,
devpriv->iobase + APCI2032_DIGITAL_OP_WATCHDOG +
APCI2032_TCW_PROG);
break;
default:
printk("\nSpecified functionality does not exist\n");
return -EINVAL;
}
return insn->n;
}
/*
+----------------------------------------------------------------------------+
| Function Name : int i_APCI2032_ReadWatchdog |
| (struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,
unsigned int *data); |
+----------------------------------------------------------------------------+
| Task : Read The Watchdog |
+----------------------------------------------------------------------------+
| Input Parameters : struct comedi_device *dev : Driver handle |
| struct comedi_subdevice *s, :pointer to subdevice structure
struct comedi_insn *insn :pointer to insn structure |
| unsigned int *data : Data Pointer to read status |
+----------------------------------------------------------------------------+
| Output Parameters : -- |
+----------------------------------------------------------------------------+
| Return Value : TRUE : No error occur |
| : FALSE : Error occur. Return the error |
| |
+----------------------------------------------------------------------------+
*/
int i_APCI2032_ReadWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
struct comedi_insn * insn, unsigned int * data)
{
data[0] =
inl(devpriv->iobase + APCI2032_DIGITAL_OP_WATCHDOG +
APCI2032_TCW_TRIG_STATUS) & 0x1;
return insn->n;
}
/*
+----------------------------------------------------------------------------+
| Function Name : void v_APCI2032_Interrupt |
| (int irq , void *d) |
+----------------------------------------------------------------------------+
| Task : Writes port value To the selected port |
+----------------------------------------------------------------------------+
| Input Parameters : int irq : irq number |
| void *d : void pointer |
+----------------------------------------------------------------------------+
| Output Parameters : -- |
+----------------------------------------------------------------------------+
| Return Value : TRUE : No error occur |
| : FALSE : Error occur. Return the error |
| |
+----------------------------------------------------------------------------+
*/
void v_APCI2032_Interrupt(int irq, void *d)
{
struct comedi_device *dev = d;
unsigned int ui_DO;
ui_DO = inl(devpriv->iobase + APCI2032_DIGITAL_OP_IRQ) & 0x1; //Check if VCC OR CC interrupt has occured.
if (ui_DO == 0) {
printk("\nInterrupt from unKnown source\n");
} // if(ui_DO==0)
if (ui_DO) {
// Check for Digital Output interrupt Type - 1: Vcc interrupt 2: CC interrupt.
ui_Type =
inl(devpriv->iobase +
APCI2032_DIGITAL_OP_INTERRUPT_STATUS) & 0x3;
outl(0x0,
devpriv->iobase + APCI2032_DIGITAL_OP +
APCI2032_DIGITAL_OP_INTERRUPT);
if (ui_Type == 1) {
//Sends signal to user space
send_sig(SIGIO, devpriv->tsk_Current, 0);
} // if (ui_Type==1)
else {
if (ui_Type == 2) {
// Sends signal to user space
send_sig(SIGIO, devpriv->tsk_Current, 0);
} //if (ui_Type==2)
} //else if (ui_Type==1)
} //if(ui_DO)
return;
}
/*
+----------------------------------------------------------------------------+
| Function Name : int i_APCI2032_ReadInterruptStatus |
| (struct comedi_device *dev,struct comedi_subdevice *s, |
| struct comedi_insn *insn,unsigned int *data) |
+----------------------------------------------------------------------------+
| Task :Reads the interrupt status register |
+----------------------------------------------------------------------------+
| Input Parameters : |
+----------------------------------------------------------------------------+
| Output Parameters : -- |
+----------------------------------------------------------------------------+
| Return Value : |
| |
+----------------------------------------------------------------------------+
*/
int i_APCI2032_ReadInterruptStatus(struct comedi_device * dev, struct comedi_subdevice * s,
struct comedi_insn * insn, unsigned int * data)
{
*data = ui_Type;
return insn->n;
}
/*
+----------------------------------------------------------------------------+
| Function Name : int i_APCI2032_Reset(struct comedi_device *dev) |
| |
+----------------------------------------------------------------------------+
| Task :Resets the registers of the card |
+----------------------------------------------------------------------------+
| Input Parameters : |
+----------------------------------------------------------------------------+
| Output Parameters : -- |
+----------------------------------------------------------------------------+
| Return Value : |
| |
+----------------------------------------------------------------------------+
*/
int i_APCI2032_Reset(struct comedi_device * dev)
{
devpriv->b_DigitalOutputRegister = 0;
ui_Type = 0;
outl(0x0, devpriv->iobase + APCI2032_DIGITAL_OP); //Resets the output channels
outl(0x0, devpriv->iobase + APCI2032_DIGITAL_OP_INTERRUPT); //Disables the interrupt.
outl(0x0, devpriv->iobase + APCI2032_DIGITAL_OP_WATCHDOG + APCI2032_TCW_PROG); //disable the watchdog
outl(0x0, devpriv->iobase + APCI2032_DIGITAL_OP_WATCHDOG + APCI2032_TCW_RELOAD_VALUE); //reload=0
return 0;
}

View file

@ -0,0 +1,81 @@
/*
* Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
*
* ADDI-DATA GmbH
* Dieselstrasse 3
* D-77833 Ottersweier
* Tel: +19(0)7223/9493-0
* Fax: +49(0)7223/9493-92
* http://www.addi-data-com
* info@addi-data.com
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*/
/********* Definitions for APCI-2032 card *****/
// Card Specific information
#define APCI2032_BOARD_VENDOR_ID 0x15B8
#define APCI2032_ADDRESS_RANGE 63
//DIGITAL INPUT-OUTPUT DEFINE
#define APCI2032_DIGITAL_OP 0
#define APCI2032_DIGITAL_OP_RW 0
#define APCI2032_DIGITAL_OP_INTERRUPT 4
#define APCI2032_DIGITAL_OP_IRQ 12
//Digital Output Interrupt Status
#define APCI2032_DIGITAL_OP_INTERRUPT_STATUS 8
//Digital Output Interrupt Enable Disable.
#define APCI2032_DIGITAL_OP_VCC_INTERRUPT_ENABLE 0x1
#define APCI2032_DIGITAL_OP_VCC_INTERRUPT_DISABLE 0xFFFFFFFE
#define APCI2032_DIGITAL_OP_CC_INTERRUPT_ENABLE 0x2
#define APCI2032_DIGITAL_OP_CC_INTERRUPT_DISABLE 0xFFFFFFFD
//ADDIDATA Enable Disable
#define ADDIDATA_ENABLE 1
#define ADDIDATA_DISABLE 0
// TIMER COUNTER WATCHDOG DEFINES
#define ADDIDATA_WATCHDOG 2
#define APCI2032_DIGITAL_OP_WATCHDOG 16
#define APCI2032_TCW_RELOAD_VALUE 4
#define APCI2032_TCW_TIMEBASE 8
#define APCI2032_TCW_PROG 12
#define APCI2032_TCW_TRIG_STATUS 16
#define APCI2032_TCW_IRQ 20
// Hardware Layer functions for Apci2032
//DO
int i_APCI2032_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
INT i_APCI2032_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
INT i_APCI2032_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
int i_APCI2032_ReadInterruptStatus(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
// TIMER
// timer value is passed as u seconds
INT i_APCI2032_ConfigWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
int i_APCI2032_StartStopWriteWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
int i_APCI2032_ReadWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
// Interrupt functions.....
void v_APCI2032_Interrupt(int irq, void *d);
//Reset functions
int i_APCI2032_Reset(struct comedi_device *dev);

View file

@ -0,0 +1,549 @@
/**
@verbatim
Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
ADDI-DATA GmbH
Dieselstrasse 3
D-77833 Ottersweier
Tel: +19(0)7223/9493-0
Fax: +49(0)7223/9493-92
http://www.addi-data-com
info@addi-data.com
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
You shoud also find the complete GPL in the COPYING file accompanying this source code.
@endverbatim
*/
/*
+-----------------------------------------------------------------------+
| (C) ADDI-DATA GmbH Dieselstraße 3 D-77833 Ottersweier |
+-----------------------------------------------------------------------+
| Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com |
| Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com |
+-------------------------------+---------------------------------------+
| Project : APCI-2200 | Compiler : GCC |
| Module name : hwdrv_apci2200.c| Version : 2.96 |
+-------------------------------+---------------------------------------+
| Project manager: Eric Stolz | Date : 02/12/2002 |
+-------------------------------+---------------------------------------+
| Description : Hardware Layer Acces For APCI-2200 |
+-----------------------------------------------------------------------+
| UPDATES |
+----------+-----------+------------------------------------------------+
| Date | Author | Description of updates |
+----------+-----------+------------------------------------------------+
| | | |
| | | |
| | | |
+----------+-----------+------------------------------------------------+
*/
/*
+----------------------------------------------------------------------------+
| Included files |
+----------------------------------------------------------------------------+
*/
#include "hwdrv_apci2200.h"
/*
+----------------------------------------------------------------------------+
| Function Name : int i_APCI2200_Read1DigitalInput |
| (struct comedi_device *dev,struct comedi_subdevice *s, |
| struct comedi_insn *insn,unsigned int *data) |
+----------------------------------------------------------------------------+
| Task : Return the status of the digital input |
+----------------------------------------------------------------------------+
| Input Parameters : struct comedi_device *dev : Driver handle |
| struct comedi_subdevice *s, :pointer to subdevice structure
struct comedi_insn *insn :pointer to insn structure |
| unsigned int *data : Data Pointer to read status |
+----------------------------------------------------------------------------+
| Output Parameters : -- |
+----------------------------------------------------------------------------+
| Return Value : TRUE : No error occur |
| : FALSE : Error occur. Return the error |
| |
+----------------------------------------------------------------------------+
*/
INT i_APCI2200_Read1DigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
struct comedi_insn * insn, unsigned int * data)
{
UINT ui_TmpValue = 0;
UINT ui_Channel;
ui_Channel = CR_CHAN(insn->chanspec);
if (ui_Channel >= 0 && ui_Channel <= 7) {
ui_TmpValue = (UINT) inw(devpriv->iobase + APCI2200_DIGITAL_IP);
*data = (ui_TmpValue >> ui_Channel) & 0x1;
} //if(ui_Channel >= 0 && ui_Channel <=7)
else {
printk("\nThe specified channel does not exist\n");
return -EINVAL; // "sorry channel spec wrong "
} //else if(ui_Channel >= 0 && ui_Channel <=7)
return insn->n;
}
/*
+----------------------------------------------------------------------------+
| Function Name : int i_APCI2200_ReadMoreDigitalInput |
| (struct comedi_device *dev,struct comedi_subdevice *s, |
| struct comedi_insn *insn,unsigned int *data) |
+----------------------------------------------------------------------------+
| Task : Return the status of the Requested digital inputs |
+----------------------------------------------------------------------------+
| Input Parameters : struct comedi_device *dev : Driver handle |
| struct comedi_subdevice *s, :pointer to subdevice structure
struct comedi_insn *insn :pointer to insn structure |
| unsigned int *data : Data Pointer to read status |
+----------------------------------------------------------------------------+
| Output Parameters : -- |
+----------------------------------------------------------------------------+
| Return Value : TRUE : No error occur |
| : FALSE : Error occur. Return the error |
| |
+----------------------------------------------------------------------------+
*/
INT i_APCI2200_ReadMoreDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
struct comedi_insn * insn, unsigned int * data)
{
UINT ui_PortValue = data[0];
UINT ui_Mask = 0;
UINT ui_NoOfChannels;
ui_NoOfChannels = CR_CHAN(insn->chanspec);
*data = (UINT) inw(devpriv->iobase + APCI2200_DIGITAL_IP);
switch (ui_NoOfChannels) {
case 2:
ui_Mask = 3;
*data = (*data >> (2 * ui_PortValue)) & ui_Mask;
break;
case 4:
ui_Mask = 15;
*data = (*data >> (4 * ui_PortValue)) & ui_Mask;
break;
case 7:
break;
default:
printk("\nWrong parameters\n");
return -EINVAL; // "sorry channel spec wrong "
break;
} //switch(ui_NoOfChannels)
return insn->n;
}
/*
+----------------------------------------------------------------------------+
| Function Name : int i_APCI2200_ConfigDigitalOutput (struct comedi_device *dev,
struct comedi_subdevice *s struct comedi_insn *insn,unsigned int *data) |
| |
+----------------------------------------------------------------------------+
| Task : Configures The Digital Output Subdevice. |
+----------------------------------------------------------------------------+
| Input Parameters : struct comedi_device *dev : Driver handle |
| unsigned int *data : Data Pointer contains |
| configuration parameters as below |
| struct comedi_subdevice *s, :pointer to subdevice structure
struct comedi_insn *insn :pointer to insn structure |
| data[0] :1:Memory on |
| 0:Memory off |
| |
| |
+----------------------------------------------------------------------------+
| Output Parameters : -- |
+----------------------------------------------------------------------------+
| Return Value : TRUE : No error occur |
| : FALSE : Error occur. Return the error |
| |
+----------------------------------------------------------------------------+
*/
int i_APCI2200_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
struct comedi_insn * insn, unsigned int * data)
{
devpriv->b_OutputMemoryStatus = data[0];
return insn->n;
}
/*
+----------------------------------------------------------------------------+
| Function Name : int i_APCI2200_WriteDigitalOutput |
| (struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,
unsigned int *data) |
+----------------------------------------------------------------------------+
| Task : Writes port value To the selected port |
+----------------------------------------------------------------------------+
| Input Parameters : struct comedi_device *dev : Driver handle |
| struct comedi_subdevice *s, :pointer to subdevice structure
struct comedi_insn *insn :pointer to insn structure |
| unsigned int *data : Data Pointer to read status |
+----------------------------------------------------------------------------+
| Output Parameters : -- |
+----------------------------------------------------------------------------+
| Return Value : TRUE : No error occur |
| : FALSE : Error occur. Return the error |
| |
+----------------------------------------------------------------------------+
*/
INT i_APCI2200_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
struct comedi_insn * insn, unsigned int * data)
{
UINT ui_Temp, ui_Temp1;
UINT ui_NoOfChannel = CR_CHAN(insn->chanspec); // get the channel
if (devpriv->b_OutputMemoryStatus) {
ui_Temp = inw(devpriv->iobase + APCI2200_DIGITAL_OP);
} //if(devpriv->b_OutputMemoryStatus )
else {
ui_Temp = 0;
} //if(devpriv->b_OutputMemoryStatus )
if (data[3] == 0) {
if (data[1] == 0) {
data[0] = (data[0] << ui_NoOfChannel) | ui_Temp;
outw(data[0], devpriv->iobase + APCI2200_DIGITAL_OP);
} //if(data[1]==0)
else {
if (data[1] == 1) {
switch (ui_NoOfChannel) {
case 2:
data[0] =
(data[0] << (2 *
data[2])) | ui_Temp;
break;
case 4:
data[0] =
(data[0] << (4 *
data[2])) | ui_Temp;
break;
case 8:
data[0] =
(data[0] << (8 *
data[2])) | ui_Temp;
break;
case 15:
data[0] = data[0] | ui_Temp;
break;
default:
comedi_error(dev, " chan spec wrong");
return -EINVAL; // "sorry channel spec wrong "
} //switch(ui_NoOfChannels)
outw(data[0],
devpriv->iobase + APCI2200_DIGITAL_OP);
} // if(data[1]==1)
else {
printk("\nSpecified channel not supported\n");
} //else if(data[1]==1)
} //elseif(data[1]==0)
} //if(data[3]==0)
else {
if (data[3] == 1) {
if (data[1] == 0) {
data[0] = ~data[0] & 0x1;
ui_Temp1 = 1;
ui_Temp1 = ui_Temp1 << ui_NoOfChannel;
ui_Temp = ui_Temp | ui_Temp1;
data[0] = (data[0] << ui_NoOfChannel) ^ 0xffff;
data[0] = data[0] & ui_Temp;
outw(data[0],
devpriv->iobase + APCI2200_DIGITAL_OP);
} //if(data[1]==0)
else {
if (data[1] == 1) {
switch (ui_NoOfChannel) {
case 2:
data[0] = ~data[0] & 0x3;
ui_Temp1 = 3;
ui_Temp1 =
ui_Temp1 << 2 * data[2];
ui_Temp = ui_Temp | ui_Temp1;
data[0] =
((data[0] << (2 *
data
[2])) ^
0xffff) & ui_Temp;
break;
case 4:
data[0] = ~data[0] & 0xf;
ui_Temp1 = 15;
ui_Temp1 =
ui_Temp1 << 4 * data[2];
ui_Temp = ui_Temp | ui_Temp1;
data[0] =
((data[0] << (4 *
data
[2])) ^
0xffff) & ui_Temp;
break;
case 8:
data[0] = ~data[0] & 0xff;
ui_Temp1 = 255;
ui_Temp1 =
ui_Temp1 << 8 * data[2];
ui_Temp = ui_Temp | ui_Temp1;
data[0] =
((data[0] << (8 *
data
[2])) ^
0xffff) & ui_Temp;
break;
case 15:
break;
default:
comedi_error(dev,
" chan spec wrong");
return -EINVAL; // "sorry channel spec wrong "
} //switch(ui_NoOfChannels)
outw(data[0],
devpriv->iobase +
APCI2200_DIGITAL_OP);
} // if(data[1]==1)
else {
printk("\nSpecified channel not supported\n");
} //else if(data[1]==1)
} //elseif(data[1]==0)
} //if(data[3]==1);
else {
printk("\nSpecified functionality does not exist\n");
return -EINVAL;
} //if else data[3]==1)
} //if else data[3]==0)
return (insn->n);;
}
/*
+----------------------------------------------------------------------------+
| Function Name : int i_APCI2200_ReadDigitalOutput |
| (struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,
unsigned int *data) |
+----------------------------------------------------------------------------+
| Task : Read value of the selected channel or port |
+----------------------------------------------------------------------------+
| Input Parameters : struct comedi_device *dev : Driver handle |
| struct comedi_subdevice *s, :pointer to subdevice structure
struct comedi_insn *insn :pointer to insn structure |
| unsigned int *data : Data Pointer to read status |
+----------------------------------------------------------------------------+
| Output Parameters : -- |
+----------------------------------------------------------------------------+
| Return Value : TRUE : No error occur |
| : FALSE : Error occur. Return the error |
| |
+----------------------------------------------------------------------------+
*/
INT i_APCI2200_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
struct comedi_insn * insn, unsigned int * data)
{
UINT ui_Temp;
UINT ui_NoOfChannel = CR_CHAN(insn->chanspec); // get the channel
ui_Temp = data[0];
*data = inw(devpriv->iobase + APCI2200_DIGITAL_OP);
if (ui_Temp == 0) {
*data = (*data >> ui_NoOfChannel) & 0x1;
} //if(ui_Temp==0)
else {
if (ui_Temp == 1) {
switch (ui_NoOfChannel) {
case 2:
*data = (*data >> (2 * data[1])) & 3;
break;
case 4:
*data = (*data >> (4 * data[1])) & 15;
break;
case 8:
*data = (*data >> (8 * data[1])) & 255;
break;
case 15:
break;
default:
comedi_error(dev, " chan spec wrong");
return -EINVAL; // "sorry channel spec wrong "
} //switch(ui_NoOfChannels)
} //if(ui_Temp==1)
else {
printk("\nSpecified channel not supported \n");
} //elseif(ui_Temp==1)
} //elseif(ui_Temp==0)
return insn->n;
}
/*
+----------------------------------------------------------------------------+
| Function Name : int i_APCI2200_ConfigWatchdog(struct comedi_device *dev,
struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data) |
| |
+----------------------------------------------------------------------------+
| Task : Configures The Watchdog |
+----------------------------------------------------------------------------+
| Input Parameters : struct comedi_device *dev : Driver handle |
| struct comedi_subdevice *s, :pointer to subdevice structure
struct comedi_insn *insn :pointer to insn structure |
| unsigned int *data : Data Pointer to read status |
+----------------------------------------------------------------------------+
| Output Parameters : -- |
+----------------------------------------------------------------------------+
| Return Value : TRUE : No error occur |
| : FALSE : Error occur. Return the error |
| |
+----------------------------------------------------------------------------+
*/
int i_APCI2200_ConfigWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
struct comedi_insn * insn, unsigned int * data)
{
if (data[0] == 0) {
//Disable the watchdog
outw(0x0,
devpriv->iobase + APCI2200_WATCHDOG +
APCI2200_WATCHDOG_ENABLEDISABLE);
//Loading the Reload value
outw(data[1],
devpriv->iobase + APCI2200_WATCHDOG +
APCI2200_WATCHDOG_RELOAD_VALUE);
data[1] = data[1] >> 16;
outw(data[1],
devpriv->iobase + APCI2200_WATCHDOG +
APCI2200_WATCHDOG_RELOAD_VALUE + 2);
} //if(data[0]==0)
else {
printk("\nThe input parameters are wrong\n");
return -EINVAL;
} //elseif(data[0]==0)
return insn->n;
}
/*
+----------------------------------------------------------------------------+
| Function Name : int i_APCI2200_StartStopWriteWatchdog |
| (struct comedi_device *dev,struct comedi_subdevice *s,
struct comedi_insn *insn,unsigned int *data); |
+----------------------------------------------------------------------------+
| Task : Start / Stop The Watchdog |
+----------------------------------------------------------------------------+
| Input Parameters : struct comedi_device *dev : Driver handle |
| struct comedi_subdevice *s, :pointer to subdevice structure
struct comedi_insn *insn :pointer to insn structure |
| unsigned int *data : Data Pointer to read status |
+----------------------------------------------------------------------------+
| Output Parameters : -- |
+----------------------------------------------------------------------------+
| Return Value : TRUE : No error occur |
| : FALSE : Error occur. Return the error |
| |
+----------------------------------------------------------------------------+
*/
int i_APCI2200_StartStopWriteWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
struct comedi_insn * insn, unsigned int * data)
{
switch (data[0]) {
case 0: //stop the watchdog
outw(0x0, devpriv->iobase + APCI2200_WATCHDOG + APCI2200_WATCHDOG_ENABLEDISABLE); //disable the watchdog
break;
case 1: //start the watchdog
outw(0x0001,
devpriv->iobase + APCI2200_WATCHDOG +
APCI2200_WATCHDOG_ENABLEDISABLE);
break;
case 2: //Software trigger
outw(0x0201,
devpriv->iobase + APCI2200_WATCHDOG +
APCI2200_WATCHDOG_ENABLEDISABLE);
break;
default:
printk("\nSpecified functionality does not exist\n");
return -EINVAL;
} // switch(data[0])
return insn->n;
}
/*
+----------------------------------------------------------------------------+
| Function Name : int i_APCI2200_ReadWatchdog |
| (struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,
unsigned int *data); |
+----------------------------------------------------------------------------+
| Task : Read The Watchdog |
+----------------------------------------------------------------------------+
| Input Parameters : struct comedi_device *dev : Driver handle |
| struct comedi_subdevice *s, :pointer to subdevice structure
struct comedi_insn *insn :pointer to insn structure |
| unsigned int *data : Data Pointer to read status |
+----------------------------------------------------------------------------+
| Output Parameters : -- |
+----------------------------------------------------------------------------+
| Return Value : TRUE : No error occur |
| : FALSE : Error occur. Return the error |
| |
+----------------------------------------------------------------------------+
*/
int i_APCI2200_ReadWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
struct comedi_insn * insn, unsigned int * data)
{
data[0] =
inw(devpriv->iobase + APCI2200_WATCHDOG +
APCI2200_WATCHDOG_STATUS) & 0x1;
return insn->n;
}
/*
+----------------------------------------------------------------------------+
| Function Name : int i_APCI2200_Reset(struct comedi_device *dev) | |
+----------------------------------------------------------------------------+
| Task :resets all the registers |
+----------------------------------------------------------------------------+
| Input Parameters : struct comedi_device *dev
+----------------------------------------------------------------------------+
| Output Parameters : -- |
+----------------------------------------------------------------------------+
| Return Value : |
| |
+----------------------------------------------------------------------------+
*/
INT i_APCI2200_Reset(struct comedi_device * dev)
{
outw(0x0, devpriv->iobase + APCI2200_DIGITAL_OP); //RESETS THE DIGITAL OUTPUTS
outw(0x0,
devpriv->iobase + APCI2200_WATCHDOG +
APCI2200_WATCHDOG_ENABLEDISABLE);
outw(0x0,
devpriv->iobase + APCI2200_WATCHDOG +
APCI2200_WATCHDOG_RELOAD_VALUE);
outw(0x0,
devpriv->iobase + APCI2200_WATCHDOG +
APCI2200_WATCHDOG_RELOAD_VALUE + 2);
return 0;
}

View file

@ -0,0 +1,61 @@
/*
* Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
*
* ADDI-DATA GmbH
* Dieselstrasse 3
* D-77833 Ottersweier
* Tel: +19(0)7223/9493-0
* Fax: +49(0)7223/9493-92
* http://www.addi-data-com
* info@addi-data.com
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*/
/********* Definitions for APCI-2200 card *****/
// Card Specific information
#define APCI2200_BOARD_VENDOR_ID 0x15b8
#define APCI2200_ADDRESS_RANGE 64
//DIGITAL INPUT-OUTPUT DEFINE
#define APCI2200_DIGITAL_OP 4
#define APCI2200_DIGITAL_IP 0
// TIMER COUNTER WATCHDOG DEFINES
#define APCI2200_WATCHDOG 0x08
#define APCI2200_WATCHDOG_ENABLEDISABLE 12
#define APCI2200_WATCHDOG_RELOAD_VALUE 4
#define APCI2200_WATCHDOG_STATUS 16
// Hardware Layer functions for Apci2200
//Digital Input
INT i_APCI2200_ReadMoreDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
INT i_APCI2200_Read1DigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
//Digital Output
int i_APCI2200_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
INT i_APCI2200_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
INT i_APCI2200_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
// TIMER
int i_APCI2200_ConfigWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
int i_APCI2200_StartStopWriteWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
int i_APCI2200_ReadWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
//reset
INT i_APCI2200_Reset(struct comedi_device *dev);

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,241 @@
// hwdrv_apci3120.h
/*
* Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
*
* ADDI-DATA GmbH
* Dieselstrasse 3
* D-77833 Ottersweier
* Tel: +19(0)7223/9493-0
* Fax: +49(0)7223/9493-92
* http://www.addi-data-com
* info@addi-data.com
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*/
// comedi related defines
//ANALOG INPUT RANGE
static const struct comedi_lrange range_apci3120_ai = { 8, {
BIP_RANGE(10),
BIP_RANGE(5),
BIP_RANGE(2),
BIP_RANGE(1),
UNI_RANGE(10),
UNI_RANGE(5),
UNI_RANGE(2),
UNI_RANGE(1)
}
};
// ANALOG OUTPUT RANGE
static const struct comedi_lrange range_apci3120_ao = { 2, {
BIP_RANGE(10),
UNI_RANGE(10)
}
};
#define APCI3120_BIPOLAR_RANGES 4 // used for test on mixture of BIP/UNI ranges
#define APCI3120_BOARD_VENDOR_ID 0x10E8
#define APCI3120_ADDRESS_RANGE 16
#define APCI3120_DISABLE 0
#define APCI3120_ENABLE 1
#define APCI3120_START 1
#define APCI3120_STOP 0
#define APCI3120_EOC_MODE 1
#define APCI3120_EOS_MODE 2
#define APCI3120_DMA_MODE 3
//DIGITAL INPUT-OUTPUT DEFINE
#define APCI3120_DIGITAL_OUTPUT 0x0D
#define APCI3120_RD_STATUS 0x02
#define APCI3120_RD_FIFO 0x00
// digital output insn_write ON /OFF selection
#define APCI3120_SET4DIGITALOUTPUTON 1
#define APCI3120_SET4DIGITALOUTPUTOFF 0
// analog output SELECT BIT
#define APCI3120_ANALOG_OP_CHANNEL_1 0x0000
#define APCI3120_ANALOG_OP_CHANNEL_2 0x4000
#define APCI3120_ANALOG_OP_CHANNEL_3 0x8000
#define APCI3120_ANALOG_OP_CHANNEL_4 0xC000
#define APCI3120_ANALOG_OP_CHANNEL_5 0x0000
#define APCI3120_ANALOG_OP_CHANNEL_6 0x4000
#define APCI3120_ANALOG_OP_CHANNEL_7 0x8000
#define APCI3120_ANALOG_OP_CHANNEL_8 0xC000
// Enable external trigger bit in nWrAddress
#define APCI3120_ENABLE_EXT_TRIGGER 0x8000
//ANALOG OUTPUT AND INPUT DEFINE
#define APCI3120_UNIPOLAR 0x80 //$$ RAM sequence polarity BIT
#define APCI3120_BIPOLAR 0x00 //$$ RAM sequence polarity BIT
#define APCI3120_ANALOG_OUTPUT_1 0x08 // (ADDRESS )
#define APCI3120_ANALOG_OUTPUT_2 0x0A // (ADDRESS )
#define APCI3120_1_GAIN 0x00 //$$ RAM sequence Gain Bits for gain 1
#define APCI3120_2_GAIN 0x10 //$$ RAM sequence Gain Bits for gain 2
#define APCI3120_5_GAIN 0x20 //$$ RAM sequence Gain Bits for gain 5
#define APCI3120_10_GAIN 0x30 //$$ RAM sequence Gain Bits for gain 10
#define APCI3120_SEQ_RAM_ADDRESS 0x06 //$$ EARLIER NAMED APCI3120_FIFO_ADDRESS
#define APCI3120_RESET_FIFO 0x0C //(ADDRESS)
#define APCI3120_TIMER_0_MODE_2 0x01 //$$ Bits for timer mode
#define APCI3120_TIMER_0_MODE_4 0x2
#define APCI3120_SELECT_TIMER_0_WORD 0x00
#define APCI3120_ENABLE_TIMER0 0x1000 //$$Gatebit 0 in nWrAddress
#define APCI3120_CLEAR_PR 0xF0FF
#define APCI3120_CLEAR_PA 0xFFF0
#define APCI3120_CLEAR_PA_PR (APCI3120_CLEAR_PR & APCI3120_CLEAR_PA)
// nWrMode_Select
#define APCI3120_ENABLE_SCAN 0x8 //$$ bit in nWrMode_Select
#define APCI3120_DISABLE_SCAN (~APCI3120_ENABLE_SCAN)
#define APCI3120_ENABLE_EOS_INT 0x2 //$$ bit in nWrMode_Select
#define APCI3120_DISABLE_EOS_INT (~APCI3120_ENABLE_EOS_INT)
#define APCI3120_ENABLE_EOC_INT 0x1
#define APCI3120_DISABLE_EOC_INT (~APCI3120_ENABLE_EOC_INT)
#define APCI3120_DISABLE_ALL_INTERRUPT_WITHOUT_TIMER (APCI3120_DISABLE_EOS_INT & APCI3120_DISABLE_EOC_INT)
#define APCI3120_DISABLE_ALL_INTERRUPT (APCI3120_DISABLE_TIMER_INT & APCI3120_DISABLE_EOS_INT & APCI3120_DISABLE_EOC_INT)
//status register bits
#define APCI3120_EOC 0x8000
#define APCI3120_EOS 0x2000
// software trigger dummy register
#define APCI3120_START_CONVERSION 0x02 //(ADDRESS)
//TIMER DEFINE
#define APCI3120_QUARTZ_A 70
#define APCI3120_QUARTZ_B 50
#define APCI3120_TIMER 1
#define APCI3120_WATCHDOG 2
#define APCI3120_TIMER_DISABLE 0
#define APCI3120_TIMER_ENABLE 1
#define APCI3120_ENABLE_TIMER2 0x4000 //$$ gatebit 2 in nWrAddress
#define APCI3120_DISABLE_TIMER2 (~APCI3120_ENABLE_TIMER2)
#define APCI3120_ENABLE_TIMER_INT 0x04 //$$ ENAIRQ_FC_Bit in nWrModeSelect
#define APCI3120_DISABLE_TIMER_INT (~APCI3120_ENABLE_TIMER_INT)
#define APCI3120_WRITE_MODE_SELECT 0x0E // (ADDRESS)
#define APCI3120_SELECT_TIMER_0_WORD 0x00
#define APCI3120_SELECT_TIMER_1_WORD 0x01
#define APCI3120_TIMER_1_MODE_2 0x4
//$$ BIT FOR MODE IN nCsTimerCtr1
#define APCI3120_TIMER_2_MODE_0 0x0
#define APCI3120_TIMER_2_MODE_2 0x10
#define APCI3120_TIMER_2_MODE_5 0x30
//$$ BIT FOR MODE IN nCsTimerCtr0
#define APCI3120_SELECT_TIMER_2_LOW_WORD 0x02
#define APCI3120_SELECT_TIMER_2_HIGH_WORD 0x03
#define APCI3120_TIMER_CRT0 0x0D //(ADDRESS for cCsTimerCtr0)
#define APCI3120_TIMER_CRT1 0x0C //(ADDRESS for cCsTimerCtr1)
#define APCI3120_TIMER_VALUE 0x04 //ADDRESS for nCsTimerWert
#define APCI3120_TIMER_STATUS_REGISTER 0x0D //ADDRESS for delete timer 2 interrupt
#define APCI3120_RD_STATUS 0x02 //ADDRESS
#define APCI3120_WR_ADDRESS 0x00 //ADDRESS
#define APCI3120_ENABLE_WATCHDOG 0x20 //$$BIT in nWrMode_Select
#define APCI3120_DISABLE_WATCHDOG (~APCI3120_ENABLE_WATCHDOG)
#define APCI3120_ENABLE_TIMER_COUNTER 0x10 //$$BIT in nWrMode_Select
#define APCI3120_DISABLE_TIMER_COUNTER (~APCI3120_ENABLE_TIMER_COUNTER)
#define APCI3120_FC_TIMER 0x1000 //bit in status register
#define APCI3120_ENABLE_TIMER0 0x1000
#define APCI3120_ENABLE_TIMER1 0x2000
#define APCI3120_ENABLE_TIMER2 0x4000
#define APCI3120_DISABLE_TIMER0 (~APCI3120_ENABLE_TIMER0)
#define APCI3120_DISABLE_TIMER1 (~APCI3120_ENABLE_TIMER1)
#define APCI3120_DISABLE_TIMER2 (~APCI3120_ENABLE_TIMER2)
#define APCI3120_TIMER2_SELECT_EOS 0xC0 // ADDED on 20-6
#define APCI3120_COUNTER 3 // on 20-6
#define APCI3120_DISABLE_ALL_TIMER ( APCI3120_DISABLE_TIMER0 & APCI3120_DISABLE_TIMER1 & APCI3120_DISABLE_TIMER2 ) // on 20-6
#define MAX_ANALOGINPUT_CHANNELS 32
typedef struct {
BYTE b_Type; /* EOC or EOS */
BYTE b_InterruptFlag; /* Interrupt use or not */
UINT ui_ConvertTiming; /* Selection of the convertion time */
BYTE b_NbrOfChannel; /* Number of channel to read */
UINT ui_ChannelList[MAX_ANALOGINPUT_CHANNELS]; /* Number of the channel to be read */
UINT ui_RangeList[MAX_ANALOGINPUT_CHANNELS]; /* Gain of each channel */
} str_AnalogReadInformation;
// Function Declaration For APCI-3120
// Internal functions
int i_APCI3120_SetupChannelList(struct comedi_device *dev, struct comedi_subdevice *s,
int n_chan, unsigned int *chanlist, char check);
int i_APCI3120_ExttrigEnable(struct comedi_device *dev);
int i_APCI3120_ExttrigDisable(struct comedi_device *dev);
int i_APCI3120_StopCyclicAcquisition(struct comedi_device *dev, struct comedi_subdevice *s);
int i_APCI3120_Reset(struct comedi_device *dev);
int i_APCI3120_CyclicAnalogInput(int mode, struct comedi_device *dev,
struct comedi_subdevice *s);
// Interrupt functions
void v_APCI3120_Interrupt(int irq, void *d);
//UPDATE-0.7.57->0.7.68 void v_APCI3120_InterruptDmaMoveBlock16bit(struct comedi_device *dev,struct comedi_subdevice *s,short *dma,short *data,int n);
void v_APCI3120_InterruptDmaMoveBlock16bit(struct comedi_device *dev,
struct comedi_subdevice *s,
short *dma_buffer,
unsigned int num_samples);
int i_APCI3120_InterruptHandleEos(struct comedi_device *dev);
void v_APCI3120_InterruptDma(int irq, void *d);
// TIMER
int i_APCI3120_InsnConfigTimer(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
int i_APCI3120_InsnWriteTimer(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
int i_APCI3120_InsnReadTimer(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
//DI
// for di read
int i_APCI3120_InsnBitsDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
int i_APCI3120_InsnReadDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
//DO
//int i_APCI3120_WriteDigitalOutput(struct comedi_device *dev, BYTE data);
int i_APCI3120_InsnConfigDigitalOutput(struct comedi_device *dev,
struct comedi_subdevice *s, struct comedi_insn *insn,
unsigned int *data);
int i_APCI3120_InsnBitsDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
int i_APCI3120_InsnWriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
//AO
//int i_APCI3120_Write1AnalogValue(struct comedi_device *dev,UINT ui_Range,UINT ui_Channel,UINT data );
int i_APCI3120_InsnWriteAnalogOutput(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
//AI HArdware layer
int i_APCI3120_InsnConfigAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
int i_APCI3120_InsnReadAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
int i_APCI3120_CommandTestAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_cmd *cmd);
int i_APCI3120_CommandAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s);
//int i_APCI3120_CancelAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s);
int i_APCI3120_StopCyclicAcquisition(struct comedi_device *dev, struct comedi_subdevice *s);

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,187 @@
/*
* Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
*
* ADDI-DATA GmbH
* Dieselstrasse 3
* D-77833 Ottersweier
* Tel: +19(0)7223/9493-0
* Fax: +49(0)7223/9493-92
* http://www.addi-data-com
* info@addi-data.com
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*/
// Card Specific information
#define APCI3200_BOARD_VENDOR_ID 0x15B8
//#define APCI3200_ADDRESS_RANGE 264
int MODULE_NO;
struct {
INT i_Gain;
INT i_Polarity;
INT i_OffsetRange;
INT i_Coupling;
INT i_SingleDiff;
INT i_AutoCalibration;
UINT ui_ReloadValue;
UINT ui_TimeUnitReloadVal;
INT i_Interrupt;
INT i_ModuleSelection;
} Config_Parameters_Module1, Config_Parameters_Module2,
Config_Parameters_Module3, Config_Parameters_Module4;
//ANALOG INPUT RANGE
static const struct comedi_lrange range_apci3200_ai = { 8, {
BIP_RANGE(10),
BIP_RANGE(5),
BIP_RANGE(2),
BIP_RANGE(1),
UNI_RANGE(10),
UNI_RANGE(5),
UNI_RANGE(2),
UNI_RANGE(1)
}
};
static const struct comedi_lrange range_apci3300_ai = { 4, {
UNI_RANGE(10),
UNI_RANGE(5),
UNI_RANGE(2),
UNI_RANGE(1)
}
};
//Analog Input related Defines
#define APCI3200_AI_OFFSET_GAIN 0
#define APCI3200_AI_SC_TEST 4
#define APCI3200_AI_IRQ 8
#define APCI3200_AI_AUTOCAL 12
#define APCI3200_RELOAD_CONV_TIME_VAL 32
#define APCI3200_CONV_TIME_TIME_BASE 36
#define APCI3200_RELOAD_DELAY_TIME_VAL 40
#define APCI3200_DELAY_TIME_TIME_BASE 44
#define APCI3200_AI_MODULE1 0
#define APCI3200_AI_MODULE2 64
#define APCI3200_AI_MODULE3 128
#define APCI3200_AI_MODULE4 192
#define TRUE 1
#define FALSE 0
#define APCI3200_AI_EOSIRQ 16
#define APCI3200_AI_EOS 20
#define APCI3200_AI_CHAN_ID 24
#define APCI3200_AI_CHAN_VAL 28
#define ANALOG_INPUT 0
#define TEMPERATURE 1
#define RESISTANCE 2
#define ENABLE_EXT_TRIG 1
#define ENABLE_EXT_GATE 2
#define ENABLE_EXT_TRIG_GATE 3
#define APCI3200_MAXVOLT 2.5
#define ADDIDATA_GREATER_THAN_TEST 0
#define ADDIDATA_LESS_THAN_TEST 1
#define ADDIDATA_UNIPOLAR 1
#define ADDIDATA_BIPOLAR 2
//BEGIN JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
#define MAX_MODULE 4
//END JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
typedef struct {
ULONG ul_NumberOfValue;
ULONG *pul_ResistanceValue;
ULONG *pul_TemperatureValue;
} str_ADDIDATA_RTDStruct, *pstr_ADDIDATA_RTDStruct;
//BEGIN JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
typedef struct {
// Begin JK 05/08/2003 change for Linux
unsigned long ul_CurrentSourceCJC;
unsigned long ul_CurrentSource[5];
// End JK 05/08/2003 change for Linux
// Begin CG 15/02/02 Rev 1.0 -> Rev 1.1 : Add Header Type 1
unsigned long ul_GainFactor[8]; // Gain Factor
unsigned int w_GainValue[10];
// End CG 15/02/02 Rev 1.0 -> Rev 1.1 : Add Header Type 1
} str_Module;
//END JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
//BEGIN JK 06.07.04: Management of sevrals boards
typedef struct {
INT i_CJCAvailable;
INT i_CJCPolarity;
INT i_CJCGain;
INT i_InterruptFlag;
INT i_ADDIDATAPolarity;
INT i_ADDIDATAGain;
INT i_AutoCalibration;
INT i_ADDIDATAConversionTime;
INT i_ADDIDATAConversionTimeUnit;
INT i_ADDIDATAType;
INT i_ChannelNo;
INT i_ChannelCount;
INT i_ScanType;
INT i_FirstChannel;
INT i_LastChannel;
INT i_Sum;
INT i_Offset;
UINT ui_Channel_num;
INT i_Count;
INT i_Initialised;
//UINT ui_InterruptChannelValue[96]; //Buffer
UINT ui_InterruptChannelValue[144]; //Buffer
BYTE b_StructInitialized;
//Begin JK 19.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68
unsigned int ui_ScanValueArray[7 + 12]; // 7 is the maximal number of channels
//End JK 19.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68
//Begin JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
INT i_ConnectionType;
INT i_NbrOfModule;
str_Module s_Module[MAX_MODULE];
//End JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
} str_BoardInfos;
//END JK 06.07.04: Management of sevrals boards
// Hardware Layer functions for Apci3200
//AI
INT i_APCI3200_ConfigAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
INT i_APCI3200_ReadAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
INT i_APCI3200_InsnWriteReleaseAnalogInput(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
INT i_APCI3200_InsnBits_AnalogInput_Test(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
INT i_APCI3200_StopCyclicAcquisition(struct comedi_device *dev, struct comedi_subdevice *s);
INT i_APCI3200_InterruptHandleEos(struct comedi_device *dev);
INT i_APCI3200_CommandTestAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_cmd *cmd);
INT i_APCI3200_CommandAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s);
INT i_APCI3200_ReadDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
//Interrupt
void v_APCI3200_Interrupt(int irq, void *d);
int i_APCI3200_InterruptHandleEos(struct comedi_device *dev);
//Reset functions
INT i_APCI3200_Reset(struct comedi_device *dev);
int i_APCI3200_ReadCJCCalOffset(struct comedi_device *dev, unsigned int *data);
int i_APCI3200_ReadCJCValue(struct comedi_device *dev, unsigned int *data);
int i_APCI3200_ReadCalibrationGainValue(struct comedi_device *dev, UINT *data);
int i_APCI3200_ReadCalibrationOffsetValue(struct comedi_device *dev, UINT *data);
int i_APCI3200_Read1AnalogInputChannel(struct comedi_device *dev,
struct comedi_subdevice *s, struct comedi_insn *insn,
unsigned int *data);
int i_APCI3200_ReadCJCCalGain(struct comedi_device *dev, unsigned int *data);

View file

@ -0,0 +1,742 @@
/**
@verbatim
Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
ADDI-DATA GmbH
Dieselstrasse 3
D-77833 Ottersweier
Tel: +19(0)7223/9493-0
Fax: +49(0)7223/9493-92
http://www.addi-data-com
info@addi-data.com
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
You shoud also find the complete GPL in the COPYING file accompanying this source code.
@endverbatim
*/
/*.
+-----------------------------------------------------------------------+
| (C) ADDI-DATA GmbH Dieselstraße 3 D-77833 Ottersweier |
+-----------------------------------------------------------------------+
| Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com |
| Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com |
+-------------------------------+---------------------------------------+
| Project : APCI-3501 | Compiler : GCC |
| Module name : hwdrv_apci3501.c| Version : 2.96 |
+-------------------------------+---------------------------------------+
| Project manager: Eric Stolz | Date : 02/12/2002 |
+-------------------------------+---------------------------------------+
| Description : Hardware Layer Acces For APCI-3501 |
+-----------------------------------------------------------------------+
| UPDATES |
+----------+-----------+------------------------------------------------+
| Date | Author | Description of updates |
+----------+-----------+------------------------------------------------+
| | | |
| | | |
| | | |
+----------+-----------+------------------------------------------------+
*/
/*
+----------------------------------------------------------------------------+
| Included files |
+----------------------------------------------------------------------------+
*/
#include "hwdrv_apci3501.h"
/*
+----------------------------------------------------------------------------+
| Function Name : int i_APCI3501_ReadDigitalInput |
| (struct comedi_device *dev,struct comedi_subdevice *s, |
| struct comedi_insn *insn,unsigned int *data) |
+----------------------------------------------------------------------------+
| Task : Read value of the selected channel or port |
+----------------------------------------------------------------------------+
| Input Parameters : struct comedi_device *dev : Driver handle |
| UINT ui_NoOfChannels : No Of Channels To read |
| UINT *data : Data Pointer to read status |
+----------------------------------------------------------------------------+
| Output Parameters : -- |
+----------------------------------------------------------------------------+
| Return Value : TRUE : No error occur |
| : FALSE : Error occur. Return the error |
| |
+----------------------------------------------------------------------------+
*/
INT i_APCI3501_ReadDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
struct comedi_insn * insn, unsigned int * data)
{
UINT ui_Temp;
UINT ui_NoOfChannel;
ui_NoOfChannel = CR_CHAN(insn->chanspec);
ui_Temp = data[0];
*data = inl(devpriv->iobase + APCI3501_DIGITAL_IP);
if (ui_Temp == 0) {
*data = (*data >> ui_NoOfChannel) & 0x1;
} //if (ui_Temp==0)
else {
if (ui_Temp == 1) {
*data = *data & 0x3;
} //if (ui_Temp==1)
else {
printk("\nSpecified channel not supported \n");
} //elseif (ui_Temp==1)
} //elseif (ui_Temp==0)
return insn->n;
}
/*
+----------------------------------------------------------------------------+
| Function Name : int i_APCI3501_ConfigDigitalOutput |
| (struct comedi_device *dev,struct comedi_subdevice *s, |
| struct comedi_insn *insn,unsigned int *data) |
+----------------------------------------------------------------------------+
| Task : Configures The Digital Output Subdevice. |
+----------------------------------------------------------------------------+
| Input Parameters : struct comedi_device *dev : Driver handle |
| UINT *data : Data Pointer contains |
| configuration parameters as below |
| |
| data[1] : 1 Enable VCC Interrupt |
| 0 Disable VCC Interrupt |
| data[2] : 1 Enable CC Interrupt |
| 0 Disable CC Interrupt |
| |
+----------------------------------------------------------------------------+
| Output Parameters : -- |
+----------------------------------------------------------------------------+
| Return Value : TRUE : No error occur |
| : FALSE : Error occur. Return the error |
| |
+----------------------------------------------------------------------------+
*/
int i_APCI3501_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
struct comedi_insn * insn, unsigned int * data)
{
if ((data[0] != 0) && (data[0] != 1)) {
comedi_error(dev,
"Not a valid Data !!! ,Data should be 1 or 0\n");
return -EINVAL;
} //if ( (data[0]!=0) && (data[0]!=1) )
if (data[0]) {
devpriv->b_OutputMemoryStatus = ADDIDATA_ENABLE;
} // if (data[0])
else {
devpriv->b_OutputMemoryStatus = ADDIDATA_DISABLE;
} //else if (data[0])
return insn->n;
}
/*
+----------------------------------------------------------------------------+
| Function Name : int i_APCI3501_WriteDigitalOutput |
| (struct comedi_device *dev,struct comedi_subdevice *s, |
| struct comedi_insn *insn,unsigned int *data) |
+----------------------------------------------------------------------------+
| Task : writes To the digital Output Subdevice |
+----------------------------------------------------------------------------+
| Input Parameters : struct comedi_device *dev : Driver handle |
| struct comedi_subdevice *s : Subdevice Pointer |
| struct comedi_insn *insn : Insn Structure Pointer |
| unsigned int *data : Data Pointer contains |
| configuration parameters as below |
| |
+----------------------------------------------------------------------------+
| Output Parameters : -- |
+----------------------------------------------------------------------------+
| Return Value : TRUE : No error occur |
| : FALSE : Error occur. Return the error |
| |
+----------------------------------------------------------------------------+
*/
INT i_APCI3501_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
struct comedi_insn * insn, unsigned int * data)
{
UINT ui_Temp, ui_Temp1;
UINT ui_NoOfChannel = CR_CHAN(insn->chanspec); // get the channel
if (devpriv->b_OutputMemoryStatus) {
ui_Temp = inl(devpriv->iobase + APCI3501_DIGITAL_OP);
} //if(devpriv->b_OutputMemoryStatus )
else {
ui_Temp = 0;
} //if(devpriv->b_OutputMemoryStatus )
if (data[3] == 0) {
if (data[1] == 0) {
data[0] = (data[0] << ui_NoOfChannel) | ui_Temp;
outl(data[0], devpriv->iobase + APCI3501_DIGITAL_OP);
} //if(data[1]==0)
else {
if (data[1] == 1) {
data[0] = (data[0] << (2 * data[2])) | ui_Temp;
outl(data[0],
devpriv->iobase + APCI3501_DIGITAL_OP);
} // if(data[1]==1)
else {
printk("\nSpecified channel not supported\n");
} //else if(data[1]==1)
} //elseif(data[1]==0)
} //if(data[3]==0)
else {
if (data[3] == 1) {
if (data[1] == 0) {
data[0] = ~data[0] & 0x1;
ui_Temp1 = 1;
ui_Temp1 = ui_Temp1 << ui_NoOfChannel;
ui_Temp = ui_Temp | ui_Temp1;
data[0] =
(data[0] << ui_NoOfChannel) ^
0xffffffff;
data[0] = data[0] & ui_Temp;
outl(data[0],
devpriv->iobase + APCI3501_DIGITAL_OP);
} //if(data[1]==0)
else {
if (data[1] == 1) {
data[0] = ~data[0] & 0x3;
ui_Temp1 = 3;
ui_Temp1 = ui_Temp1 << 2 * data[2];
ui_Temp = ui_Temp | ui_Temp1;
data[0] =
((data[0] << (2 *
data[2])) ^
0xffffffff) & ui_Temp;
outl(data[0],
devpriv->iobase +
APCI3501_DIGITAL_OP);
} // if(data[1]==1)
else {
printk("\nSpecified channel not supported\n");
} //else if(data[1]==1)
} //elseif(data[1]==0)
} //if(data[3]==1);
else {
printk("\nSpecified functionality does not exist\n");
return -EINVAL;
} //if else data[3]==1)
} //if else data[3]==0)
return insn->n;
}
/*
+----------------------------------------------------------------------------+
| Function Name : int i_APCI3501_ReadDigitalOutput |
| (struct comedi_device *dev,struct comedi_subdevice *s, |
| struct comedi_insn *insn,unsigned int *data) |
+----------------------------------------------------------------------------+
| Task : Read value of the selected channel or port |
+----------------------------------------------------------------------------+
| Input Parameters : struct comedi_device *dev : Driver handle |
| UINT ui_NoOfChannels : No Of Channels To read |
| UINT *data : Data Pointer to read status |
+----------------------------------------------------------------------------+
| Output Parameters : -- |
+----------------------------------------------------------------------------+
| Return Value : TRUE : No error occur |
| : FALSE : Error occur. Return the error |
| |
+----------------------------------------------------------------------------+
*/
INT i_APCI3501_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
struct comedi_insn * insn, unsigned int * data)
{
UINT ui_Temp;
UINT ui_NoOfChannel;
ui_NoOfChannel = CR_CHAN(insn->chanspec);
ui_Temp = data[0];
*data = inl(devpriv->iobase + APCI3501_DIGITAL_OP);
if (ui_Temp == 0) {
*data = (*data >> ui_NoOfChannel) & 0x1;
} // if (ui_Temp==0)
else {
if (ui_Temp == 1) {
*data = *data & 0x3;
} // if (ui_Temp==1)
else {
printk("\nSpecified channel not supported \n");
} // else if (ui_Temp==1)
} // else if (ui_Temp==0)
return insn->n;
}
/*
+----------------------------------------------------------------------------+
| Function Name : int i_APCI3501_ConfigAnalogOutput |
| (struct comedi_device *dev,struct comedi_subdevice *s, |
| struct comedi_insn *insn,unsigned int *data) |
+----------------------------------------------------------------------------+
| Task : Configures The Analog Output Subdevice |
+----------------------------------------------------------------------------+
| Input Parameters : struct comedi_device *dev : Driver handle |
| struct comedi_subdevice *s : Subdevice Pointer |
| struct comedi_insn *insn : Insn Structure Pointer |
| unsigned int *data : Data Pointer contains |
| configuration parameters as below |
| |
| data[0] : Voltage Mode |
| 0:Mode 0 |
| 1:Mode 1 |
| |
+----------------------------------------------------------------------------+
| Output Parameters : -- |
+----------------------------------------------------------------------------+
| Return Value : TRUE : No error occur |
| : FALSE : Error occur. Return the error |
| |
+----------------------------------------------------------------------------+
*/
INT i_APCI3501_ConfigAnalogOutput(struct comedi_device * dev, struct comedi_subdevice * s,
struct comedi_insn * insn, unsigned int * data)
{
outl(data[0],
devpriv->iobase + APCI3501_ANALOG_OUTPUT +
APCI3501_AO_VOLT_MODE);
if (data[0]) {
devpriv->b_InterruptMode = MODE1;
} else {
devpriv->b_InterruptMode = MODE0;
}
return insn->n;
}
/*
+----------------------------------------------------------------------------+
| Function Name : int i_APCI3501_WriteAnalogOutput |
| (struct comedi_device *dev,struct comedi_subdevice *s, |
| struct comedi_insn *insn,unsigned int *data) |
+----------------------------------------------------------------------------+
| Task : Writes To the Selected Anlog Output Channel |
+----------------------------------------------------------------------------+
| Input Parameters : struct comedi_device *dev : Driver handle |
| struct comedi_subdevice *s : Subdevice Pointer |
| struct comedi_insn *insn : Insn Structure Pointer |
| unsigned int *data : Data Pointer contains |
| configuration parameters as below |
| |
| |
+----------------------------------------------------------------------------+
| Output Parameters : -- |
+----------------------------------------------------------------------------+
| Return Value : TRUE : No error occur |
| : FALSE : Error occur. Return the error |
| |
+----------------------------------------------------------------------------+
*/
INT i_APCI3501_WriteAnalogOutput(struct comedi_device * dev, struct comedi_subdevice * s,
struct comedi_insn * insn, unsigned int * data)
{
ULONG ul_Command1 = 0, ul_Channel_no, ul_Polarity, ul_DAC_Ready = 0;;
ul_Channel_no = CR_CHAN(insn->chanspec);
if (devpriv->b_InterruptMode == MODE1) {
ul_Polarity = 0x80000000;
if ((*data < 0) || (*data > 16384)) {
printk("\nIn WriteAnalogOutput :: Not Valid Data\n");
}
} // end if(devpriv->b_InterruptMode==MODE1)
else {
ul_Polarity = 0;
if ((*data < 0) || (*data > 8192)) {
printk("\nIn WriteAnalogOutput :: Not Valid Data\n");
}
} // end else
if ((ul_Channel_no < 0) || (ul_Channel_no > 7)) {
printk("\nIn WriteAnalogOutput :: Not Valid Channel\n");
} // end if((ul_Channel_no<0)||(ul_Channel_no>7))
ul_DAC_Ready = inl(devpriv->iobase + APCI3501_ANALOG_OUTPUT);
while (ul_DAC_Ready == 0) {
ul_DAC_Ready = inl(devpriv->iobase + APCI3501_ANALOG_OUTPUT);
ul_DAC_Ready = (ul_DAC_Ready >> 8) & 1;
}
if (ul_DAC_Ready) {
// Output the Value on the output channels.
ul_Command1 =
(ULONG) ((ULONG) (ul_Channel_no & 0xFF) |
(ULONG) ((*data << 0x8) & 0x7FFFFF00L) |
(ULONG) (ul_Polarity));
outl(ul_Command1,
devpriv->iobase + APCI3501_ANALOG_OUTPUT +
APCI3501_AO_PROG);
}
return insn->n;
}
/*
+----------------------------------------------------------------------------+
| Function Name : int i_APCI3501_ConfigTimerCounterWatchdog |
| (struct comedi_device *dev,struct comedi_subdevice *s, |
| struct comedi_insn *insn,unsigned int *data) |
+----------------------------------------------------------------------------+
| Task : Configures The Timer , Counter or Watchdog |
+----------------------------------------------------------------------------+
| Input Parameters : struct comedi_device *dev : Driver handle |
| UINT *data : Data Pointer contains |
| configuration parameters as below |
| |
| data[0] : 0 Configure As Timer |
| 1 Configure As Counter |
| 2 Configure As Watchdog |
| data[1] : 1 Enable Interrupt |
| 0 Disable Interrupt |
| data[2] : Time Unit |
| data[3] : Reload Value |
+----------------------------------------------------------------------------+
| Output Parameters : -- |
+----------------------------------------------------------------------------+
| Return Value : TRUE : No error occur |
| : FALSE : Error occur. Return the error |
| |
+----------------------------------------------------------------------------+
*/
INT i_APCI3501_ConfigTimerCounterWatchdog(struct comedi_device * dev,
struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
{
ULONG ul_Command1 = 0;
devpriv->tsk_Current = current;
if (data[0] == ADDIDATA_WATCHDOG) {
devpriv->b_TimerSelectMode = ADDIDATA_WATCHDOG;
//Disable the watchdog
outl(0x0, devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG); //disable Wa
if (data[1] == 1) {
//Enable TIMER int & DISABLE ALL THE OTHER int SOURCES
outl(0x02,
devpriv->iobase + APCI3501_WATCHDOG +
APCI3501_TCW_PROG);
} else {
outl(0x0, devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG); //disable Timer interrupt
}
//Loading the Timebase value
outl(data[2],
devpriv->iobase + APCI3501_WATCHDOG +
APCI3501_TCW_TIMEBASE);
//Loading the Reload value
outl(data[3],
devpriv->iobase + APCI3501_WATCHDOG +
APCI3501_TCW_RELOAD_VALUE);
//Set the mode
ul_Command1 = inl(devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG) | 0xFFF819E0UL; //e2->e0
outl(ul_Command1,
devpriv->iobase + APCI3501_WATCHDOG +
APCI3501_TCW_PROG);
} //end if(data[0]==ADDIDATA_WATCHDOG)
else if (data[0] == ADDIDATA_TIMER) {
//First Stop The Timer
ul_Command1 =
inl(devpriv->iobase + APCI3501_WATCHDOG +
APCI3501_TCW_PROG);
ul_Command1 = ul_Command1 & 0xFFFFF9FEUL;
outl(ul_Command1, devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG); //Stop The Timer
devpriv->b_TimerSelectMode = ADDIDATA_TIMER;
if (data[1] == 1) {
//Enable TIMER int & DISABLE ALL THE OTHER int SOURCES
outl(0x02,
devpriv->iobase + APCI3501_WATCHDOG +
APCI3501_TCW_PROG);
} else {
outl(0x0, devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG); //disable Timer interrupt
}
// Loading Timebase
outl(data[2],
devpriv->iobase + APCI3501_WATCHDOG +
APCI3501_TCW_TIMEBASE);
//Loading the Reload value
outl(data[3],
devpriv->iobase + APCI3501_WATCHDOG +
APCI3501_TCW_RELOAD_VALUE);
// printk ("\nTimer Address :: %x\n", (devpriv->iobase+APCI3501_WATCHDOG));
ul_Command1 =
inl(devpriv->iobase + APCI3501_WATCHDOG +
APCI3501_TCW_PROG);
ul_Command1 =
(ul_Command1 & 0xFFF719E2UL) | 2UL << 13UL | 0x10UL;
outl(ul_Command1, devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG); //mode 2
} //end if(data[0]==ADDIDATA_TIMER)
return insn->n;
}
/*
+----------------------------------------------------------------------------+
| Function Name : int i_APCI3501_StartStopWriteTimerCounterWatchdog |
| (struct comedi_device *dev,struct comedi_subdevice *s, |
| struct comedi_insn *insn,unsigned int *data) |
+----------------------------------------------------------------------------+
| Task : Start / Stop The Selected Timer , Counter or Watchdog |
+----------------------------------------------------------------------------+
| Input Parameters : struct comedi_device *dev : Driver handle |
| UINT *data : Data Pointer contains |
| configuration parameters as below |
| |
| data[0] : 0 Timer |
| 1 Counter |
| 2 Watchdog | | data[1] : 1 Start |
| 0 Stop | 2 Trigger |
+----------------------------------------------------------------------------+
| Output Parameters : -- |
+----------------------------------------------------------------------------+
| Return Value : TRUE : No error occur |
| : FALSE : Error occur. Return the error |
| |
+----------------------------------------------------------------------------+
*/
int i_APCI3501_StartStopWriteTimerCounterWatchdog(struct comedi_device * dev,
struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
{
ULONG ul_Command1 = 0;
int i_Temp;
if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) {
if (data[1] == 1) {
ul_Command1 =
inl(devpriv->iobase + APCI3501_WATCHDOG +
APCI3501_TCW_PROG);
ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x1UL;
//Enable the Watchdog
outl(ul_Command1,
devpriv->iobase + APCI3501_WATCHDOG +
APCI3501_TCW_PROG);
}
else if (data[1] == 0) //Stop The Watchdog
{
//Stop The Watchdog
ul_Command1 =
inl(devpriv->iobase + APCI3501_WATCHDOG +
APCI3501_TCW_PROG);
ul_Command1 = ul_Command1 & 0xFFFFF9FEUL;
outl(0x0,
devpriv->iobase + APCI3501_WATCHDOG +
APCI3501_TCW_PROG);
} else if (data[1] == 2) {
ul_Command1 =
inl(devpriv->iobase + APCI3501_WATCHDOG +
APCI3501_TCW_PROG);
ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x200UL;
outl(ul_Command1,
devpriv->iobase + APCI3501_WATCHDOG +
APCI3501_TCW_PROG);
} //if(data[1]==2)
} // end if (devpriv->b_TimerSelectMode==ADDIDATA_WATCHDOG)
if (devpriv->b_TimerSelectMode == ADDIDATA_TIMER) {
if (data[1] == 1) {
ul_Command1 =
inl(devpriv->iobase + APCI3501_WATCHDOG +
APCI3501_TCW_PROG);
ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x1UL;
//Enable the Timer
outl(ul_Command1,
devpriv->iobase + APCI3501_WATCHDOG +
APCI3501_TCW_PROG);
} else if (data[1] == 0) {
//Stop The Timer
ul_Command1 =
inl(devpriv->iobase + APCI3501_WATCHDOG +
APCI3501_TCW_PROG);
ul_Command1 = ul_Command1 & 0xFFFFF9FEUL;
outl(ul_Command1,
devpriv->iobase + APCI3501_WATCHDOG +
APCI3501_TCW_PROG);
}
else if (data[1] == 2) {
//Trigger the Timer
ul_Command1 =
inl(devpriv->iobase + APCI3501_WATCHDOG +
APCI3501_TCW_PROG);
ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x200UL;
outl(ul_Command1,
devpriv->iobase + APCI3501_WATCHDOG +
APCI3501_TCW_PROG);
}
} // end if (devpriv->b_TimerSelectMode==ADDIDATA_TIMER)
i_Temp = inl(devpriv->iobase + APCI3501_WATCHDOG +
APCI3501_TCW_TRIG_STATUS) & 0x1;
return insn->n;
}
/*
+----------------------------------------------------------------------------+
| Function Name : int i_APCI3501_ReadTimerCounterWatchdog |
| (struct comedi_device *dev,struct comedi_subdevice *s, |
| struct comedi_insn *insn,unsigned int *data) |
+----------------------------------------------------------------------------+
| Task : Read The Selected Timer , Counter or Watchdog |
+----------------------------------------------------------------------------+
| Input Parameters : struct comedi_device *dev : Driver handle |
| UINT *data : Data Pointer contains |
| configuration parameters as below |
| |
| data[0] : 0 Timer |
| 1 Counter |
| 2 Watchdog | | data[1] : Timer Counter Watchdog Number |
+----------------------------------------------------------------------------+
| Output Parameters : -- |
+----------------------------------------------------------------------------+
| Return Value : TRUE : No error occur |
| : FALSE : Error occur. Return the error |
| |
+----------------------------------------------------------------------------+
*/
int i_APCI3501_ReadTimerCounterWatchdog(struct comedi_device * dev,
struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
{
if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) {
data[0] =
inl(devpriv->iobase + APCI3501_WATCHDOG +
APCI3501_TCW_TRIG_STATUS) & 0x1;
data[1] = inl(devpriv->iobase + APCI3501_WATCHDOG);
} // end if (devpriv->b_TimerSelectMode==ADDIDATA_WATCHDOG)
else if (devpriv->b_TimerSelectMode == ADDIDATA_TIMER) {
data[0] =
inl(devpriv->iobase + APCI3501_WATCHDOG +
APCI3501_TCW_TRIG_STATUS) & 0x1;
data[1] = inl(devpriv->iobase + APCI3501_WATCHDOG);
} // end if (devpriv->b_TimerSelectMode==ADDIDATA_TIMER)
else if ((devpriv->b_TimerSelectMode != ADDIDATA_TIMER)
&& (devpriv->b_TimerSelectMode != ADDIDATA_WATCHDOG)) {
printk("\nIn ReadTimerCounterWatchdog :: Invalid Subdevice \n");
}
return insn->n;
}
/*
+----------------------------------------------------------------------------+
| Function Name : int i_APCI3501_Reset(struct comedi_device *dev) |
| |
+----------------------------------------------------------------------------+
| Task :Resets the registers of the card |
+----------------------------------------------------------------------------+
| Input Parameters : |
+----------------------------------------------------------------------------+
| Output Parameters : -- |
+----------------------------------------------------------------------------+
| Return Value : |
| |
+----------------------------------------------------------------------------+
*/
int i_APCI3501_Reset(struct comedi_device * dev)
{
int i_Count = 0, i_temp = 0;
ULONG ul_Command1 = 0, ul_Polarity, ul_DAC_Ready = 0;
outl(0x0, devpriv->iobase + APCI3501_DIGITAL_OP);
outl(1, devpriv->iobase + APCI3501_ANALOG_OUTPUT +
APCI3501_AO_VOLT_MODE);
ul_Polarity = 0x80000000;
for (i_Count = 0; i_Count <= 7; i_Count++) {
ul_DAC_Ready = inl(devpriv->iobase + APCI3501_ANALOG_OUTPUT);
while (ul_DAC_Ready == 0) {
ul_DAC_Ready =
inl(devpriv->iobase + APCI3501_ANALOG_OUTPUT);
ul_DAC_Ready = (ul_DAC_Ready >> 8) & 1;
}
if (ul_DAC_Ready) {
// Output the Value on the output channels.
ul_Command1 =
(ULONG) ((ULONG) (i_Count & 0xFF) |
(ULONG) ((i_temp << 0x8) & 0x7FFFFF00L) |
(ULONG) (ul_Polarity));
outl(ul_Command1,
devpriv->iobase + APCI3501_ANALOG_OUTPUT +
APCI3501_AO_PROG);
}
}
return 0;
}
/*
+----------------------------------------------------------------------------+
| Function Name : static void v_APCI3501_Interrupt |
| (int irq , void *d) |
+----------------------------------------------------------------------------+
| Task : Interrupt processing Routine |
+----------------------------------------------------------------------------+
| Input Parameters : int irq : irq number |
| void *d : void pointer |
+----------------------------------------------------------------------------+
| Output Parameters : -- |
+----------------------------------------------------------------------------+
| Return Value : TRUE : No error occur |
| : FALSE : Error occur. Return the error |
| |
+----------------------------------------------------------------------------+
*/
void v_APCI3501_Interrupt(int irq, void *d)
{
int i_temp;
struct comedi_device *dev = d;
unsigned int ui_Timer_AOWatchdog;
unsigned long ul_Command1;
// Disable Interrupt
ul_Command1 =
inl(devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG);
ul_Command1 = (ul_Command1 & 0xFFFFF9FDul);
outl(ul_Command1,
devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG);
ui_Timer_AOWatchdog =
inl(devpriv->iobase + APCI3501_WATCHDOG +
APCI3501_TCW_IRQ) & 0x1;
if ((!ui_Timer_AOWatchdog)) {
comedi_error(dev, "IRQ from unknow source");
return;
}
// Enable Interrupt
//Send a signal to from kernel to user space
send_sig(SIGIO, devpriv->tsk_Current, 0);
ul_Command1 =
inl(devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG);
ul_Command1 = ((ul_Command1 & 0xFFFFF9FDul) | 1 << 1);
outl(ul_Command1,
devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG);
i_temp = inl(devpriv->iobase + APCI3501_WATCHDOG +
APCI3501_TCW_TRIG_STATUS) & 0x1;
return;
}

View file

@ -0,0 +1,94 @@
/*
* Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
*
* ADDI-DATA GmbH
* Dieselstrasse 3
* D-77833 Ottersweier
* Tel: +19(0)7223/9493-0
* Fax: +49(0)7223/9493-92
* http://www.addi-data-com
* info@addi-data.com
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*/
// Card Specific information
#define APCI3501_BOARD_VENDOR_ID 0x15B8
#define APCI3501_ADDRESS_RANGE 255
#define APCI3501_DIGITAL_IP 0x50
#define APCI3501_DIGITAL_OP 0x40
#define APCI3501_ANALOG_OUTPUT 0x00
//Analog Output related Defines
#define APCI3501_AO_VOLT_MODE 0
#define APCI3501_AO_PROG 4
#define APCI3501_AO_TRIG_SCS 8
#define UNIPOLAR 0
#define BIPOLAR 1
#define MODE0 0
#define MODE1 1
// ANALOG OUTPUT RANGE
struct comedi_lrange range_apci3501_ao = { 2, {
BIP_RANGE(10),
UNI_RANGE(10)
}
};
//Watchdog Related Defines
#define APCI3501_WATCHDOG 0x20
#define APCI3501_TCW_SYNC_ENABLEDISABLE 0
#define APCI3501_TCW_RELOAD_VALUE 4
#define APCI3501_TCW_TIMEBASE 8
#define APCI3501_TCW_PROG 12
#define APCI3501_TCW_TRIG_STATUS 16
#define APCI3501_TCW_IRQ 20
#define APCI3501_TCW_WARN_TIMEVAL 24
#define APCI3501_TCW_WARN_TIMEBASE 28
#define ADDIDATA_TIMER 0
#define ADDIDATA_WATCHDOG 2
// Hardware Layer functions for Apci3501
//AO
INT i_APCI3501_ConfigAnalogOutput(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
INT i_APCI3501_WriteAnalogOutput(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
//DI
// for di read
//INT i_APCI3501_ReadDigitalInput(struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data);
INT i_APCI3501_ReadDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
//DO
int i_APCI3501_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
INT i_APCI3501_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
INT i_APCI3501_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
// TIMER
// timer value is passed as u seconds
INT i_APCI3501_ConfigTimerCounterWatchdog(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
int i_APCI3501_StartStopWriteTimerCounterWatchdog(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data);
int i_APCI3501_ReadTimerCounterWatchdog(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
//Interrupt
void v_APCI3501_Interrupt(int irq, void *d);
//Reset functions
int i_APCI3501_Reset(struct comedi_device *dev);

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,62 @@
/*
* Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
*
* ADDI-DATA GmbH
* Dieselstrasse 3
* D-77833 Ottersweier
* Tel: +19(0)7223/9493-0
* Fax: +49(0)7223/9493-92
* http://www.addi-data-com
* info@addi-data.com
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*/
#ifndef COMEDI_SUBD_TTLIO
#define COMEDI_SUBD_TTLIO 11 /* Digital Input Output But TTL */
#endif
#ifndef ADDIDATA_ENABLE
#define ADDIDATA_ENABLE 1
#define ADDIDATA_DISABLE 0
#endif
#define APCI3XXX_SINGLE 0
#define APCI3XXX_DIFF 1
#define APCI3XXX_CONFIGURATION 0
#define APCI3XXX_TTL_INIT_DIRECTION_PORT2 0
#ifdef __KERNEL__
static const struct comedi_lrange range_apci3XXX_ai = { 8, {BIP_RANGE(10),
BIP_RANGE(5),
BIP_RANGE(2),
BIP_RANGE(1),
UNI_RANGE(10),
UNI_RANGE(5),
UNI_RANGE(2),
UNI_RANGE(1)}
};
static const struct comedi_lrange range_apci3XXX_ttl = { 12, {BIP_RANGE(1),
BIP_RANGE(1),
BIP_RANGE(1),
BIP_RANGE(1),
BIP_RANGE(1),
BIP_RANGE(1),
BIP_RANGE(1),
BIP_RANGE(1),
BIP_RANGE(1),
BIP_RANGE(1),
BIP_RANGE(1),
BIP_RANGE(1)}
};
static const struct comedi_lrange range_apci3XXX_ao = { 2, {BIP_RANGE(10),
UNI_RANGE(10)}
};
#endif

View file

@ -0,0 +1,5 @@
#define CONFIG_APCI_035 1
#define ADDIDATA_WATCHDOG 2 // Or shold it be something else
#include "addi-data/addi_common.c"

View file

@ -0,0 +1,3 @@
#define CONFIG_APCI_1032 1
#include "addi-data/addi_common.c"

View file

@ -0,0 +1,3 @@
#define CONFIG_APCI_1500 1
#include "addi-data/addi_common.c"

View file

@ -0,0 +1,3 @@
#define CONFIG_APCI_1516 1
#include "addi-data/addi_common.c"

View file

@ -0,0 +1,3 @@
#define CONFIG_APCI_1564 1
#include "addi-data/addi_common.c"

View file

@ -0,0 +1,3 @@
#define CONFIG_APCI_16XX 1
#include "addi-data/addi_common.c"

View file

@ -0,0 +1,3 @@
#define CONFIG_APCI_1710 1
#include "addi-data/addi_common.c"

Some files were not shown because too many files have changed in this diff Show more