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:
commit
3516c6a8dc
|
@ -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.
|
|
@ -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).
|
|
@ -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
|
|
@ -73,6 +73,8 @@ source "drivers/staging/rt2860/Kconfig"
|
||||||
|
|
||||||
source "drivers/staging/rt2870/Kconfig"
|
source "drivers/staging/rt2870/Kconfig"
|
||||||
|
|
||||||
|
source "drivers/staging/rt3070/Kconfig"
|
||||||
|
|
||||||
source "drivers/staging/comedi/Kconfig"
|
source "drivers/staging/comedi/Kconfig"
|
||||||
|
|
||||||
source "drivers/staging/asus_oled/Kconfig"
|
source "drivers/staging/asus_oled/Kconfig"
|
||||||
|
@ -93,5 +95,25 @@ source "drivers/staging/epl/Kconfig"
|
||||||
|
|
||||||
source "drivers/staging/android/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_EXCLUDE_BUILD
|
||||||
endif # STAGING
|
endif # STAGING
|
||||||
|
|
|
@ -19,6 +19,7 @@ obj-$(CONFIG_AGNX) += agnx/
|
||||||
obj-$(CONFIG_OTUS) += otus/
|
obj-$(CONFIG_OTUS) += otus/
|
||||||
obj-$(CONFIG_RT2860) += rt2860/
|
obj-$(CONFIG_RT2860) += rt2860/
|
||||||
obj-$(CONFIG_RT2870) += rt2870/
|
obj-$(CONFIG_RT2870) += rt2870/
|
||||||
|
obj-$(CONFIG_RT3070) += rt3070/
|
||||||
obj-$(CONFIG_COMEDI) += comedi/
|
obj-$(CONFIG_COMEDI) += comedi/
|
||||||
obj-$(CONFIG_ASUS_OLED) += asus_oled/
|
obj-$(CONFIG_ASUS_OLED) += asus_oled/
|
||||||
obj-$(CONFIG_PANEL) += panel/
|
obj-$(CONFIG_PANEL) += panel/
|
||||||
|
@ -29,3 +30,13 @@ obj-$(CONFIG_INPUT_MIMIO) += mimio/
|
||||||
obj-$(CONFIG_TRANZPORT) += frontier/
|
obj-$(CONFIG_TRANZPORT) += frontier/
|
||||||
obj-$(CONFIG_EPL) += epl/
|
obj-$(CONFIG_EPL) += epl/
|
||||||
obj-$(CONFIG_ANDROID) += android/
|
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/
|
||||||
|
|
|
@ -41,16 +41,16 @@ static const struct ieee80211_rate agnx_rates_80211g[] = {
|
||||||
/* { .bitrate = 20, .hw_value = 2, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, */
|
/* { .bitrate = 20, .hw_value = 2, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, */
|
||||||
/* { .bitrate = 55, .hw_value = 3, .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 = 110, .hw_value = 4, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, */
|
||||||
{ .bitrate = 10, .hw_value = 1, },
|
{ .bitrate = 10, .hw_value = 1, },
|
||||||
{ .bitrate = 20, .hw_value = 2, },
|
{ .bitrate = 20, .hw_value = 2, },
|
||||||
{ .bitrate = 55, .hw_value = 3, },
|
{ .bitrate = 55, .hw_value = 3, },
|
||||||
{ .bitrate = 110, .hw_value = 4,},
|
{ .bitrate = 110, .hw_value = 4,},
|
||||||
|
|
||||||
{ .bitrate = 60, .hw_value = 0xB, },
|
{ .bitrate = 60, .hw_value = 0xB, },
|
||||||
{ .bitrate = 90, .hw_value = 0xF, },
|
{ .bitrate = 90, .hw_value = 0xF, },
|
||||||
{ .bitrate = 120, .hw_value = 0xA },
|
{ .bitrate = 120, .hw_value = 0xA },
|
||||||
{ .bitrate = 180, .hw_value = 0xE, },
|
{ .bitrate = 180, .hw_value = 0xE, },
|
||||||
// { .bitrate = 240, .hw_value = 0xd, },
|
/* { .bitrate = 240, .hw_value = 0xd, }, */
|
||||||
{ .bitrate = 360, .hw_value = 0xD, },
|
{ .bitrate = 360, .hw_value = 0xD, },
|
||||||
{ .bitrate = 480, .hw_value = 0x8, },
|
{ .bitrate = 480, .hw_value = 0x8, },
|
||||||
{ .bitrate = 540, .hw_value = 0xC, },
|
{ .bitrate = 540, .hw_value = 0xC, },
|
||||||
|
@ -110,10 +110,10 @@ struct agnx_priv {
|
||||||
/* Need volatile? */
|
/* Need volatile? */
|
||||||
u32 irq_status;
|
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;
|
struct ieee80211_low_level_stats stats;
|
||||||
|
|
||||||
// unsigned int phymode;
|
/* unsigned int phymode; */
|
||||||
int mode;
|
int mode;
|
||||||
int channel;
|
int channel;
|
||||||
u8 bssid[ETH_ALEN];
|
u8 bssid[ETH_ALEN];
|
||||||
|
|
|
@ -23,7 +23,7 @@ static inline void agnx_bug(char *reason)
|
||||||
|
|
||||||
static inline void agnx_print_desc(struct agnx_desc *desc)
|
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);
|
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_high);
|
||||||
PRINTK_LE32(STA, sta->phy_stats_low);
|
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);
|
agnx_print_sta_traffic(sta->traffic + 0);
|
||||||
|
|
||||||
PRINTK_LE16(STA, sta->traffic_class0_frag_success);
|
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)
|
static inline void dump_ieee80211_hdr(struct ieee80211_hdr *hdr, char *tag)
|
||||||
{
|
{
|
||||||
u16 fctl;
|
u16 fctl;
|
||||||
int hdrlen;
|
int hdrlen;
|
||||||
DECLARE_MAC_BUF(mac);
|
DECLARE_MAC_BUF(mac);
|
||||||
|
|
||||||
fctl = le16_to_cpu(hdr->frame_control);
|
fctl = le16_to_cpu(hdr->frame_control);
|
||||||
switch (fctl & IEEE80211_FCTL_FTYPE) {
|
switch (fctl & IEEE80211_FCTL_FTYPE) {
|
||||||
case IEEE80211_FTYPE_DATA:
|
case IEEE80211_FTYPE_DATA:
|
||||||
printk(PFX "%s DATA ", tag);
|
printk(PFX "%s DATA ", tag);
|
||||||
|
@ -324,7 +324,7 @@ static inline void dump_ieee80211_hdr(struct ieee80211_hdr *hdr, char *tag)
|
||||||
break;
|
break;
|
||||||
case IEEE80211_FTYPE_MGMT:
|
case IEEE80211_FTYPE_MGMT:
|
||||||
printk(PFX "%s MGMT ", tag);
|
printk(PFX "%s MGMT ", tag);
|
||||||
switch(fctl & IEEE80211_FCTL_STYPE) {
|
switch (fctl & IEEE80211_FCTL_STYPE) {
|
||||||
case IEEE80211_STYPE_ASSOC_REQ:
|
case IEEE80211_STYPE_ASSOC_REQ:
|
||||||
printk("SubType: ASSOC_REQ ");
|
printk("SubType: ASSOC_REQ ");
|
||||||
break;
|
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);
|
printk(PFX "%s Packet type: Unknow\n", tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
hdrlen = ieee80211_hdrlen(fctl);
|
hdrlen = ieee80211_hdrlen(fctl);
|
||||||
|
|
||||||
if (hdrlen >= 4)
|
if (hdrlen >= 4)
|
||||||
printk("FC=0x%04x DUR=0x%04x",
|
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;
|
void __iomem *ctl = priv->ctl;
|
||||||
int i;
|
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));
|
printk(KERN_DEBUG PFX "TXM: %x---> 0x%.8x\n", i, ioread32(ctl + i));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
static inline void dump_rxm_registers(struct agnx_priv *priv)
|
static inline void dump_rxm_registers(struct agnx_priv *priv)
|
||||||
{
|
{
|
||||||
void __iomem *ctl = priv->ctl;
|
void __iomem *ctl = priv->ctl;
|
||||||
int i;
|
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));
|
printk(KERN_DEBUG PFX "RXM: %x---> 0x%.8x\n", i, ioread32(ctl + 0x2000 + i));
|
||||||
}
|
}
|
||||||
static inline void dump_bm_registers(struct agnx_priv *priv)
|
static inline void dump_bm_registers(struct agnx_priv *priv)
|
||||||
{
|
{
|
||||||
void __iomem *ctl = priv->ctl;
|
void __iomem *ctl = priv->ctl;
|
||||||
int i;
|
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));
|
printk(KERN_DEBUG PFX "BM: %x---> 0x%.8x\n", i, ioread32(ctl + 0x2c00 + i));
|
||||||
}
|
}
|
||||||
static inline void dump_cir_registers(struct agnx_priv *priv)
|
static inline void dump_cir_registers(struct agnx_priv *priv)
|
||||||
{
|
{
|
||||||
void __iomem *ctl = priv->ctl;
|
void __iomem *ctl = priv->ctl;
|
||||||
int i;
|
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));
|
printk(KERN_DEBUG PFX "CIR: %x---> 0x%.8x\n", i, ioread32(ctl + 0x3000 + i));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,34 +39,34 @@ static inline void agnx_interrupt_ack(struct agnx_priv *priv, u32 *reason)
|
||||||
void __iomem *ctl = priv->ctl;
|
void __iomem *ctl = priv->ctl;
|
||||||
u32 reg;
|
u32 reg;
|
||||||
|
|
||||||
if ( *reason & AGNX_STAT_RX ) {
|
if (*reason & AGNX_STAT_RX) {
|
||||||
/* Mark complete RX */
|
/* Mark complete RX */
|
||||||
reg = ioread32(ctl + AGNX_CIR_RXCTL);
|
reg = ioread32(ctl + AGNX_CIR_RXCTL);
|
||||||
reg |= 0x4;
|
reg |= 0x4;
|
||||||
iowrite32(reg, ctl + AGNX_CIR_RXCTL);
|
iowrite32(reg, ctl + AGNX_CIR_RXCTL);
|
||||||
/* disable Rx interrupt */
|
/* disable Rx interrupt */
|
||||||
}
|
}
|
||||||
if ( *reason & AGNX_STAT_TX ) {
|
if (*reason & AGNX_STAT_TX) {
|
||||||
reg = ioread32(ctl + AGNX_CIR_TXDCTL);
|
reg = ioread32(ctl + AGNX_CIR_TXDCTL);
|
||||||
if (reg & 0x4) {
|
if (reg & 0x4) {
|
||||||
iowrite32(reg, ctl + AGNX_CIR_TXDCTL);
|
iowrite32(reg, ctl + AGNX_CIR_TXDCTL);
|
||||||
*reason |= AGNX_STAT_TXD;
|
*reason |= AGNX_STAT_TXD;
|
||||||
}
|
}
|
||||||
reg = ioread32(ctl + AGNX_CIR_TXMCTL);
|
reg = ioread32(ctl + AGNX_CIR_TXMCTL);
|
||||||
if (reg & 0x4) {
|
if (reg & 0x4) {
|
||||||
iowrite32(reg, ctl + AGNX_CIR_TXMCTL);
|
iowrite32(reg, ctl + AGNX_CIR_TXMCTL);
|
||||||
*reason |= AGNX_STAT_TXM;
|
*reason |= AGNX_STAT_TXM;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( *reason & AGNX_STAT_X ) {
|
/* if (*reason & AGNX_STAT_X) {
|
||||||
/* reg = ioread32(ctl + AGNX_INT_STAT); */
|
reg = ioread32(ctl + AGNX_INT_STAT);
|
||||||
/* iowrite32(reg, ctl + AGNX_INT_STAT); */
|
iowrite32(reg, ctl + AGNX_INT_STAT);
|
||||||
/* /\* FIXME reinit interrupt mask *\/ */
|
/* FIXME reinit interrupt mask *\/
|
||||||
/* reg = 0xc390bf9 & ~IRQ_TX_BEACON; */
|
reg = 0xc390bf9 & ~IRQ_TX_BEACON;
|
||||||
/* reg &= ~IRQ_TX_DISABLE; */
|
reg &= ~IRQ_TX_DISABLE;
|
||||||
/* iowrite32(reg, ctl + AGNX_INT_MASK); */
|
iowrite32(reg, ctl + AGNX_INT_MASK);
|
||||||
/* iowrite32(0x800, ctl + AGNX_CIR_BLKCTL); */
|
iowrite32(0x800, ctl + AGNX_CIR_BLKCTL);
|
||||||
}
|
} */
|
||||||
} /* agnx_interrupt_ack */
|
} /* agnx_interrupt_ack */
|
||||||
|
|
||||||
static irqreturn_t agnx_interrupt_handler(int irq, void *dev_id)
|
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);
|
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)
|
if (priv->init_status != AGNX_START)
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -92,7 +92,7 @@ static irqreturn_t agnx_interrupt_handler(int irq, void *dev_id)
|
||||||
ret = IRQ_HANDLED;
|
ret = IRQ_HANDLED;
|
||||||
priv->irq_status = ioread32(ctl + AGNX_INT_STAT);
|
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
|
/* Make sure the txm and txd flags don't conflict with other unknown
|
||||||
interrupt flag, maybe is not necessary */
|
interrupt flag, maybe is not necessary */
|
||||||
irq_reason &= 0xF;
|
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 */
|
/* TODO Make sure the card finished initialized */
|
||||||
agnx_interrupt_ack(priv, &irq_reason);
|
agnx_interrupt_ack(priv, &irq_reason);
|
||||||
|
|
||||||
if ( irq_reason & AGNX_STAT_RX )
|
if (irq_reason & AGNX_STAT_RX)
|
||||||
handle_rx_irq(priv);
|
handle_rx_irq(priv);
|
||||||
if ( irq_reason & AGNX_STAT_TXD )
|
if (irq_reason & AGNX_STAT_TXD)
|
||||||
handle_txd_irq(priv);
|
handle_txd_irq(priv);
|
||||||
if ( irq_reason & AGNX_STAT_TXM )
|
if (irq_reason & AGNX_STAT_TXM)
|
||||||
handle_txm_irq(priv);
|
handle_txm_irq(priv);
|
||||||
if ( irq_reason & AGNX_STAT_X )
|
if (irq_reason & AGNX_STAT_X)
|
||||||
handle_other_irq(priv);
|
handle_other_irq(priv);
|
||||||
|
|
||||||
enable_rx_interrupt(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;
|
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);
|
priv->rx.info = kzalloc(sizeof(struct agnx_info) * len, GFP_ATOMIC);
|
||||||
if (!priv->rx.info)
|
if (!priv->rx.info)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
@ -210,28 +210,27 @@ static void rings_free(struct agnx_priv *priv)
|
||||||
#if 0
|
#if 0
|
||||||
static void agnx_periodic_work_handler(struct work_struct *work)
|
static void agnx_periodic_work_handler(struct work_struct *work)
|
||||||
{
|
{
|
||||||
struct agnx_priv *priv = container_of(work, struct agnx_priv,
|
struct agnx_priv *priv = container_of(work, struct agnx_priv, periodic_work.work);
|
||||||
periodic_work.work);
|
/* unsigned long flags; */
|
||||||
// unsigned long flags;
|
|
||||||
unsigned long delay;
|
unsigned long delay;
|
||||||
|
|
||||||
/* fixme: using mutex?? */
|
/* fixme: using mutex?? */
|
||||||
// spin_lock_irqsave(&priv->lock, flags);
|
/* spin_lock_irqsave(&priv->lock, flags); */
|
||||||
|
|
||||||
/* TODO Recalibrate*/
|
/* TODO Recalibrate*/
|
||||||
// calibrate_oscillator(priv);
|
/* calibrate_oscillator(priv); */
|
||||||
// antenna_calibrate(priv);
|
/* antenna_calibrate(priv); */
|
||||||
// agnx_send_packet(priv, 997);
|
/* agnx_send_packet(priv, 997); /
|
||||||
/* FIXME */
|
/* FIXME */
|
||||||
/* if (debug == 3) */
|
/* if (debug == 3) */
|
||||||
/* delay = msecs_to_jiffies(AGNX_PERIODIC_DELAY); */
|
/* delay = msecs_to_jiffies(AGNX_PERIODIC_DELAY); */
|
||||||
/* else */
|
/* else */
|
||||||
delay = msecs_to_jiffies(AGNX_PERIODIC_DELAY);
|
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);
|
queue_delayed_work(priv->hw->workqueue, &priv->periodic_work, delay);
|
||||||
|
|
||||||
// spin_unlock_irqrestore(&priv->lock, flags);
|
/* spin_unlock_irqrestore(&priv->lock, flags); */
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -255,12 +254,12 @@ static int agnx_start(struct ieee80211_hw *dev)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
// mdelay(500);
|
/* mdelay(500); */
|
||||||
|
|
||||||
might_sleep();
|
might_sleep();
|
||||||
agnx_hw_init(priv);
|
agnx_hw_init(priv);
|
||||||
|
|
||||||
// mdelay(500);
|
/* mdelay(500); */
|
||||||
might_sleep();
|
might_sleep();
|
||||||
|
|
||||||
priv->init_status = AGNX_START;
|
priv->init_status = AGNX_START;
|
||||||
|
@ -280,16 +279,16 @@ static void agnx_stop(struct ieee80211_hw *dev)
|
||||||
/* make sure hardware will not generate irq */
|
/* make sure hardware will not generate irq */
|
||||||
agnx_hw_reset(priv);
|
agnx_hw_reset(priv);
|
||||||
free_irq(priv->pdev->irq, dev);
|
free_irq(priv->pdev->irq, dev);
|
||||||
flush_workqueue(priv->hw->workqueue);
|
flush_workqueue(priv->hw->workqueue);
|
||||||
// cancel_delayed_work_sync(&priv->periodic_work);
|
/* cancel_delayed_work_sync(&priv->periodic_work); */
|
||||||
unfill_rings(priv);
|
unfill_rings(priv);
|
||||||
rings_free(priv);
|
rings_free(priv);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int agnx_config(struct ieee80211_hw *dev,
|
static int agnx_config(struct ieee80211_hw *dev, u32 changed)
|
||||||
struct ieee80211_conf *conf)
|
|
||||||
{
|
{
|
||||||
struct agnx_priv *priv = dev->priv;
|
struct agnx_priv *priv = dev->priv;
|
||||||
|
struct ieee80211_conf *conf = &dev->conf;
|
||||||
int channel = ieee80211_frequency_to_channel(conf->channel->center_freq);
|
int channel = ieee80211_frequency_to_channel(conf->channel->center_freq);
|
||||||
AGNX_TRACE;
|
AGNX_TRACE;
|
||||||
|
|
||||||
|
@ -315,7 +314,6 @@ static int agnx_config_interface(struct ieee80211_hw *dev,
|
||||||
spin_lock(&priv->lock);
|
spin_lock(&priv->lock);
|
||||||
|
|
||||||
if (memcmp(conf->bssid, priv->bssid, ETH_ALEN)) {
|
if (memcmp(conf->bssid, priv->bssid, ETH_ALEN)) {
|
||||||
// u32 reghi, reglo;
|
|
||||||
agnx_set_bssid(priv, conf->bssid);
|
agnx_set_bssid(priv, conf->bssid);
|
||||||
memcpy(priv->bssid, conf->bssid, ETH_ALEN);
|
memcpy(priv->bssid, conf->bssid, ETH_ALEN);
|
||||||
hash_write(priv, conf->bssid, BSSID_STAID);
|
hash_write(priv, conf->bssid, BSSID_STAID);
|
||||||
|
@ -425,7 +423,7 @@ static struct ieee80211_ops agnx_ops = {
|
||||||
.remove_interface = agnx_remove_interface,
|
.remove_interface = agnx_remove_interface,
|
||||||
.config = agnx_config,
|
.config = agnx_config,
|
||||||
.config_interface = agnx_config_interface,
|
.config_interface = agnx_config_interface,
|
||||||
.configure_filter = agnx_configure_filter,
|
.configure_filter = agnx_configure_filter,
|
||||||
.get_stats = agnx_get_stats,
|
.get_stats = agnx_get_stats,
|
||||||
.get_tx_stats = agnx_get_tx_stats,
|
.get_tx_stats = agnx_get_tx_stats,
|
||||||
.get_tsf = agnx_get_tsft
|
.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)
|
static void __devexit agnx_pci_remove(struct pci_dev *pdev)
|
||||||
{
|
{
|
||||||
struct ieee80211_hw *dev = pci_get_drvdata(pdev);
|
struct ieee80211_hw *dev = pci_get_drvdata(pdev);
|
||||||
struct agnx_priv *priv = dev->priv;
|
struct agnx_priv *priv;
|
||||||
AGNX_TRACE;
|
AGNX_TRACE;
|
||||||
|
|
||||||
if (!dev)
|
if (!dev)
|
||||||
return;
|
return;
|
||||||
|
priv = dev->priv;
|
||||||
ieee80211_unregister_hw(dev);
|
ieee80211_unregister_hw(dev);
|
||||||
pci_iounmap(pdev, priv->ctl);
|
pci_iounmap(pdev, priv->ctl);
|
||||||
pci_iounmap(pdev, priv->data);
|
pci_iounmap(pdev, priv->data);
|
||||||
|
@ -504,7 +503,7 @@ static int __devinit agnx_pci_probe(struct pci_dev *pdev,
|
||||||
|
|
||||||
/* Map mem #1 and #2 */
|
/* Map mem #1 and #2 */
|
||||||
priv->ctl = pci_iomap(pdev, 0, mem_len0);
|
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) {
|
if (!priv->ctl) {
|
||||||
printk(KERN_ERR PFX "Can't map device memory\n");
|
printk(KERN_ERR PFX "Can't map device memory\n");
|
||||||
goto err_free_dev;
|
goto err_free_dev;
|
||||||
|
|
|
@ -114,7 +114,7 @@ static void mac_address_set(struct agnx_priv *priv)
|
||||||
/* FIXME */
|
/* FIXME */
|
||||||
reg = (mac_addr[0] << 24) | (mac_addr[1] << 16) | mac_addr[2] << 8 | mac_addr[3];
|
reg = (mac_addr[0] << 24) | (mac_addr[1] << 16) | mac_addr[2] << 8 | mac_addr[3];
|
||||||
iowrite32(reg, ctl + AGNX_RXM_MACHI);
|
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);
|
iowrite32(reg, ctl + AGNX_RXM_MACLO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,7 +127,7 @@ static void receiver_bssid_set(struct agnx_priv *priv, u8 *bssid)
|
||||||
/* FIXME */
|
/* FIXME */
|
||||||
reg = bssid[0] << 24 | (bssid[1] << 16) | (bssid[2] << 8) | bssid[3];
|
reg = bssid[0] << 24 | (bssid[1] << 16) | (bssid[2] << 8) | bssid[3];
|
||||||
iowrite32(reg, ctl + AGNX_RXM_BSSIDHI);
|
iowrite32(reg, ctl + AGNX_RXM_BSSIDHI);
|
||||||
reg = (bssid[4] << 8) | bssid[5];
|
reg = (bssid[4] << 8) | bssid[5];
|
||||||
iowrite32(reg, ctl + AGNX_RXM_BSSIDLO);
|
iowrite32(reg, ctl + AGNX_RXM_BSSIDLO);
|
||||||
|
|
||||||
/* Enable the receiver */
|
/* Enable the receiver */
|
||||||
|
@ -401,9 +401,9 @@ static void rx_management_init(struct agnx_priv *priv)
|
||||||
agnx_write32(ctl, 0x2074, 0x1f171710);
|
agnx_write32(ctl, 0x2074, 0x1f171710);
|
||||||
agnx_write32(ctl, 0x2078, 0x10100d0d);
|
agnx_write32(ctl, 0x2078, 0x10100d0d);
|
||||||
agnx_write32(ctl, 0x207c, 0x11111010);
|
agnx_write32(ctl, 0x207c, 0x11111010);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
agnx_write32(ctl, AGNX_RXM_DELAY11, 0x0);
|
agnx_write32(ctl, AGNX_RXM_DELAY11, 0x0);
|
||||||
|
}
|
||||||
agnx_write32(ctl, AGNX_RXM_REQRATE, 0x8195e00);
|
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
|
/* It seemed if we set other bit to 1 the bit 0 will
|
||||||
be auto change to 0 */
|
be auto change to 0 */
|
||||||
agnx_write32(ctl, AGNX_BM_TXTOPEER, 0x2 | 0x1);
|
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 */
|
} /* gain_ctlcnt_init */
|
||||||
|
|
||||||
|
|
||||||
|
@ -490,7 +490,7 @@ static void phy_init(struct agnx_priv *priv)
|
||||||
/* Load InitialGainTable */
|
/* Load InitialGainTable */
|
||||||
gain_table_init(priv);
|
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: */
|
/* Clear the following offsets in Memory Range #2: */
|
||||||
memset_io(data + 0x5040, 0, 0xa * 4);
|
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_SIFST11B, 0x28);
|
||||||
agnx_write32(ctl, AGNX_GCR_CWDETEC, 0x0);
|
agnx_write32(ctl, AGNX_GCR_CWDETEC, 0x0);
|
||||||
agnx_write32(ctl, AGNX_GCR_0X38, 0x1e);
|
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_DISCOVMOD, 0x3);
|
||||||
|
|
||||||
agnx_write32(ctl, AGNX_GCR_THCAP11A, 0x32);
|
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,
|
print_hex_dump_bytes(PFX "EEPROM: ", DUMP_PREFIX_NONE, eeprom,
|
||||||
ARRAY_SIZE(eeprom));
|
ARRAY_SIZE(eeprom));
|
||||||
} while(0);
|
} while (0);
|
||||||
|
|
||||||
spi_rc_write(ctl, RF_CHIP0, 0x26);
|
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 */
|
/* Initialize the system interface */
|
||||||
system_itf_init(priv);
|
system_itf_init(priv);
|
||||||
|
@ -874,19 +874,19 @@ static void card_interface_init(struct agnx_priv *priv)
|
||||||
/* FIXME Enable the request */
|
/* FIXME Enable the request */
|
||||||
/* Check packet length */
|
/* Check packet length */
|
||||||
/* Set maximum packet length */
|
/* Set maximum packet length */
|
||||||
/* agnx_write32(ctl, AGNX_RXM_REQRATE, 0x88195e00); */
|
/* agnx_write32(ctl, AGNX_RXM_REQRATE, 0x88195e00); */
|
||||||
/* enable_receiver(priv); */
|
/* enable_receiver(priv); */
|
||||||
|
|
||||||
/* Set the Receiver BSSID */
|
/* Set the Receiver BSSID */
|
||||||
receiver_bssid_set(priv, bssid);
|
receiver_bssid_set(priv, bssid);
|
||||||
|
|
||||||
/* FIXME Set to managed mode */
|
/* FIXME Set to managed mode */
|
||||||
set_managed_mode(priv);
|
set_managed_mode(priv);
|
||||||
// set_promiscuous_mode(priv);
|
/* set_promiscuous_mode(priv); */
|
||||||
/* set_scan_mode(priv); */
|
/* set_scan_mode(priv); */
|
||||||
/* set_learn_mode(priv); */
|
/* set_learn_mode(priv); */
|
||||||
// set_promis_and_managed(priv);
|
/* set_promis_and_managed(priv); */
|
||||||
// set_adhoc_mode(priv);
|
/* set_adhoc_mode(priv); */
|
||||||
|
|
||||||
/* Set the recieve request rate */
|
/* Set the recieve request rate */
|
||||||
/* Check packet length */
|
/* Check packet length */
|
||||||
|
|
|
@ -109,12 +109,12 @@ void rf_chips_init(struct agnx_priv *priv)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set SPI clock speed to 200NS */
|
/* Set SPI clock speed to 200NS */
|
||||||
reg = agnx_read32(ctl, AGNX_SPI_CFG);
|
reg = agnx_read32(ctl, AGNX_SPI_CFG);
|
||||||
reg &= ~0xF;
|
reg &= ~0xF;
|
||||||
reg |= 0x3;
|
reg |= 0x3;
|
||||||
agnx_write32(ctl, AGNX_SPI_CFG, reg);
|
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 = agnx_read32(ctl, AGNX_SPI_CFG);
|
||||||
reg &= ~0xF;
|
reg &= ~0xF;
|
||||||
reg |= 0x1;
|
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_THD0BTFEST, 70);
|
||||||
agnx_write32(ctl, AGNX_GCR_SIGHTH, 100);
|
agnx_write32(ctl, AGNX_GCR_SIGHTH, 100);
|
||||||
agnx_write32(ctl, AGNX_GCR_SIGLTH, 48);
|
agnx_write32(ctl, AGNX_GCR_SIGLTH, 48);
|
||||||
// agnx_write32(ctl, AGNX_GCR_SIGLTH, 16);
|
/* agnx_write32(ctl, AGNX_GCR_SIGLTH, 16); */
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printk(KERN_WARNING PFX "Unknow antenna number\n");
|
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)
|
if (reg == 0x4)
|
||||||
spi_rf_write(ctl, RF_CHIP0|RF_CHIP1, reg|0x1000);
|
spi_rf_write(ctl, RF_CHIP0|RF_CHIP1, reg|0x1000);
|
||||||
else if (reg != 0x0)
|
else if (reg != 0x0)
|
||||||
spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, reg|0x1000);
|
spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, reg|0x1000);
|
||||||
else {
|
else {
|
||||||
if (chain == 3 || chain == 6) {
|
if (chain == 3 || chain == 6) {
|
||||||
spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, reg|0x1000);
|
spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, reg|0x1000);
|
||||||
agnx_write32(ctl, AGNX_GCR_RXOVERIDE, 0x0);
|
agnx_write32(ctl, AGNX_GCR_RXOVERIDE, 0x0);
|
||||||
|
@ -634,8 +634,7 @@ static void chain_calibrate(struct agnx_priv *priv, struct chains *chains,
|
||||||
}
|
}
|
||||||
} /* chain_calibrate */
|
} /* chain_calibrate */
|
||||||
|
|
||||||
|
static inline void get_calibrete_value(struct agnx_priv *priv, struct chains *chains,
|
||||||
static void inline get_calibrete_value(struct agnx_priv *priv, struct chains *chains,
|
|
||||||
unsigned int num)
|
unsigned int num)
|
||||||
{
|
{
|
||||||
void __iomem *ctl = priv->ctl;
|
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 (num == 0 || num == 1 || num == 2) {
|
||||||
if ( 0 == chains[num].cali)
|
if (0 == chains[num].cali)
|
||||||
chains[num].cali = 0xff;
|
chains[num].cali = 0xff;
|
||||||
else
|
else
|
||||||
chains[num].cali--;
|
chains[num].cali--;
|
||||||
|
@ -669,7 +668,7 @@ static inline void calibra_delay(struct agnx_priv *priv)
|
||||||
unsigned int i = 100;
|
unsigned int i = 100;
|
||||||
|
|
||||||
wmb();
|
wmb();
|
||||||
while (i--) {
|
while (--i) {
|
||||||
reg = (ioread32(ctl + AGNX_ACI_STATUS));
|
reg = (ioread32(ctl + AGNX_ACI_STATUS));
|
||||||
if (reg == 0x4000)
|
if (reg == 0x4000)
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -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);
|
iowrite32(reglo, ctl + AGNX_RXM_HASH_CMD_LOW);
|
||||||
|
|
||||||
reghi = ioread32(ctl + AGNX_RXM_HASH_CMD_HIGH);
|
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);
|
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(reghi, ctl + AGNX_RXM_HASH_CMD_HIGH);
|
||||||
iowrite32(reglo, ctl + AGNX_RXM_HASH_CMD_LOW);
|
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))
|
if (!(reglo & 0x80000000))
|
||||||
printk(KERN_WARNING PFX "Update hash table failed\n");
|
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);
|
iowrite32(reglo, ctl + AGNX_RXM_HASH_CMD_LOW);
|
||||||
reghi = ioread32(ctl + AGNX_RXM_HASH_CMD_HIGH);
|
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);
|
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;
|
void __iomem *ctl = priv->ctl;
|
||||||
u32 reghi, reglo;
|
u32 reghi, reglo;
|
||||||
|
|
||||||
reglo = 0x0; /* dump command */
|
reglo = 0x40000000; /* status bit */
|
||||||
reglo|= 0x40000000; /* status bit */
|
|
||||||
iowrite32(reglo, ctl + AGNX_RXM_HASH_CMD_LOW);
|
iowrite32(reglo, ctl + AGNX_RXM_HASH_CMD_LOW);
|
||||||
iowrite32(sta_id << 16, ctl + AGNX_RXM_HASH_DUMP_DATA);
|
iowrite32(sta_id << 16, ctl + AGNX_RXM_HASH_DUMP_DATA);
|
||||||
|
|
||||||
udelay(80);
|
udelay(80);
|
||||||
|
|
||||||
reghi = ioread32(ctl + AGNX_RXM_HASH_CMD_HIGH);
|
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);
|
printk(PFX "hash cmd are : %.8x%.8x\n", reghi, reglo);
|
||||||
reghi = ioread32(ctl + AGNX_RXM_HASH_CMD_FLAG);
|
reghi = ioread32(ctl + AGNX_RXM_HASH_CMD_FLAG);
|
||||||
printk(PFX "hash flag is : %.8x\n", reghi);
|
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 get_sta_power(struct agnx_priv *priv, struct agnx_sta_power *power, unsigned int sta_idx)
|
||||||
{
|
{
|
||||||
void __iomem *ctl = priv->ctl;
|
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));
|
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;
|
void __iomem *ctl = priv->ctl;
|
||||||
/* FIXME 2. Write Template to offset + station number */
|
/* 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));
|
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;
|
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));
|
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_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, 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);
|
tx_wq.reg2 |= cpu_to_le32(reg);
|
||||||
|
|
||||||
/* Suppose all 8 traffic class are used */
|
/* 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(NEW_PACKET, NEW_PACKET_SHIFT, 1);
|
||||||
reg |= agnx_set_bits(TRAFFIC_VALID, TRAFFIC_VALID_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);
|
traffic->reg0 = cpu_to_le32(reg);
|
||||||
|
|
||||||
/* 3. setting RX Sequence Number to 4095 */
|
/* 3. setting RX Sequence Number to 4095 */
|
||||||
|
|
|
@ -16,7 +16,7 @@ struct agnx_hash_cmd {
|
||||||
#define PASS 0x00000001
|
#define PASS 0x00000001
|
||||||
#define PASS_SHIFT 1
|
#define PASS_SHIFT 1
|
||||||
__be32 cmdlo;
|
__be32 cmdlo;
|
||||||
}__attribute__((__packed__));
|
} __attribute__((__packed__));
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -80,7 +80,7 @@ void routing_table_init(struct agnx_priv *priv)
|
||||||
|
|
||||||
disable_receiver(priv);
|
disable_receiver(priv);
|
||||||
|
|
||||||
for ( type = 0; type < 0x3; type++ ) {
|
for (type = 0; type < 0x3; type++) {
|
||||||
for (subtype = 0; subtype < 0x10; subtype++) {
|
for (subtype = 0; subtype < 0x10; subtype++) {
|
||||||
/* 1. Set Routing table to R/W and to Return status on Read */
|
/* 1. Set Routing table to R/W and to Return status on Read */
|
||||||
reg = (type << ROUTAB_TYPE_SHIFT) |
|
reg = (type << ROUTAB_TYPE_SHIFT) |
|
||||||
|
@ -89,7 +89,7 @@ void routing_table_init(struct agnx_priv *priv)
|
||||||
if (type == ROUTAB_TYPE_DATA) {
|
if (type == ROUTAB_TYPE_DATA) {
|
||||||
/* NULL goes to RFP */
|
/* NULL goes to RFP */
|
||||||
if (subtype == ROUTAB_SUBTYPE_NULL)
|
if (subtype == ROUTAB_SUBTYPE_NULL)
|
||||||
// reg |= ROUTAB_ROUTE_RFP;
|
/* reg |= ROUTAB_ROUTE_RFP; */
|
||||||
reg |= ROUTAB_ROUTE_CPU;
|
reg |= ROUTAB_ROUTE_CPU;
|
||||||
/* QOS NULL goes to CPU */
|
/* QOS NULL goes to CPU */
|
||||||
else if (subtype == ROUTAB_SUBTYPE_QOSNULL)
|
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_QOSDATAPOLL) ||
|
||||||
(subtype == ROUTAB_SUBTYPE_QOSDATAACKPOLL))
|
(subtype == ROUTAB_SUBTYPE_QOSDATAACKPOLL))
|
||||||
reg |= ROUTAB_ROUTE_ENCRY;
|
reg |= ROUTAB_ROUTE_ENCRY;
|
||||||
// reg |= ROUTAB_ROUTE_CPU;
|
/* reg |= ROUTAB_ROUTE_CPU; */
|
||||||
/*Drop NULL and QOS NULL ack, poll and poll ack*/
|
/*Drop NULL and QOS NULL ack, poll and poll ack*/
|
||||||
else if ((subtype == ROUTAB_SUBTYPE_NULLACK) ||
|
else if ((subtype == ROUTAB_SUBTYPE_NULLACK) ||
|
||||||
(subtype == ROUTAB_SUBTYPE_QOSNULLACK) ||
|
(subtype == ROUTAB_SUBTYPE_QOSNULLACK) ||
|
||||||
|
@ -112,11 +112,11 @@ void routing_table_init(struct agnx_priv *priv)
|
||||||
(subtype == ROUTAB_SUBTYPE_QOSNULLPOLL) ||
|
(subtype == ROUTAB_SUBTYPE_QOSNULLPOLL) ||
|
||||||
(subtype == ROUTAB_SUBTYPE_NULLPOLLACK) ||
|
(subtype == ROUTAB_SUBTYPE_NULLPOLLACK) ||
|
||||||
(subtype == ROUTAB_SUBTYPE_QOSNULLPOLLACK))
|
(subtype == ROUTAB_SUBTYPE_QOSNULLPOLLACK))
|
||||||
// reg |= ROUTAB_ROUTE_DROP;
|
/* reg |= ROUTAB_ROUTE_DROP; */
|
||||||
reg |= ROUTAB_ROUTE_CPU;
|
reg |= ROUTAB_ROUTE_CPU;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
reg |= (ROUTAB_ROUTE_CPU);
|
reg |= (ROUTAB_ROUTE_CPU);
|
||||||
|
}
|
||||||
iowrite32(reg, ctl + AGNX_RXM_ROUTAB);
|
iowrite32(reg, ctl + AGNX_RXM_ROUTAB);
|
||||||
/* Check to verify that the status bit cleared */
|
/* Check to verify that the status bit cleared */
|
||||||
routing_table_delay();
|
routing_table_delay();
|
||||||
|
|
|
@ -17,8 +17,8 @@
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "phy.h"
|
#include "phy.h"
|
||||||
|
|
||||||
unsigned int rx_frame_cnt = 0;
|
unsigned int rx_frame_cnt;
|
||||||
//unsigned int local_tx_sent_cnt = 0;
|
/* unsigned int local_tx_sent_cnt = 0; */
|
||||||
|
|
||||||
static inline void disable_rx_engine(struct agnx_priv *priv)
|
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));
|
memset(stat, 0, sizeof(*stat));
|
||||||
/* RSSI */
|
/* RSSI */
|
||||||
rssi = (u8 *)&hdr->phy_stats_lo;
|
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 */
|
||||||
noise = ioread32(ctl + AGNX_GCR_NOISE0);
|
noise = ioread32(ctl + AGNX_GCR_NOISE0);
|
||||||
noise += ioread32(ctl + AGNX_GCR_NOISE1);
|
noise += ioread32(ctl + AGNX_GCR_NOISE1);
|
||||||
noise += ioread32(ctl + AGNX_GCR_NOISE2);
|
noise += ioread32(ctl + AGNX_GCR_NOISE2);
|
||||||
stat->noise = noise / 3;
|
stat->noise = noise / 3;
|
||||||
/* Signal quality */
|
/* Signal quality */
|
||||||
//snr = stat->ssi - stat->noise;
|
/* snr = stat->ssi - stat->noise; */
|
||||||
if (snr >=0 && snr < 40)
|
if (snr >= 0 && snr < 40)
|
||||||
stat->signal = 5 * snr / 2;
|
stat->signal = 5 * snr / 2;
|
||||||
else if (snr >= 40)
|
else if (snr >= 40)
|
||||||
stat->signal = 100;
|
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->band = IEEE80211_BAND_2GHZ;
|
||||||
stat->freq = agnx_channels[priv->channel - 1].center_freq;
|
stat->freq = agnx_channels[priv->channel - 1].center_freq;
|
||||||
// stat->antenna = 3;
|
/* stat->antenna = 3;
|
||||||
// stat->mactime = be32_to_cpu(hdr->time_stamp);
|
stat->mactime = be32_to_cpu(hdr->time_stamp);
|
||||||
// stat->channel = priv->channel;
|
stat->channel = priv->channel; */
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void combine_hdr_frag(struct ieee80211_hdr *ieeehdr,
|
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,
|
static inline int agnx_packet_check(struct agnx_priv *priv, struct agnx_hdr *agnxhdr,
|
||||||
unsigned packet_len)
|
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");
|
printk(PFX "RX: CRC check fail\n");
|
||||||
goto drop;
|
goto drop;
|
||||||
}
|
}
|
||||||
|
@ -320,7 +319,7 @@ void handle_rx_irq(struct agnx_priv *priv)
|
||||||
{
|
{
|
||||||
struct ieee80211_rx_status status;
|
struct ieee80211_rx_status status;
|
||||||
unsigned int len;
|
unsigned int len;
|
||||||
// AGNX_TRACE;
|
/* AGNX_TRACE; */
|
||||||
|
|
||||||
do {
|
do {
|
||||||
struct agnx_desc *desc;
|
struct agnx_desc *desc;
|
||||||
|
@ -341,54 +340,54 @@ void handle_rx_irq(struct agnx_priv *priv)
|
||||||
|
|
||||||
len = (frag & PACKET_LEN) >> PACKET_LEN_SHIFT;
|
len = (frag & PACKET_LEN) >> PACKET_LEN_SHIFT;
|
||||||
if (agnx_packet_check(priv, hdr, len) == -1) {
|
if (agnx_packet_check(priv, hdr, len) == -1) {
|
||||||
rx_desc_reusing(priv, i);
|
rx_desc_reusing(priv, i);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
skb_put(skb, len);
|
skb_put(skb, len);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
u16 fctl;
|
u16 fctl;
|
||||||
fctl = le16_to_cpu(((struct ieee80211_hdr *)hdr->mac_hdr)->frame_control);
|
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");
|
dump_ieee80211_hdr((struct ieee80211_hdr *)hdr->mac_hdr, "RX");
|
||||||
} while (0);
|
} while (0);
|
||||||
|
|
||||||
if (hdr->_11b0 && !hdr->_11g0) {
|
if (hdr->_11b0 && !hdr->_11g0) {
|
||||||
/* int j; */
|
/* int j;
|
||||||
/* u16 fctl = le16_to_cpu(((struct ieee80211_hdr *)hdr->mac_hdr) */
|
u16 fctl = le16_to_cpu(((struct ieee80211_hdr *)hdr->mac_hdr)
|
||||||
/* ->frame_control); */
|
->frame_control);
|
||||||
/* if ( (fctl & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) { */
|
if ( (fctl & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) {
|
||||||
/* agnx_print_rx_hdr(hdr); */
|
agnx_print_rx_hdr(hdr);
|
||||||
// agnx_print_sta(priv, BSSID_STAID);
|
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, j); */
|
agnx_print_sta_tx_wq(priv, BSSID_STAID, j);
|
||||||
/* } */
|
} */
|
||||||
|
|
||||||
get_rx_stats(priv, hdr, &status);
|
get_rx_stats(priv, hdr, &status);
|
||||||
skb_pull(skb, sizeof(*hdr));
|
skb_pull(skb, sizeof(*hdr));
|
||||||
combine_hdr_frag((struct ieee80211_hdr *)hdr->mac_hdr, skb);
|
combine_hdr_frag((struct ieee80211_hdr *)hdr->mac_hdr, skb);
|
||||||
} else if (!hdr->_11b0 && hdr->_11g0) {
|
} else if (!hdr->_11b0 && hdr->_11g0) {
|
||||||
// int j;
|
/* int j; */
|
||||||
agnx_print_rx_hdr(hdr);
|
agnx_print_rx_hdr(hdr);
|
||||||
agnx_print_sta(priv, BSSID_STAID);
|
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);
|
agnx_print_sta_tx_wq(priv, BSSID_STAID, 0);
|
||||||
|
|
||||||
print_hex_dump_bytes("agnx: RX_PACKET: ", DUMP_PREFIX_NONE,
|
print_hex_dump_bytes("agnx: RX_PACKET: ", DUMP_PREFIX_NONE,
|
||||||
skb->data, skb->len + 8);
|
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);
|
get_rx_stats(priv, hdr, &status);
|
||||||
skb_pull(skb, sizeof(*hdr));
|
skb_pull(skb, sizeof(*hdr));
|
||||||
combine_hdr_frag((struct ieee80211_hdr *)
|
combine_hdr_frag((struct ieee80211_hdr *)
|
||||||
((void *)&hdr->mac_hdr), skb);
|
((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
|
} else
|
||||||
agnx_bug("Unknown packets type");
|
agnx_bug("Unknown packets type");
|
||||||
ieee80211_rx_irqsafe(priv->hw, skb, &status);
|
ieee80211_rx_irqsafe(priv->hw, skb, &status);
|
||||||
rx_desc_reinit(priv, i);
|
rx_desc_reinit(priv, i);
|
||||||
|
|
||||||
} while ( priv->rx.idx++ );
|
} while (priv->rx.idx++);
|
||||||
} /* handle_rx_irq */
|
} /* handle_rx_irq */
|
||||||
|
|
||||||
static inline void handle_tx_irq(struct agnx_priv *priv, struct agnx_ring *ring)
|
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);
|
pci_unmap_single(priv->pdev, info->mapping, info->dma_len, PCI_DMA_TODEVICE);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
// int j;
|
/* int j; */
|
||||||
size_t len;
|
size_t len;
|
||||||
len = info->skb->len - sizeof(struct agnx_hdr) + info->hdr_len;
|
len = info->skb->len - sizeof(struct agnx_hdr) + info->hdr_len;
|
||||||
// if (len == 614) {
|
/* if (len == 614) { */
|
||||||
// agnx_print_desc(desc);
|
/* agnx_print_desc(desc); */
|
||||||
if (info->type == PACKET) {
|
if (info->type == PACKET) {
|
||||||
// agnx_print_tx_hdr((struct agnx_hdr *)info->skb->data);
|
/* agnx_print_tx_hdr((struct agnx_hdr *)info->skb->data); */
|
||||||
/* agnx_print_sta_power(priv, LOCAL_STAID); */
|
/* agnx_print_sta_power(priv, LOCAL_STAID); */
|
||||||
/* agnx_print_sta(priv, LOCAL_STAID); */
|
/* agnx_print_sta(priv, LOCAL_STAID); */
|
||||||
/* // for (j = 0; j < 8; j++) */
|
/* for (j = 0; j < 8; j++) */
|
||||||
/* agnx_print_sta_tx_wq(priv, LOCAL_STAID, 0); */
|
/* agnx_print_sta_tx_wq(priv, LOCAL_STAID, 0); */
|
||||||
// agnx_print_sta_power(priv, BSSID_STAID);
|
/* agnx_print_sta_power(priv, BSSID_STAID); */
|
||||||
// agnx_print_sta(priv, BSSID_STAID);
|
/* 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);
|
/* agnx_print_sta_tx_wq(priv, BSSID_STAID, 0); */
|
||||||
}
|
}
|
||||||
// }
|
/* } */
|
||||||
} while (0);
|
} while (0);
|
||||||
|
|
||||||
if (info->type == PACKET) {
|
if (info->type == PACKET) {
|
||||||
// dump_txm_registers(priv);
|
/* dump_txm_registers(priv);
|
||||||
// dump_rxm_registers(priv);
|
dump_rxm_registers(priv);
|
||||||
// dump_bm_registers(priv);
|
dump_bm_registers(priv);
|
||||||
// dump_cir_registers(priv);
|
dump_cir_registers(priv); */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info->type == PACKET) {
|
if (info->type == PACKET) {
|
||||||
// struct ieee80211_hdr *hdr;
|
/* struct ieee80211_hdr *hdr; */
|
||||||
struct ieee80211_tx_info *txi = IEEE80211_SKB_CB(info->skb);
|
struct ieee80211_tx_info *txi = IEEE80211_SKB_CB(info->skb);
|
||||||
|
|
||||||
skb_pull(info->skb, sizeof(struct agnx_hdr));
|
skb_pull(info->skb, sizeof(struct agnx_hdr));
|
||||||
memcpy(skb_push(info->skb, info->hdr_len), &info->hdr, info->hdr_len);
|
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, */
|
/* print_hex_dump_bytes("agnx: TX_HANDLE: ", DUMP_PREFIX_NONE, */
|
||||||
/* info->skb->data, info->skb->len); */
|
/* 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)); */
|
/* ieee80211_tx_status_irqsafe(priv->hw, info->skb, &(info->tx_status)); */
|
||||||
/* } else */
|
/* } else */
|
||||||
/* dev_kfree_skb_irq(info->skb); */
|
/* dev_kfree_skb_irq(info->skb); */
|
||||||
}
|
}
|
||||||
memset(desc, 0, sizeof(*desc));
|
memset(desc, 0, sizeof(*desc));
|
||||||
memset(info, 0, sizeof(*info));
|
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 handle_other_irq(struct agnx_priv *priv)
|
||||||
{
|
{
|
||||||
// void __iomem *ctl = priv->ctl;
|
/* void __iomem *ctl = priv->ctl; */
|
||||||
u32 status = priv->irq_status;
|
u32 status = priv->irq_status;
|
||||||
void __iomem *ctl = priv->ctl;
|
void __iomem *ctl = priv->ctl;
|
||||||
u32 reg;
|
u32 reg;
|
||||||
|
@ -526,11 +525,11 @@ void handle_other_irq(struct agnx_priv *priv)
|
||||||
iowrite32(reg, ctl + AGNX_INT_MASK);
|
iowrite32(reg, ctl + AGNX_INT_MASK);
|
||||||
iowrite32(IRQ_RX_FRAME, ctl + AGNX_INT_STAT);
|
iowrite32(IRQ_RX_FRAME, ctl + AGNX_INT_STAT);
|
||||||
printk(PFX "IRQ: RX Frame\n");
|
printk(PFX "IRQ: RX Frame\n");
|
||||||
rx_frame_cnt++;
|
rx_frame_cnt++;
|
||||||
}
|
}
|
||||||
if (status & IRQ_ERR_INT) {
|
if (status & IRQ_ERR_INT) {
|
||||||
iowrite32(IRQ_ERR_INT, ctl + AGNX_INT_STAT);
|
iowrite32(IRQ_ERR_INT, ctl + AGNX_INT_STAT);
|
||||||
// agnx_hw_reset(priv);
|
/* agnx_hw_reset(priv); */
|
||||||
printk(PFX "IRQ: Error Interrupt\n");
|
printk(PFX "IRQ: Error Interrupt\n");
|
||||||
}
|
}
|
||||||
if (status & IRQ_TX_QUE_FULL)
|
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)
|
static inline void route_flag_set(struct agnx_hdr *txhdr)
|
||||||
{
|
{
|
||||||
// u32 reg = 0;
|
/* u32 reg = 0; */
|
||||||
|
|
||||||
/* FIXME */
|
/* FIXME */
|
||||||
/* reg = (0x7 << ROUTE_COMPRESSION_SHIFT) & ROUTE_COMPRESSION; */
|
/* reg = (0x7 << ROUTE_COMPRESSION_SHIFT) & ROUTE_COMPRESSION; */
|
||||||
/* txhdr->reg5 = cpu_to_be32(reg); */
|
/* txhdr->reg5 = cpu_to_be32(reg); */
|
||||||
txhdr->reg5 = (0xa << 0x0) | (0x7 << 0x18);
|
txhdr->reg5 = (0xa << 0x0) | (0x7 << 0x18);
|
||||||
// txhdr->reg5 = cpu_to_be32((0xa << 0x0) | (0x7 << 0x18));
|
/* txhdr->reg5 = cpu_to_be32((0xa << 0x0) | (0x7 << 0x18)); */
|
||||||
// txhdr->reg5 = cpu_to_be32(0x7 << 0x0);
|
/* txhdr->reg5 = cpu_to_be32(0x7 << 0x0); */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return 0 if no match */
|
/* 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 55:
|
||||||
case 60:
|
case 60:
|
||||||
case 90:
|
case 90:
|
||||||
case 120: power_level = 22; break;
|
case 120:
|
||||||
case 180: power_level = 19; break;
|
power_level = 22;
|
||||||
case 240: power_level = 18; break;
|
break;
|
||||||
case 360: power_level = 16; break;
|
|
||||||
case 480: power_level = 15; break;
|
case 180:
|
||||||
case 540: power_level = 14; break;
|
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:
|
default:
|
||||||
agnx_bug("Error rate setting\n");
|
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));
|
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(STATION_ID, STATION_ID_SHIFT, BSSID_STAID);
|
||||||
reg |= agnx_set_bits(WORKQUEUE_ID, WORKQUEUE_ID_SHIFT, 0);
|
reg |= agnx_set_bits(WORKQUEUE_ID, WORKQUEUE_ID_SHIFT, 0);
|
||||||
txhdr->reg4 = cpu_to_be32(reg);
|
txhdr->reg4 = cpu_to_be32(reg);
|
||||||
|
|
||||||
/* Set the Hardware Sequence Number to 1? */
|
/* 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, 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);
|
reg |= agnx_set_bits(MAC_HDR_LEN, MAC_HDR_LEN_SHIFT, tx_info->hdr_len);
|
||||||
txhdr->reg1 = cpu_to_be32(reg);
|
txhdr->reg1 = cpu_to_be32(reg);
|
||||||
/* Set the agnx_hdr's MAC header */
|
/* Set the agnx_hdr's MAC header */
|
||||||
memcpy(txhdr->mac_hdr, &tx_info->hdr, tx_info->hdr_len);
|
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, 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, 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(RELAY, RELAY_SHIFT, 0);
|
||||||
reg |= agnx_set_bits(TM, TM_SHIFT, 0);
|
reg |= agnx_set_bits(TM, TM_SHIFT, 0);
|
||||||
txhdr->reg0 = cpu_to_be32(reg);
|
txhdr->reg0 = cpu_to_be32(reg);
|
||||||
|
|
||||||
/* Set the long and short retry limits */
|
/* Set the long and short retry limits */
|
||||||
txhdr->tx.short_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;
|
txhdr->tx.long_retry_limit = tx_info->txi->control.rates[0].count;
|
||||||
|
|
||||||
/* FIXME */
|
/* FIXME */
|
||||||
len = tx_info->skb->len - sizeof(*txhdr) + tx_info->hdr_len + FCS_LEN;
|
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) {
|
if (txi->control.rates[0].idx < 0) {
|
||||||
/* For B mode Short Preamble */
|
/* For B mode Short Preamble */
|
||||||
reg = agnx_set_bits(PHY_MODE, PHY_MODE_SHIFT, AGNX_MODE_80211B_SHORT);
|
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
|
} else
|
||||||
reg = agnx_set_bits(PHY_MODE, PHY_MODE_SHIFT, AGNX_MODE_80211G);
|
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(SIGNAL, SIGNAL_SHIFT, 0xB);
|
||||||
reg |= agnx_set_bits(RATE, RATE_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);
|
reg |= agnx_set_bits(POWER_LEVEL, POWER_LEVEL_SHIFT, 20);
|
||||||
/* if rate < 11M set it to 0 */
|
/* if rate < 11M set it to 0 */
|
||||||
reg |= agnx_set_bits(NUM_TRANSMITTERS, NUM_TRANSMITTERS_SHIFT, 1);
|
reg |= agnx_set_bits(NUM_TRANSMITTERS, NUM_TRANSMITTERS_SHIFT, 1);
|
||||||
// reg |= agnx_set_bits(EDCF, EDCF_SHIFT, 1);
|
/* reg |= agnx_set_bits(EDCF, EDCF_SHIFT, 1); */
|
||||||
// reg |= agnx_set_bits(TIFS, TIFS_SHIFT, 1);
|
/* reg |= agnx_set_bits(TIFS, TIFS_SHIFT, 1); */
|
||||||
|
|
||||||
power.reg = reg;
|
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);
|
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);
|
txm_power_set(priv, txi);
|
||||||
|
|
||||||
/* do { */
|
/* do { */
|
||||||
/* int j; */
|
/* int j; */
|
||||||
/* size_t len; */
|
/* size_t len; */
|
||||||
/* len = skb->len - hdr_info->dma_len + hdr_info->hdr_len; */
|
/* len = skb->len - hdr_info->dma_len + hdr_info->hdr_len; */
|
||||||
/* // if (len == 614) { */
|
/* if (len == 614) { */
|
||||||
/* agnx_print_desc(hdr_desc); */
|
/* agnx_print_desc(hdr_desc); */
|
||||||
/* agnx_print_desc(frag_desc); */
|
/* agnx_print_desc(frag_desc); */
|
||||||
/* agnx_print_tx_hdr((struct agnx_hdr *)skb->data); */
|
/* agnx_print_tx_hdr((struct agnx_hdr *)skb->data); */
|
||||||
/* agnx_print_sta_power(priv, LOCAL_STAID); */
|
/* agnx_print_sta_power(priv, LOCAL_STAID); */
|
||||||
/* agnx_print_sta(priv, LOCAL_STAID); */
|
/* agnx_print_sta(priv, LOCAL_STAID); */
|
||||||
/* for (j = 0; j < 8; j++) */
|
/* for (j = 0; j < 8; j++) */
|
||||||
/* agnx_print_sta_tx_wq(priv, LOCAL_STAID, j); */
|
/* agnx_print_sta_tx_wq(priv, LOCAL_STAID, j); */
|
||||||
/* agnx_print_sta_power(priv, BSSID_STAID); */
|
/* agnx_print_sta_power(priv, BSSID_STAID); */
|
||||||
/* agnx_print_sta(priv, BSSID_STAID); */
|
/* 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, j); */
|
/* agnx_print_sta_tx_wq(priv, BSSID_STAID, j); */
|
||||||
/* // } */
|
/* } */
|
||||||
/* } while (0); */
|
/* } while (0); */
|
||||||
|
|
||||||
spin_unlock_irqrestore(&priv->lock, flags);
|
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 = (ioread32(priv->ctl + AGNX_CIR_TXMCTL));
|
||||||
reg |= 0x8;
|
reg |= 0x8;
|
||||||
iowrite32((reg), priv->ctl + AGNX_CIR_TXMCTL);
|
iowrite32((reg), priv->ctl + AGNX_CIR_TXMCTL);
|
||||||
}while (0);
|
} while (0);
|
||||||
|
|
||||||
/* Trigger TXD */
|
/* Trigger TXD */
|
||||||
do {
|
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 = (ioread32(priv->ctl + AGNX_CIR_TXDCTL));
|
||||||
reg |= 0x8;
|
reg |= 0x8;
|
||||||
iowrite32((reg), priv->ctl + AGNX_CIR_TXDCTL);
|
iowrite32((reg), priv->ctl + AGNX_CIR_TXDCTL);
|
||||||
}while (0);
|
} while (0);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -807,12 +823,12 @@ int _agnx_tx(struct agnx_priv *priv, struct sk_buff *skb)
|
||||||
if (tx_packet_check(skb))
|
if (tx_packet_check(skb))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* print_hex_dump_bytes("agnx: TX_PACKET: ", DUMP_PREFIX_NONE, */
|
/* print_hex_dump_bytes("agnx: TX_PACKET: ", DUMP_PREFIX_NONE, */
|
||||||
/* skb->data, skb->len); */
|
/* 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);
|
return __agnx_tx(priv, skb, &priv->txd);
|
||||||
else
|
else
|
||||||
return __agnx_tx(priv, skb, &priv->txm);
|
return __agnx_tx(priv, skb, &priv->txm);
|
||||||
|
|
|
@ -46,7 +46,6 @@
|
||||||
#include <linux/cdev.h>
|
#include <linux/cdev.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/dma-mapping.h>
|
#include <linux/dma-mapping.h>
|
||||||
#include <linux/delay.h>
|
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
|
@ -313,15 +312,16 @@ static int __devinit map_bars(struct ape_dev *ape, struct pci_dev *dev)
|
||||||
continue;
|
continue;
|
||||||
/* do not map BARs with address 0 */
|
/* do not map BARs with address 0 */
|
||||||
if (!bar_start || !bar_end) {
|
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;
|
rc = -1;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
bar_length = bar_end - bar_start + 1;
|
bar_length = bar_end - bar_start + 1;
|
||||||
/* BAR length is less than driver requires? */
|
/* BAR length is less than driver requires? */
|
||||||
if (bar_length < bar_min_len[i]) {
|
if (bar_length < bar_min_len[i]) {
|
||||||
printk(KERN_DEBUG "BAR #%d length = %lu bytes but driver "
|
printk(KERN_DEBUG "BAR #%d length = %lu bytes but driver "
|
||||||
"requires at least %lu bytes\n", i, bar_length, bar_min_len[i]);
|
"requires at least %lu bytes\n",
|
||||||
|
i, bar_length, bar_min_len[i]);
|
||||||
rc = -1;
|
rc = -1;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
@ -333,8 +333,8 @@ static int __devinit map_bars(struct ape_dev *ape, struct pci_dev *dev)
|
||||||
rc = -1;
|
rc = -1;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
printk(KERN_DEBUG "BAR[%d] mapped at 0x%p with length %lu(/%lu).\n", i,
|
printk(KERN_DEBUG "BAR[%d] mapped at 0x%p with length %lu(/%lu).\n", i,
|
||||||
ape->bar[i], bar_min_len[i], bar_length);
|
ape->bar[i], bar_min_len[i], bar_length);
|
||||||
}
|
}
|
||||||
/* succesfully mapped all required BAR regions */
|
/* succesfully mapped all required BAR regions */
|
||||||
rc = 0;
|
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]);
|
dma_addr_t next = sg_dma_address(&sgl[i + 1]);
|
||||||
/* length of this entry i */
|
/* length of this entry i */
|
||||||
len = sg_dma_len(&sgl[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? */
|
/* entry i + 1 is non-contiguous with entry i? */
|
||||||
if (next != addr + len) {
|
if (next != addr + len) {
|
||||||
/* TODO create entry here (we could overwrite i) */
|
/* 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 */
|
/* set descriptor for contiguous transfer */
|
||||||
ape_chdma_desc_set(&desc[j], cont_addr, ep_addr, cont_len);
|
ape_chdma_desc_set(&desc[j], cont_addr, ep_addr, cont_len);
|
||||||
/* next end point memory address */
|
/* 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;
|
addr = next;
|
||||||
}
|
}
|
||||||
/* TODO create entry here (we could overwrite i) */
|
/* 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 "%04d: addr=0x%Lx length=0x%08x\n", i,
|
||||||
printk(KERN_DEBUG "%4d: cont_addr=0x%08x length=0x%08x\n", j, cont_addr, cont_len);
|
(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++;
|
j++;
|
||||||
return j;
|
return j;
|
||||||
}
|
}
|
||||||
|
@ -467,15 +471,14 @@ static inline int compare(u32 *p, u32 *q, int len)
|
||||||
} else {
|
} else {
|
||||||
fail++;
|
fail++;
|
||||||
/* show the first few miscompares */
|
/* show the first few miscompares */
|
||||||
if (fail < 10) {
|
if (fail < 10)
|
||||||
printk(KERN_DEBUG "[%p] = 0x%08x != [%p] = 0x%08x ?!\n", p, *p, q, *q);
|
printk(KERN_DEBUG "[%p] = 0x%08x != [%p] = 0x%08x ?!\n", p, *p, q, *q);
|
||||||
/* but stop after a while */
|
/* but stop after a while */
|
||||||
} else if (fail == 10) {
|
else if (fail == 10)
|
||||||
printk(KERN_DEBUG "---more errors follow! not printed---\n");
|
printk(KERN_DEBUG "---more errors follow! not printed---\n");
|
||||||
} else {
|
else
|
||||||
/* stop compare after this many errors */
|
/* stop compare after this many errors */
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
p++;
|
p++;
|
||||||
q++;
|
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);
|
printk(KERN_DEBUG "ape->table_virt = 0x%p.\n", ape->table_virt);
|
||||||
|
|
||||||
if (!write_header || !read_header || !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 */
|
/* allocate and map coherently-cached memory for a DMA-able buffer */
|
||||||
/* @see Documentation/PCI/PCI-DMA-mapping.txt, near line 318 */
|
/* @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 */
|
/* 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);
|
ape_chdma_desc_set(&ape->table_virt->desc[n], buffer_bus, 4096, 2 * PAGE_SIZE);
|
||||||
#if 1
|
#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);
|
ape_chdma_desc_set(&ape->table_virt->desc[i], buffer_bus, 4096, 2 * PAGE_SIZE);
|
||||||
}
|
|
||||||
/* index of last descriptor */
|
/* index of last descriptor */
|
||||||
n = i - 1;
|
n = i - 1;
|
||||||
#endif
|
#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);
|
printk(KERN_DEBUG "EPLAST = %u, n = %d\n", eplast, n);
|
||||||
if (eplast == n) {
|
if (eplast == n) {
|
||||||
printk(KERN_DEBUG "DONE\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);
|
printk(KERN_DEBUG "#IRQs during transfer: %d\n", ape->irq_count - irq_count);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -661,9 +663,9 @@ static int __devinit dma_test(struct ape_dev *ape, struct pci_dev *dev)
|
||||||
n = 0;
|
n = 0;
|
||||||
ape_chdma_desc_set(&ape->table_virt->desc[n], buffer_bus + 8192, 4096, 2 * PAGE_SIZE);
|
ape_chdma_desc_set(&ape->table_virt->desc[n], buffer_bus + 8192, 4096, 2 * PAGE_SIZE);
|
||||||
#if 1
|
#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);
|
ape_chdma_desc_set(&ape->table_virt->desc[i], buffer_bus + 8192, 4096, 2 * PAGE_SIZE);
|
||||||
}
|
|
||||||
/* index of last descriptor */
|
/* index of last descriptor */
|
||||||
n = i - 1;
|
n = i - 1;
|
||||||
#endif
|
#endif
|
||||||
|
@ -691,7 +693,7 @@ static int __devinit dma_test(struct ape_dev *ape, struct pci_dev *dev)
|
||||||
w = (u32)(n + 1);
|
w = (u32)(n + 1);
|
||||||
/* enable updates of eplast for each descriptor completion */
|
/* enable updates of eplast for each descriptor completion */
|
||||||
w |= (u32)(1UL << 18)/*global EPLAST_EN*/;
|
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 */
|
/* enable MSI for each descriptor completion */
|
||||||
if (ape->msi_enabled)
|
if (ape->msi_enabled)
|
||||||
w |= (1UL << 17)/*global MSI*/;
|
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 */
|
/** memory write barrier */
|
||||||
wmb();
|
wmb();
|
||||||
/** dummy read to flush posted writes */
|
/** dummy read to flush posted writes */
|
||||||
//(void)ioread32();
|
/* (void) ioread32(); */
|
||||||
|
|
||||||
printk(KERN_DEBUG "POLL FOR WRITE:\n");
|
printk(KERN_DEBUG "POLL FOR WRITE:\n");
|
||||||
/* poll for completion, 1000 times 1 millisecond */
|
/* 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;
|
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 */
|
/* query for DMA transfer */
|
||||||
/* @see Documentation/PCI/PCI-DMA-mapping.txt */
|
/* @see Documentation/PCI/PCI-DMA-mapping.txt */
|
||||||
if (!pci_set_dma_mask(dev, DMA_64BIT_MASK)) {
|
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;
|
struct ape_dev *ape;
|
||||||
printk(KERN_DEBUG "remove(0x%p)\n", dev);
|
printk(KERN_DEBUG "remove(0x%p)\n", dev);
|
||||||
if ((dev == 0) || (dev->dev.driver_data == 0)) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
ape = (struct ape_dev *)dev->dev.driver_data;
|
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",
|
printk(KERN_DEBUG DRV_NAME "_write(buf=0x%p, count=%lld, pos=%llu)\n",
|
||||||
buf, (s64)count, (u64)*pos);
|
buf, (s64)count, (u64)*pos);
|
||||||
/* TODO transfer boundaries at PAGE_SIZE granularity */
|
/* TODO transfer boundaries at PAGE_SIZE granularity */
|
||||||
while (remaining > 0)
|
while (remaining > 0) {
|
||||||
{
|
|
||||||
/* limit DMA transfer size */
|
/* 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;
|
APE_CHDMA_MAX_TRANSFER_LEN;
|
||||||
/* get all user space buffer pages and create a scattergather list */
|
/* 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*/);
|
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
|
* character device file operations
|
||||||
*/
|
*/
|
||||||
static struct file_operations sg_fops = {
|
static const struct file_operations sg_fops = {
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.open = sg_open,
|
.open = sg_open,
|
||||||
.release = sg_close,
|
.release = sg_close,
|
||||||
.read = sg_read,
|
.read = sg_read,
|
||||||
.write = sg_write,
|
.write = sg_write,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* sg_init() - Initialize character device
|
/* sg_init() - Initialize character device
|
||||||
|
@ -1158,12 +1160,12 @@ static struct pci_driver pci_driver = {
|
||||||
*/
|
*/
|
||||||
static int __init alterapciechdma_init(void)
|
static int __init alterapciechdma_init(void)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
printk(KERN_DEBUG DRV_NAME " init(), built at " __DATE__ " " __TIME__ "\n");
|
printk(KERN_DEBUG DRV_NAME " init(), built at " __DATE__ " " __TIME__ "\n");
|
||||||
/* register this driver with the PCI bus driver */
|
/* register this driver with the PCI bus driver */
|
||||||
rc = pci_register_driver(&pci_driver);
|
rc = pci_register_driver(&pci_driver);
|
||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
return rc;
|
return rc;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2649,14 +2649,22 @@ static void binder_vma_open(struct vm_area_struct *vma)
|
||||||
{
|
{
|
||||||
struct binder_proc *proc = vma->vm_private_data;
|
struct binder_proc *proc = vma->vm_private_data;
|
||||||
if (binder_debug_mask & BINDER_DEBUG_OPEN_CLOSE)
|
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();
|
dump_stack();
|
||||||
}
|
}
|
||||||
static void binder_vma_close(struct vm_area_struct *vma)
|
static void binder_vma_close(struct vm_area_struct *vma)
|
||||||
{
|
{
|
||||||
struct binder_proc *proc = vma->vm_private_data;
|
struct binder_proc *proc = vma->vm_private_data;
|
||||||
if (binder_debug_mask & BINDER_DEBUG_OPEN_CLOSE)
|
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;
|
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;
|
vma->vm_end = vma->vm_start + SZ_4M;
|
||||||
|
|
||||||
if (binder_debug_mask & BINDER_DEBUG_OPEN_CLOSE)
|
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) {
|
if (vma->vm_flags & FORBIDDEN_MMAP_FLAGS) {
|
||||||
ret = -EPERM;
|
ret = -EPERM;
|
||||||
|
|
|
@ -225,7 +225,7 @@ static int __init ram_console_init(struct ram_console_buffer *buffer,
|
||||||
buffer_size - sizeof(struct ram_console_buffer);
|
buffer_size - sizeof(struct ram_console_buffer);
|
||||||
|
|
||||||
if (ram_console_buffer_size > buffer_size) {
|
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);
|
buffer, buffer_size, ram_console_buffer_size);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -235,8 +235,8 @@ static int __init ram_console_init(struct ram_console_buffer *buffer,
|
||||||
ECC_BLOCK_SIZE) + 1) * ECC_SIZE;
|
ECC_BLOCK_SIZE) + 1) * ECC_SIZE;
|
||||||
|
|
||||||
if (ram_console_buffer_size > buffer_size) {
|
if (ram_console_buffer_size > buffer_size) {
|
||||||
pr_err("ram_console: buffer %p, invalid size %d, "
|
pr_err("ram_console: buffer %p, invalid size %zu, "
|
||||||
"non-ecc datasize %d\n",
|
"non-ecc datasize %zu\n",
|
||||||
buffer, buffer_size, ram_console_buffer_size);
|
buffer, buffer_size, ram_console_buffer_size);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -322,7 +322,7 @@ static int ram_console_driver_probe(struct platform_device *pdev)
|
||||||
}
|
}
|
||||||
buffer_size = res->end - res->start + 1;
|
buffer_size = res->end - res->start + 1;
|
||||||
start = res->start;
|
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);
|
start, buffer_size);
|
||||||
buffer = ioremap(res->start, buffer_size);
|
buffer = ioremap(res->start, buffer_size);
|
||||||
if (buffer == NULL) {
|
if (buffer == NULL) {
|
||||||
|
|
|
@ -56,10 +56,10 @@ MODULE_AUTHOR("Jakub Schmidtke, sjakub@gmail.com");
|
||||||
MODULE_DESCRIPTION("Asus OLED Driver v" ASUS_OLED_VERSION);
|
MODULE_DESCRIPTION("Asus OLED Driver v" ASUS_OLED_VERSION);
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
|
||||||
static struct class *oled_class = 0;
|
static struct class *oled_class;
|
||||||
static int oled_num = 0;
|
static int oled_num;
|
||||||
|
|
||||||
static uint start_off = 0;
|
static uint start_off;
|
||||||
|
|
||||||
module_param(start_off, uint, 0644);
|
module_param(start_off, uint, 0644);
|
||||||
|
|
||||||
|
@ -80,20 +80,20 @@ struct oled_dev_desc_str {
|
||||||
};
|
};
|
||||||
|
|
||||||
/* table of devices that work with this driver */
|
/* 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, 0x1726) }, // Asus G1/G2 (and variants)
|
||||||
{ USB_DEVICE(0x0b05, 0x175b) }, // Asus G50V (and possibly others - G70? G71?)
|
{ USB_DEVICE(0x0b05, 0x175b) }, // Asus G50V (and possibly others - G70? G71?)
|
||||||
{ },
|
{ },
|
||||||
};
|
};
|
||||||
|
|
||||||
/* parameters of specific devices */
|
/* 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, 0x1726, 128, PACK_MODE_G1, "G1/G2" },
|
||||||
{ 0x0b05, 0x175b, 256, PACK_MODE_G50, "G50" },
|
{ 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) \
|
#define SETUP_PACKET_HEADER(packet, val1, val2, val3, val4, val5, val6, val7) \
|
||||||
do { \
|
do { \
|
||||||
|
@ -107,7 +107,7 @@ MODULE_DEVICE_TABLE (usb, id_table);
|
||||||
packet->header.value6 = val5; \
|
packet->header.value6 = val5; \
|
||||||
packet->header.value7 = val6; \
|
packet->header.value7 = val6; \
|
||||||
packet->header.value8 = val7; \
|
packet->header.value8 = val7; \
|
||||||
} while(0);
|
} while (0);
|
||||||
|
|
||||||
struct asus_oled_header {
|
struct asus_oled_header {
|
||||||
uint8_t magic1;
|
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);
|
SETUP_PACKET_HEADER(packet, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00);
|
||||||
|
|
||||||
if (enabl) packet->bitmap[0] = 0xaf;
|
if (enabl)
|
||||||
else packet->bitmap[0] = 0xae;
|
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,
|
retval = usb_bulk_msg(odev->udev,
|
||||||
usb_sndbulkpipe(odev->udev, 2),
|
usb_sndbulkpipe(odev->udev, 2),
|
||||||
packet,
|
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 retval;
|
||||||
int act_len;
|
int act_len;
|
||||||
|
|
||||||
|
@ -294,7 +296,7 @@ static void send_data(struct asus_oled_dev *odev)
|
||||||
return;
|
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.
|
// When sending roll-mode data the display updated only first packet.
|
||||||
// I have no idea why, but when static picture is send just before
|
// I have no idea why, but when static picture is send just before
|
||||||
// rolling picture - everything works fine.
|
// 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);
|
send_packets(odev->udev, packet, odev->buf, odev->pic_mode, packet_num);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if (odev->pack_mode==PACK_MODE_G50){
|
if (odev->pack_mode == PACK_MODE_G50) {
|
||||||
send_packets_g50(odev->udev, packet, odev->buf);
|
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;
|
x += odev->x_shift;
|
||||||
y += odev->y_shift;
|
y += odev->y_shift;
|
||||||
|
|
||||||
switch(odev->pack_mode)
|
switch (odev->pack_mode)
|
||||||
{
|
{
|
||||||
case PACK_MODE_G1:
|
case PACK_MODE_G1:
|
||||||
// i = (x/128)*640 + 127 - x + (y/8)*128;
|
// 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;
|
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
|
// binary mode, set the entire memory
|
||||||
|
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
odev->buf_size = (odev->dev_width * ASUS_OLED_DISP_HEIGHT) / 8;
|
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);
|
odev->buf = kmalloc(odev->buf_size, GFP_KERNEL);
|
||||||
|
|
||||||
memset(odev->buf, 0xff, odev->buf_size);
|
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[i-1] = buf[i];
|
||||||
odev->buf_offs = i-1;
|
odev->buf_offs = i-1;
|
||||||
}
|
}
|
||||||
|
|
||||||
odev->width=odev->dev_width / 8;
|
odev->width = odev->dev_width / 8;
|
||||||
odev->height=ASUS_OLED_DISP_HEIGHT;
|
odev->height = ASUS_OLED_DISP_HEIGHT;
|
||||||
odev->x_shift=0;
|
odev->x_shift = 0;
|
||||||
odev->y_shift=0;
|
odev->y_shift = 0;
|
||||||
odev->last_val=0;
|
odev->last_val = 0;
|
||||||
|
|
||||||
send_data(odev);
|
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;
|
goto error_header;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(tolower(buf[1])) {
|
switch (tolower(buf[1])) {
|
||||||
case ASUS_OLED_STATIC:
|
case ASUS_OLED_STATIC:
|
||||||
case ASUS_OLED_ROLL:
|
case ASUS_OLED_ROLL:
|
||||||
case ASUS_OLED_FLASH:
|
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') {
|
if (buf[i] >= '0' && buf[i] <= '9') {
|
||||||
w = 10*w + (buf[i] - '0');
|
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 if (tolower(buf[i]) == 'x')
|
||||||
else goto error_width;
|
break;
|
||||||
|
else
|
||||||
|
goto error_width;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (++i; i < count; ++i) {
|
for (++i; i < count; ++i) {
|
||||||
if (buf[i] >= '0' && buf[i] <= '9') {
|
if (buf[i] >= '0' && buf[i] <= '9') {
|
||||||
h = 10*h + (buf[i] - '0');
|
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 if (tolower(buf[i]) == '>')
|
||||||
else goto error_height;
|
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;
|
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;
|
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);
|
odev->buf = kmalloc(odev->buf_size, GFP_KERNEL);
|
||||||
|
|
||||||
if (odev->buf == NULL) {
|
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;
|
int ret;
|
||||||
|
|
||||||
if (buf[offs] == '1' || buf[offs] == '#') {
|
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] == ' ') {
|
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') {
|
else if (buf[offs] == '\n') {
|
||||||
// New line detected. Lets assume, that all characters till the end of the
|
// New line detected. Lets assume, that all characters till the end of the
|
||||||
// line were equal to the last character in this line.
|
// line were equal to the last character in this line.
|
||||||
if (odev->buf_offs % odev->width != 0)
|
if (odev->buf_offs % odev->width != 0)
|
||||||
if ( (ret = append_values(odev, odev->last_val,
|
ret = append_values(odev, odev->last_val,
|
||||||
odev->width - (odev->buf_offs % odev->width))) < 0) return ret;
|
odev->width - (odev->buf_offs % odev->width));
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
offs++;
|
offs++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (odev->buf_offs >= max_offs) send_data(odev);
|
if (odev->buf_offs >= max_offs)
|
||||||
|
send_data(odev);
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
|
|
||||||
|
@ -566,9 +587,9 @@ static int asus_oled_probe(struct usb_interface *interface, const struct usb_dev
|
||||||
uint16_t dev_width = 0;
|
uint16_t dev_width = 0;
|
||||||
oled_pack_mode_t pack_mode = PACK_MODE_LAST;
|
oled_pack_mode_t pack_mode = PACK_MODE_LAST;
|
||||||
const struct oled_dev_desc_str * dev_desc = oled_dev_desc_table;
|
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...
|
// Even possible? Just to make sure...
|
||||||
dev_err(&interface->dev, "No usb_device_id provided!\n");
|
dev_err(&interface->dev, "No usb_device_id provided!\n");
|
||||||
return -ENODEV;
|
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");
|
dev_err(&interface->dev, "Missing or incomplete device description!\n");
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
@ -611,20 +632,20 @@ static int asus_oled_probe(struct usb_interface *interface, const struct usb_dev
|
||||||
odev->last_val = 0;
|
odev->last_val = 0;
|
||||||
odev->buf = NULL;
|
odev->buf = NULL;
|
||||||
odev->enabled = 1;
|
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;
|
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;
|
goto err_files;
|
||||||
}
|
|
||||||
|
|
||||||
odev->dev = device_create(oled_class, &interface->dev, MKDEV(0,0),
|
odev->dev = device_create(oled_class, &interface->dev, MKDEV(0, 0),
|
||||||
NULL,"oled_%d", ++oled_num);
|
NULL, "oled_%d", ++oled_num);
|
||||||
|
|
||||||
if (IS_ERR(odev->dev)) {
|
if (IS_ERR(odev->dev)) {
|
||||||
retval = PTR_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);
|
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;
|
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;
|
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);
|
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 @@ err_files:
|
||||||
device_remove_file(&interface->dev, &ASUS_OLED_DEVICE_ATTR(enabled));
|
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(picture));
|
||||||
|
|
||||||
usb_set_intfdata (interface, NULL);
|
usb_set_intfdata(interface, NULL);
|
||||||
usb_put_dev(odev->udev);
|
usb_put_dev(odev->udev);
|
||||||
kfree(odev);
|
kfree(odev);
|
||||||
|
|
||||||
|
@ -670,19 +691,20 @@ static void asus_oled_disconnect(struct usb_interface *interface)
|
||||||
{
|
{
|
||||||
struct asus_oled_dev *odev;
|
struct asus_oled_dev *odev;
|
||||||
|
|
||||||
odev = usb_get_intfdata (interface);
|
odev = usb_get_intfdata(interface);
|
||||||
usb_set_intfdata (interface, NULL);
|
usb_set_intfdata(interface, NULL);
|
||||||
|
|
||||||
device_remove_file(odev->dev, &dev_attr_picture);
|
device_remove_file(odev->dev, &dev_attr_picture);
|
||||||
device_remove_file(odev->dev, &dev_attr_enabled);
|
device_remove_file(odev->dev, &dev_attr_enabled);
|
||||||
device_unregister(odev->dev);
|
device_unregister(odev->dev);
|
||||||
|
|
||||||
device_remove_file(&interface->dev, & ASUS_OLED_DEVICE_ATTR(picture));
|
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(enabled));
|
||||||
|
|
||||||
usb_put_dev(odev->udev);
|
usb_put_dev(odev->udev);
|
||||||
|
|
||||||
if (odev->buf) kfree(odev->buf);
|
if (odev->buf)
|
||||||
|
kfree(odev->buf);
|
||||||
|
|
||||||
kfree(odev);
|
kfree(odev);
|
||||||
|
|
||||||
|
@ -713,7 +735,8 @@ static int __init asus_oled_init(void)
|
||||||
return PTR_ERR(oled_class);
|
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");
|
err("Error creating class version file");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
@ -740,6 +763,6 @@ static void __exit asus_oled_exit(void)
|
||||||
usb_deregister(&oled_driver);
|
usb_deregister(&oled_driver);
|
||||||
}
|
}
|
||||||
|
|
||||||
module_init (asus_oled_init);
|
module_init(asus_oled_init);
|
||||||
module_exit (asus_oled_exit);
|
module_exit(asus_oled_exit);
|
||||||
|
|
||||||
|
|
|
@ -1,2 +1,7 @@
|
||||||
rewrite the driver to use the proper in-kernel wireless stack
|
Fix the mac80211 port of at76_usb (the proper in-kernel wireless
|
||||||
instead of using its own.
|
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.
|
||||||
|
|
|
@ -36,7 +36,7 @@
|
||||||
#include <net/ieee80211_radiotap.h>
|
#include <net/ieee80211_radiotap.h>
|
||||||
#include <linux/firmware.h>
|
#include <linux/firmware.h>
|
||||||
#include <linux/leds.h>
|
#include <linux/leds.h>
|
||||||
#include <net/ieee80211.h>
|
#include <linux/ieee80211.h>
|
||||||
|
|
||||||
#include "at76_usb.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 */
|
/* write TLV data elements */
|
||||||
|
|
||||||
ie->id = MFIE_TYPE_SSID;
|
ie->id = WLAN_EID_SSID;
|
||||||
ie->len = bss->ssid_len;
|
ie->len = bss->ssid_len;
|
||||||
memcpy(ie->data, bss->ssid, bss->ssid_len);
|
memcpy(ie->data, bss->ssid, bss->ssid_len);
|
||||||
next_ie(&ie);
|
next_ie(&ie);
|
||||||
|
|
||||||
ie->id = MFIE_TYPE_RATES;
|
ie->id = WLAN_EID_SUPP_RATES;
|
||||||
ie->len = sizeof(hw_rates);
|
ie->len = sizeof(hw_rates);
|
||||||
memcpy(ie->data, hw_rates, sizeof(hw_rates));
|
memcpy(ie->data, hw_rates, sizeof(hw_rates));
|
||||||
next_ie(&ie); /* ie points behind the supp_rates field */
|
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) {
|
switch (ie->id) {
|
||||||
|
|
||||||
case MFIE_TYPE_SSID:
|
case WLAN_EID_SSID:
|
||||||
if (have_ssid)
|
if (have_ssid)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -4420,7 +4420,7 @@ static void at76_rx_mgmt_beacon(struct at76_priv *priv,
|
||||||
have_ssid = 1;
|
have_ssid = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MFIE_TYPE_RATES:
|
case WLAN_EID_SUPP_RATES:
|
||||||
if (have_rates)
|
if (have_rates)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -4433,7 +4433,7 @@ static void at76_rx_mgmt_beacon(struct at76_priv *priv,
|
||||||
hex2str(ie->data, ie->len));
|
hex2str(ie->data, ie->len));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MFIE_TYPE_DS_SET:
|
case WLAN_EID_DS_PARAMS:
|
||||||
if (have_channel)
|
if (have_channel)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -4443,9 +4443,9 @@ static void at76_rx_mgmt_beacon(struct at76_priv *priv,
|
||||||
priv->netdev->name, match->channel);
|
priv->netdev->name, match->channel);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MFIE_TYPE_CF_SET:
|
case WLAN_EID_CF_PARAMS:
|
||||||
case MFIE_TYPE_TIM:
|
case WLAN_EID_TIM:
|
||||||
case MFIE_TYPE_IBSS_SET:
|
case WLAN_EID_IBSS_PARAMS:
|
||||||
default:
|
default:
|
||||||
at76_dbg(DBG_RX_BEACON, "%s: beacon IE id %d len %d %s",
|
at76_dbg(DBG_RX_BEACON, "%s: beacon IE id %d len %d %s",
|
||||||
priv->netdev->name, ie->id, ie->len,
|
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__);
|
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);
|
at76_free_bss_list(priv);
|
||||||
del_timer_sync(&priv->bss_list_timer);
|
del_timer_sync(&priv->bss_list_timer);
|
||||||
|
|
|
@ -22,6 +22,93 @@
|
||||||
#ifndef _AT76_USB_H
|
#ifndef _AT76_USB_H
|
||||||
#define _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 */
|
/* Board types */
|
||||||
enum board_type {
|
enum board_type {
|
||||||
BOARD_503_ISL3861 = 1,
|
BOARD_503_ISL3861 = 1,
|
||||||
|
|
|
@ -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.
|
|
@ -0,0 +1 @@
|
||||||
|
obj-$(CONFIG_B3DFG) += b3dfg.o
|
|
@ -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
|
@ -6,6 +6,13 @@ config COMEDI
|
||||||
Enable support a wide range of data acquisition devices
|
Enable support a wide range of data acquisition devices
|
||||||
for Linux.
|
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
|
config COMEDI_RT
|
||||||
tristate "Comedi Real-time support"
|
tristate "Comedi Real-time support"
|
||||||
depends on COMEDI && RT
|
depends on COMEDI && RT
|
||||||
|
@ -20,6 +27,13 @@ config COMEDI_PCI_DRIVERS
|
||||||
---help---
|
---help---
|
||||||
Enable lots of comedi PCI drivers to be built
|
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
|
config COMEDI_USB_DRIVERS
|
||||||
tristate "Comedi USB drivers"
|
tristate "Comedi USB drivers"
|
||||||
depends on COMEDI && USB
|
depends on COMEDI && USB
|
||||||
|
|
|
@ -57,9 +57,6 @@ extern "C" {
|
||||||
/* max length of device and driver names */
|
/* max length of device and driver names */
|
||||||
#define COMEDI_NAMELEN 20
|
#define COMEDI_NAMELEN 20
|
||||||
|
|
||||||
typedef unsigned int lsampl_t;
|
|
||||||
typedef unsigned short sampl_t;
|
|
||||||
|
|
||||||
/* packs and unpacks a channel/range number */
|
/* packs and unpacks a channel/range number */
|
||||||
|
|
||||||
#define CR_PACK(chan, rng, aref) ((((aref)&0x3)<<24) | (((rng)&0xff)<<16) | (chan))
|
#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_GET_CLOCK_SRC = 2004, /* Get master clock source */
|
||||||
INSN_CONFIG_SET_OTHER_SRC = 2005, /* Set other source */
|
INSN_CONFIG_SET_OTHER_SRC = 2005, /* Set other source */
|
||||||
/* INSN_CONFIG_GET_OTHER_SRC = 2006,*/ /* Get other source */
|
/* INSN_CONFIG_GET_OTHER_SRC = 2006,*/ /* Get other source */
|
||||||
INSN_CONFIG_GET_HARDWARE_BUFFER_SIZE, /* Get size in bytes of
|
INSN_CONFIG_GET_HARDWARE_BUFFER_SIZE = 2006, /* Get size in bytes of
|
||||||
subdevice's on-board fifos
|
subdevice's on-board
|
||||||
used during streaming
|
fifos used during
|
||||||
input/output */
|
streaming
|
||||||
|
input/output */
|
||||||
INSN_CONFIG_SET_COUNTER_MODE = 4097,
|
INSN_CONFIG_SET_COUNTER_MODE = 4097,
|
||||||
INSN_CONFIG_8254_SET_MODE = INSN_CONFIG_SET_COUNTER_MODE, /* deprecated */
|
INSN_CONFIG_8254_SET_MODE = INSN_CONFIG_SET_COUNTER_MODE, /* deprecated */
|
||||||
INSN_CONFIG_8254_READ_STATUS = 4098,
|
INSN_CONFIG_8254_READ_STATUS = 4098,
|
||||||
|
@ -293,45 +291,32 @@ enum comedi_support_level {
|
||||||
/* ioctls */
|
/* ioctls */
|
||||||
|
|
||||||
#define CIO 'd'
|
#define CIO 'd'
|
||||||
#define COMEDI_DEVCONFIG _IOW(CIO, 0, comedi_devconfig)
|
#define COMEDI_DEVCONFIG _IOW(CIO, 0, struct comedi_devconfig)
|
||||||
#define COMEDI_DEVINFO _IOR(CIO, 1, comedi_devinfo)
|
#define COMEDI_DEVINFO _IOR(CIO, 1, struct comedi_devinfo)
|
||||||
#define COMEDI_SUBDINFO _IOR(CIO, 2, comedi_subdinfo)
|
#define COMEDI_SUBDINFO _IOR(CIO, 2, struct comedi_subdinfo)
|
||||||
#define COMEDI_CHANINFO _IOR(CIO, 3, comedi_chaninfo)
|
#define COMEDI_CHANINFO _IOR(CIO, 3, struct comedi_chaninfo)
|
||||||
#define COMEDI_TRIG _IOWR(CIO, 4, comedi_trig)
|
#define COMEDI_TRIG _IOWR(CIO, 4, comedi_trig)
|
||||||
#define COMEDI_LOCK _IO(CIO, 5)
|
#define COMEDI_LOCK _IO(CIO, 5)
|
||||||
#define COMEDI_UNLOCK _IO(CIO, 6)
|
#define COMEDI_UNLOCK _IO(CIO, 6)
|
||||||
#define COMEDI_CANCEL _IO(CIO, 7)
|
#define COMEDI_CANCEL _IO(CIO, 7)
|
||||||
#define COMEDI_RANGEINFO _IOR(CIO, 8, comedi_rangeinfo)
|
#define COMEDI_RANGEINFO _IOR(CIO, 8, struct comedi_rangeinfo)
|
||||||
#define COMEDI_CMD _IOR(CIO, 9, comedi_cmd)
|
#define COMEDI_CMD _IOR(CIO, 9, struct comedi_cmd)
|
||||||
#define COMEDI_CMDTEST _IOR(CIO, 10, comedi_cmd)
|
#define COMEDI_CMDTEST _IOR(CIO, 10, struct comedi_cmd)
|
||||||
#define COMEDI_INSNLIST _IOR(CIO, 11, comedi_insnlist)
|
#define COMEDI_INSNLIST _IOR(CIO, 11, struct comedi_insnlist)
|
||||||
#define COMEDI_INSN _IOR(CIO, 12, comedi_insn)
|
#define COMEDI_INSN _IOR(CIO, 12, struct comedi_insn)
|
||||||
#define COMEDI_BUFCONFIG _IOR(CIO, 13, comedi_bufconfig)
|
#define COMEDI_BUFCONFIG _IOR(CIO, 13, struct comedi_bufconfig)
|
||||||
#define COMEDI_BUFINFO _IOWR(CIO, 14, comedi_bufinfo)
|
#define COMEDI_BUFINFO _IOWR(CIO, 14, struct comedi_bufinfo)
|
||||||
#define COMEDI_POLL _IO(CIO, 15)
|
#define COMEDI_POLL _IO(CIO, 15)
|
||||||
|
|
||||||
/* structures */
|
/* structures */
|
||||||
|
|
||||||
typedef struct comedi_trig_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 {
|
|
||||||
unsigned int subdev; /* subdevice */
|
unsigned int subdev; /* subdevice */
|
||||||
unsigned int mode; /* mode */
|
unsigned int mode; /* mode */
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
unsigned int n_chan; /* number of channels */
|
unsigned int n_chan; /* number of channels */
|
||||||
unsigned int *chanlist; /* channel/range list */
|
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 n; /* number of scans */
|
||||||
unsigned int trigsrc;
|
unsigned int trigsrc;
|
||||||
unsigned int trigvar;
|
unsigned int trigvar;
|
||||||
|
@ -340,21 +325,21 @@ struct comedi_trig_struct {
|
||||||
unsigned int unused[3];
|
unsigned int unused[3];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct comedi_insn_struct {
|
struct comedi_insn {
|
||||||
unsigned int insn;
|
unsigned int insn;
|
||||||
unsigned int n;
|
unsigned int n;
|
||||||
lsampl_t *data;
|
unsigned int *data;
|
||||||
unsigned int subdev;
|
unsigned int subdev;
|
||||||
unsigned int chanspec;
|
unsigned int chanspec;
|
||||||
unsigned int unused[3];
|
unsigned int unused[3];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct comedi_insnlist_struct {
|
struct comedi_insnlist {
|
||||||
unsigned int n_insns;
|
unsigned int n_insns;
|
||||||
comedi_insn *insns;
|
struct comedi_insn *insns;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct comedi_cmd_struct {
|
struct comedi_cmd {
|
||||||
unsigned int subdev;
|
unsigned int subdev;
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
|
|
||||||
|
@ -376,37 +361,37 @@ struct comedi_cmd_struct {
|
||||||
unsigned int *chanlist; /* channel/range list */
|
unsigned int *chanlist; /* channel/range list */
|
||||||
unsigned int chanlist_len;
|
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;
|
unsigned int data_len;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct comedi_chaninfo_struct {
|
struct comedi_chaninfo {
|
||||||
unsigned int subdev;
|
unsigned int subdev;
|
||||||
lsampl_t *maxdata_list;
|
unsigned int *maxdata_list;
|
||||||
unsigned int *flaglist;
|
unsigned int *flaglist;
|
||||||
unsigned int *rangelist;
|
unsigned int *rangelist;
|
||||||
unsigned int unused[4];
|
unsigned int unused[4];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct comedi_rangeinfo_struct {
|
struct comedi_rangeinfo {
|
||||||
unsigned int range_type;
|
unsigned int range_type;
|
||||||
void *range_ptr;
|
void *range_ptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct comedi_krange_struct {
|
struct comedi_krange {
|
||||||
int min; /* fixed point, multiply by 1e-6 */
|
int min; /* fixed point, multiply by 1e-6 */
|
||||||
int max; /* fixed point, multiply by 1e-6 */
|
int max; /* fixed point, multiply by 1e-6 */
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct comedi_subdinfo_struct {
|
struct comedi_subdinfo {
|
||||||
unsigned int type;
|
unsigned int type;
|
||||||
unsigned int n_chan;
|
unsigned int n_chan;
|
||||||
unsigned int subd_flags;
|
unsigned int subd_flags;
|
||||||
unsigned int timer_type;
|
unsigned int timer_type;
|
||||||
unsigned int len_chanlist;
|
unsigned int len_chanlist;
|
||||||
lsampl_t maxdata;
|
unsigned int maxdata;
|
||||||
unsigned int flags; /* channel flags */
|
unsigned int flags; /* channel flags */
|
||||||
unsigned int range_type; /* lookup in kernel */
|
unsigned int range_type; /* lookup in kernel */
|
||||||
unsigned int settling_time_0;
|
unsigned int settling_time_0;
|
||||||
|
@ -414,7 +399,7 @@ struct comedi_subdinfo_struct {
|
||||||
unsigned int unused[8];
|
unsigned int unused[8];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct comedi_devinfo_struct {
|
struct comedi_devinfo {
|
||||||
unsigned int version_code;
|
unsigned int version_code;
|
||||||
unsigned int n_subdevs;
|
unsigned int n_subdevs;
|
||||||
char driver_name[COMEDI_NAMELEN];
|
char driver_name[COMEDI_NAMELEN];
|
||||||
|
@ -424,12 +409,12 @@ struct comedi_devinfo_struct {
|
||||||
int unused[30];
|
int unused[30];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct comedi_devconfig_struct {
|
struct comedi_devconfig {
|
||||||
char board_name[COMEDI_NAMELEN];
|
char board_name[COMEDI_NAMELEN];
|
||||||
int options[COMEDI_NDEVCONFOPTS];
|
int options[COMEDI_NDEVCONFOPTS];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct comedi_bufconfig_struct {
|
struct comedi_bufconfig {
|
||||||
unsigned int subdevice;
|
unsigned int subdevice;
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
|
|
||||||
|
@ -439,7 +424,7 @@ struct comedi_bufconfig_struct {
|
||||||
unsigned int unused[4];
|
unsigned int unused[4];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct comedi_bufinfo_struct {
|
struct comedi_bufinfo {
|
||||||
unsigned int subdevice;
|
unsigned int subdevice;
|
||||||
unsigned int bytes_read;
|
unsigned int bytes_read;
|
||||||
|
|
||||||
|
|
|
@ -37,31 +37,31 @@
|
||||||
#include <linux/ioctl32.h> /* for (un)register_ioctl32_conversion */
|
#include <linux/ioctl32.h> /* for (un)register_ioctl32_conversion */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define COMEDI32_CHANINFO _IOR(CIO,3,comedi32_chaninfo)
|
#define COMEDI32_CHANINFO _IOR(CIO, 3, struct comedi32_chaninfo_struct)
|
||||||
#define COMEDI32_RANGEINFO _IOR(CIO,8,comedi32_rangeinfo)
|
#define COMEDI32_RANGEINFO _IOR(CIO, 8, struct comedi32_rangeinfo_struct)
|
||||||
/* N.B. COMEDI32_CMD and COMEDI_CMD ought to use _IOWR, not _IOR.
|
/* 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. */
|
* 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.
|
/* 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. */
|
* 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_CMDTEST _IOR(CIO, 10, struct comedi32_cmd_struct)
|
||||||
#define COMEDI32_INSNLIST _IOR(CIO,11,comedi32_insnlist)
|
#define COMEDI32_INSNLIST _IOR(CIO, 11, struct comedi32_insnlist_struct)
|
||||||
#define COMEDI32_INSN _IOR(CIO,12,comedi32_insn)
|
#define COMEDI32_INSN _IOR(CIO, 12, struct comedi32_insn_struct)
|
||||||
|
|
||||||
typedef struct comedi32_chaninfo_struct {
|
struct comedi32_chaninfo_struct {
|
||||||
unsigned int subdev;
|
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 flaglist; /* 32-bit 'unsigned int *' */
|
||||||
compat_uptr_t rangelist; /* 32-bit 'unsigned int *' */
|
compat_uptr_t rangelist; /* 32-bit 'unsigned int *' */
|
||||||
unsigned int unused[4];
|
unsigned int unused[4];
|
||||||
} comedi32_chaninfo;
|
};
|
||||||
|
|
||||||
typedef struct comedi32_rangeinfo_struct {
|
struct comedi32_rangeinfo_struct {
|
||||||
unsigned int range_type;
|
unsigned int range_type;
|
||||||
compat_uptr_t range_ptr; /* 32-bit 'void *' */
|
compat_uptr_t range_ptr; /* 32-bit 'void *' */
|
||||||
} comedi32_rangeinfo;
|
};
|
||||||
|
|
||||||
typedef struct comedi32_cmd_struct {
|
struct comedi32_cmd_struct {
|
||||||
unsigned int subdev;
|
unsigned int subdev;
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
unsigned int start_src;
|
unsigned int start_src;
|
||||||
|
@ -76,37 +76,36 @@ typedef struct comedi32_cmd_struct {
|
||||||
unsigned int stop_arg;
|
unsigned int stop_arg;
|
||||||
compat_uptr_t chanlist; /* 32-bit 'unsigned int *' */
|
compat_uptr_t chanlist; /* 32-bit 'unsigned int *' */
|
||||||
unsigned int chanlist_len;
|
unsigned int chanlist_len;
|
||||||
compat_uptr_t data; /* 32-bit 'sampl_t *' */
|
compat_uptr_t data; /* 32-bit 'short *' */
|
||||||
unsigned int data_len;
|
unsigned int data_len;
|
||||||
} comedi32_cmd;
|
};
|
||||||
|
|
||||||
typedef struct comedi32_insn_struct {
|
struct comedi32_insn_struct {
|
||||||
unsigned int insn;
|
unsigned int insn;
|
||||||
unsigned int n;
|
unsigned int n;
|
||||||
compat_uptr_t data; /* 32-bit 'lsampl_t *' */
|
compat_uptr_t data; /* 32-bit 'unsigned int *' */
|
||||||
unsigned int subdev;
|
unsigned int subdev;
|
||||||
unsigned int chanspec;
|
unsigned int chanspec;
|
||||||
unsigned int unused[3];
|
unsigned int unused[3];
|
||||||
} comedi32_insn;
|
};
|
||||||
|
|
||||||
typedef struct comedi32_insnlist_struct {
|
struct comedi32_insnlist_struct {
|
||||||
unsigned int n_insns;
|
unsigned int n_insns;
|
||||||
compat_uptr_t insns; /* 32-bit 'comedi_insn *' */
|
compat_uptr_t insns; /* 32-bit 'struct comedi_insn *' */
|
||||||
} comedi32_insnlist;
|
};
|
||||||
|
|
||||||
/* Handle translated ioctl. */
|
/* Handle translated ioctl. */
|
||||||
static int translated_ioctl(struct file *file, unsigned int cmd,
|
static int translated_ioctl(struct file *file, unsigned int cmd,
|
||||||
unsigned long arg)
|
unsigned long arg)
|
||||||
{
|
{
|
||||||
if (!file->f_op) {
|
if (!file->f_op)
|
||||||
return -ENOTTY;
|
return -ENOTTY;
|
||||||
}
|
|
||||||
#ifdef HAVE_UNLOCKED_IOCTL
|
#ifdef HAVE_UNLOCKED_IOCTL
|
||||||
if (file->f_op->unlocked_ioctl) {
|
if (file->f_op->unlocked_ioctl) {
|
||||||
int rc = (int)(*file->f_op->unlocked_ioctl)(file, cmd, arg);
|
int rc = (int)(*file->f_op->unlocked_ioctl)(file, cmd, arg);
|
||||||
if (rc == -ENOIOCTLCMD) {
|
if (rc == -ENOIOCTLCMD)
|
||||||
rc = -ENOTTY;
|
rc = -ENOTTY;
|
||||||
}
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -124,8 +123,8 @@ static int translated_ioctl(struct file *file, unsigned int cmd,
|
||||||
/* Handle 32-bit COMEDI_CHANINFO ioctl. */
|
/* Handle 32-bit COMEDI_CHANINFO ioctl. */
|
||||||
static int compat_chaninfo(struct file *file, unsigned long arg)
|
static int compat_chaninfo(struct file *file, unsigned long arg)
|
||||||
{
|
{
|
||||||
comedi_chaninfo __user *chaninfo;
|
struct comedi_chaninfo __user *chaninfo;
|
||||||
comedi32_chaninfo __user *chaninfo32;
|
struct comedi32_chaninfo_struct __user *chaninfo32;
|
||||||
int err;
|
int err;
|
||||||
union {
|
union {
|
||||||
unsigned int uint;
|
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 |= __put_user(compat_ptr(temp.uptr), &chaninfo->flaglist);
|
||||||
err |= __get_user(temp.uptr, &chaninfo32->rangelist);
|
err |= __get_user(temp.uptr, &chaninfo32->rangelist);
|
||||||
err |= __put_user(compat_ptr(temp.uptr), &chaninfo->rangelist);
|
err |= __put_user(compat_ptr(temp.uptr), &chaninfo->rangelist);
|
||||||
if (err) {
|
if (err)
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
|
||||||
|
|
||||||
return translated_ioctl(file, COMEDI_CHANINFO, (unsigned long)chaninfo);
|
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. */
|
/* Handle 32-bit COMEDI_RANGEINFO ioctl. */
|
||||||
static int compat_rangeinfo(struct file *file, unsigned long arg)
|
static int compat_rangeinfo(struct file *file, unsigned long arg)
|
||||||
{
|
{
|
||||||
comedi_rangeinfo __user *rangeinfo;
|
struct comedi_rangeinfo __user *rangeinfo;
|
||||||
comedi32_rangeinfo __user *rangeinfo32;
|
struct comedi32_rangeinfo_struct __user *rangeinfo32;
|
||||||
int err;
|
int err;
|
||||||
union {
|
union {
|
||||||
unsigned int uint;
|
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 |= __put_user(temp.uint, &rangeinfo->range_type);
|
||||||
err |= __get_user(temp.uptr, &rangeinfo32->range_ptr);
|
err |= __get_user(temp.uptr, &rangeinfo32->range_ptr);
|
||||||
err |= __put_user(compat_ptr(temp.uptr), &rangeinfo->range_ptr);
|
err |= __put_user(compat_ptr(temp.uptr), &rangeinfo->range_ptr);
|
||||||
if (err) {
|
if (err)
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
|
||||||
|
|
||||||
return translated_ioctl(file, COMEDI_RANGEINFO,
|
return translated_ioctl(file, COMEDI_RANGEINFO,
|
||||||
(unsigned long)rangeinfo);
|
(unsigned long)rangeinfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy 32-bit cmd structure to native cmd structure. */
|
/* Copy 32-bit cmd structure to native cmd structure. */
|
||||||
static int get_compat_cmd(comedi_cmd __user *cmd,
|
static int get_compat_cmd(struct comedi_cmd __user *cmd,
|
||||||
comedi32_cmd __user *cmd32)
|
struct comedi32_cmd_struct __user *cmd32)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
union {
|
union {
|
||||||
|
@ -242,7 +239,7 @@ static int get_compat_cmd(comedi_cmd __user *cmd,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy native cmd structure to 32-bit cmd structure. */
|
/* 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;
|
int err;
|
||||||
unsigned int temp;
|
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. */
|
/* Handle 32-bit COMEDI_CMD ioctl. */
|
||||||
static int compat_cmd(struct file *file, unsigned long arg)
|
static int compat_cmd(struct file *file, unsigned long arg)
|
||||||
{
|
{
|
||||||
comedi_cmd __user *cmd;
|
struct comedi_cmd __user *cmd;
|
||||||
comedi32_cmd __user *cmd32;
|
struct comedi32_cmd_struct __user *cmd32;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
cmd32 = compat_ptr(arg);
|
cmd32 = compat_ptr(arg);
|
||||||
cmd = compat_alloc_user_space(sizeof(*cmd));
|
cmd = compat_alloc_user_space(sizeof(*cmd));
|
||||||
|
|
||||||
rc = get_compat_cmd(cmd, cmd32);
|
rc = get_compat_cmd(cmd, cmd32);
|
||||||
if (rc) {
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
}
|
|
||||||
|
|
||||||
return translated_ioctl(file, COMEDI_CMD, (unsigned long)cmd);
|
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. */
|
/* Handle 32-bit COMEDI_CMDTEST ioctl. */
|
||||||
static int compat_cmdtest(struct file *file, unsigned long arg)
|
static int compat_cmdtest(struct file *file, unsigned long arg)
|
||||||
{
|
{
|
||||||
comedi_cmd __user *cmd;
|
struct comedi_cmd __user *cmd;
|
||||||
comedi32_cmd __user *cmd32;
|
struct comedi32_cmd_struct __user *cmd32;
|
||||||
int rc, err;
|
int rc, err;
|
||||||
|
|
||||||
cmd32 = compat_ptr(arg);
|
cmd32 = compat_ptr(arg);
|
||||||
cmd = compat_alloc_user_space(sizeof(*cmd));
|
cmd = compat_alloc_user_space(sizeof(*cmd));
|
||||||
|
|
||||||
rc = get_compat_cmd(cmd, cmd32);
|
rc = get_compat_cmd(cmd, cmd32);
|
||||||
if (rc) {
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
}
|
|
||||||
|
|
||||||
rc = translated_ioctl(file, COMEDI_CMDTEST, (unsigned long)cmd);
|
rc = translated_ioctl(file, COMEDI_CMDTEST, (unsigned long)cmd);
|
||||||
if (rc < 0) {
|
if (rc < 0)
|
||||||
return rc;
|
return rc;
|
||||||
}
|
|
||||||
|
|
||||||
err = put_compat_cmd(cmd32, cmd);
|
err = put_compat_cmd(cmd32, cmd);
|
||||||
if (err) {
|
if (err)
|
||||||
rc = err;
|
rc = err;
|
||||||
}
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy 32-bit insn structure to native insn structure. */
|
/* Copy 32-bit insn structure to native insn structure. */
|
||||||
static int get_compat_insn(comedi_insn __user *insn,
|
static int get_compat_insn(struct comedi_insn __user *insn,
|
||||||
comedi32_insn __user *insn32)
|
struct comedi32_insn_struct __user *insn32)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
union {
|
union {
|
||||||
|
@ -347,9 +341,9 @@ static int get_compat_insn(comedi_insn __user *insn,
|
||||||
/* Copy insn structure. Ignore the unused members. */
|
/* Copy insn structure. Ignore the unused members. */
|
||||||
err = 0;
|
err = 0;
|
||||||
if (!access_ok(VERIFY_READ, insn32, sizeof(*insn32))
|
if (!access_ok(VERIFY_READ, insn32, sizeof(*insn32))
|
||||||
|| !access_ok(VERIFY_WRITE, insn, sizeof(*insn))) {
|
|| !access_ok(VERIFY_WRITE, insn, sizeof(*insn)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
|
||||||
err |= __get_user(temp.uint, &insn32->insn);
|
err |= __get_user(temp.uint, &insn32->insn);
|
||||||
err |= __put_user(temp.uint, &insn->insn);
|
err |= __put_user(temp.uint, &insn->insn);
|
||||||
err |= __get_user(temp.uint, &insn32->n);
|
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)
|
static int compat_insnlist(struct file *file, unsigned long arg)
|
||||||
{
|
{
|
||||||
struct combined_insnlist {
|
struct combined_insnlist {
|
||||||
comedi_insnlist insnlist;
|
struct comedi_insnlist insnlist;
|
||||||
comedi_insn insn[1];
|
struct comedi_insn insn[1];
|
||||||
} __user *s;
|
} __user *s;
|
||||||
comedi32_insnlist __user *insnlist32;
|
struct comedi32_insnlist_struct __user *insnlist32;
|
||||||
comedi32_insn __user *insn32;
|
struct comedi32_insn_struct __user *insn32;
|
||||||
compat_uptr_t uptr;
|
compat_uptr_t uptr;
|
||||||
unsigned int n_insns, n;
|
unsigned int n_insns, n;
|
||||||
int err, rc;
|
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(n_insns, &insnlist32->n_insns);
|
||||||
err |= __get_user(uptr, &insnlist32->insns);
|
err |= __get_user(uptr, &insnlist32->insns);
|
||||||
insn32 = compat_ptr(uptr);
|
insn32 = compat_ptr(uptr);
|
||||||
if (err) {
|
if (err)
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
|
||||||
|
|
||||||
/* Allocate user memory to copy insnlist and insns into. */
|
/* Allocate user memory to copy insnlist and insns into. */
|
||||||
s = compat_alloc_user_space(offsetof(struct combined_insnlist,
|
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(n_insns, &s->insnlist.n_insns);
|
||||||
err |= __put_user(&s->insn[0], &s->insnlist.insns);
|
err |= __put_user(&s->insn[0], &s->insnlist.insns);
|
||||||
if (err) {
|
if (err)
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
|
||||||
|
|
||||||
/* Copy insn structures. */
|
/* Copy insn structures. */
|
||||||
for (n = 0; n < n_insns; n++) {
|
for (n = 0; n < n_insns; n++) {
|
||||||
rc = get_compat_insn(&s->insn[n], &insn32[n]);
|
rc = get_compat_insn(&s->insn[n], &insn32[n]);
|
||||||
if (rc) {
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return translated_ioctl(file, COMEDI_INSNLIST,
|
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. */
|
/* Handle 32-bit COMEDI_INSN ioctl. */
|
||||||
static int compat_insn(struct file *file, unsigned long arg)
|
static int compat_insn(struct file *file, unsigned long arg)
|
||||||
{
|
{
|
||||||
comedi_insn __user *insn;
|
struct comedi_insn __user *insn;
|
||||||
comedi32_insn __user *insn32;
|
struct comedi32_insn_struct __user *insn32;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
insn32 = compat_ptr(arg);
|
insn32 = compat_ptr(arg);
|
||||||
insn = compat_alloc_user_space(sizeof(*insn));
|
insn = compat_alloc_user_space(sizeof(*insn));
|
||||||
|
|
||||||
rc = get_compat_insn(insn, insn32);
|
rc = get_compat_insn(insn, insn32);
|
||||||
if (rc) {
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
}
|
|
||||||
|
|
||||||
return translated_ioctl(file, COMEDI_INSN, (unsigned long)insn);
|
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;
|
int rc;
|
||||||
|
|
||||||
/* Make sure we are dealing with a Comedi device. */
|
/* 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;
|
return -ENOTTY;
|
||||||
}
|
|
||||||
rc = raw_ioctl(file, cmd, arg);
|
rc = raw_ioctl(file, cmd, arg);
|
||||||
/* Do not return -ENOIOCTLCMD. */
|
/* Do not return -ENOIOCTLCMD. */
|
||||||
if (rc == -ENOIOCTLCMD) {
|
if (rc == -ENOIOCTLCMD)
|
||||||
rc = -ENOTTY;
|
rc = -ENOTTY;
|
||||||
}
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -59,33 +59,39 @@ int comedi_debug;
|
||||||
module_param(comedi_debug, int, 0644);
|
module_param(comedi_debug, int, 0644);
|
||||||
#endif
|
#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 DEFINE_SPINLOCK(comedi_file_info_table_lock);
|
||||||
static struct comedi_device_file_info
|
static struct comedi_device_file_info
|
||||||
*comedi_file_info_table[COMEDI_NUM_MINORS];
|
*comedi_file_info_table[COMEDI_NUM_MINORS];
|
||||||
|
|
||||||
static int do_devconfig_ioctl(comedi_device *dev, comedi_devconfig *arg);
|
static int do_devconfig_ioctl(struct comedi_device *dev, struct comedi_devconfig *arg);
|
||||||
static int do_bufconfig_ioctl(comedi_device *dev, void *arg);
|
static int do_bufconfig_ioctl(struct comedi_device *dev, void *arg);
|
||||||
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);
|
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);
|
void *file);
|
||||||
static int do_chaninfo_ioctl(comedi_device *dev, comedi_chaninfo *arg);
|
static int do_chaninfo_ioctl(struct comedi_device *dev, struct comedi_chaninfo *arg);
|
||||||
static int do_bufinfo_ioctl(comedi_device *dev, void *arg);
|
static int do_bufinfo_ioctl(struct comedi_device *dev, void *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);
|
||||||
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);
|
||||||
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);
|
||||||
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);
|
||||||
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);
|
||||||
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);
|
||||||
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);
|
||||||
static int do_poll_ioctl(comedi_device *dev, unsigned int subd, 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);
|
extern void do_become_nonbusy(struct comedi_device *dev, struct comedi_subdevice *s);
|
||||||
static int do_cancel(comedi_device *dev, 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 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
|
#ifdef HAVE_UNLOCKED_IOCTL
|
||||||
static long comedi_unlocked_ioctl(struct file *file, unsigned int cmd,
|
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);
|
const unsigned minor = iminor(file->f_dentry->d_inode);
|
||||||
struct comedi_device_file_info *dev_file_info =
|
struct comedi_device_file_info *dev_file_info =
|
||||||
comedi_get_device_file_info(minor);
|
comedi_get_device_file_info(minor);
|
||||||
comedi_device *dev = dev_file_info->device;
|
struct comedi_device *dev;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
if (dev_file_info == NULL || dev_file_info->device == NULL)
|
||||||
|
return -ENODEV;
|
||||||
|
dev = dev_file_info->device;
|
||||||
|
|
||||||
mutex_lock(&dev->mutex);
|
mutex_lock(&dev->mutex);
|
||||||
|
|
||||||
/* Device config is special, because it must work on
|
/* Device config is special, because it must work on
|
||||||
|
@ -182,9 +192,9 @@ done:
|
||||||
writes:
|
writes:
|
||||||
none
|
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;
|
int ret;
|
||||||
unsigned char *aux_data = NULL;
|
unsigned char *aux_data = NULL;
|
||||||
int aux_len;
|
int aux_len;
|
||||||
|
@ -203,7 +213,7 @@ static int do_devconfig_ioctl(comedi_device *dev, comedi_devconfig *arg)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (copy_from_user(&it, arg, sizeof(comedi_devconfig)))
|
if (copy_from_user(&it, arg, sizeof(struct comedi_devconfig)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
it.board_name[COMEDI_NAMELEN - 1] = 0;
|
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
|
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;
|
struct comedi_bufconfig bc;
|
||||||
comedi_async *async;
|
struct comedi_async *async;
|
||||||
comedi_subdevice *s;
|
struct comedi_subdevice *s;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if (copy_from_user(&bc, arg, sizeof(comedi_bufconfig)))
|
if (copy_from_user(&bc, arg, sizeof(struct comedi_bufconfig)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
if (bc.subdevice >= dev->n_subdevices || bc.subdevice < 0)
|
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;
|
bc.maximum_size = async->max_bufsize;
|
||||||
|
|
||||||
copyback:
|
copyback:
|
||||||
if (copy_to_user(arg, &bc, sizeof(comedi_bufconfig)))
|
if (copy_to_user(arg, &bc, sizeof(struct comedi_bufconfig)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -350,16 +360,16 @@ copyback:
|
||||||
devinfo structure
|
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)
|
struct file *file)
|
||||||
{
|
{
|
||||||
comedi_devinfo devinfo;
|
struct comedi_devinfo devinfo;
|
||||||
const unsigned minor = iminor(file->f_dentry->d_inode);
|
const unsigned minor = iminor(file->f_dentry->d_inode);
|
||||||
struct comedi_device_file_info *dev_file_info =
|
struct comedi_device_file_info *dev_file_info =
|
||||||
comedi_get_device_file_info(minor);
|
comedi_get_device_file_info(minor);
|
||||||
comedi_subdevice *read_subdev =
|
struct comedi_subdevice *read_subdev =
|
||||||
comedi_get_read_subdevice(dev_file_info);
|
comedi_get_read_subdevice(dev_file_info);
|
||||||
comedi_subdevice *write_subdev =
|
struct comedi_subdevice *write_subdev =
|
||||||
comedi_get_write_subdevice(dev_file_info);
|
comedi_get_write_subdevice(dev_file_info);
|
||||||
|
|
||||||
memset(&devinfo, 0, sizeof(devinfo));
|
memset(&devinfo, 0, sizeof(devinfo));
|
||||||
|
@ -380,7 +390,7 @@ static int do_devinfo_ioctl(comedi_device *dev, comedi_devinfo *arg,
|
||||||
else
|
else
|
||||||
devinfo.write_subdevice = -1;
|
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 -EFAULT;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -400,14 +410,14 @@ static int do_devinfo_ioctl(comedi_device *dev, comedi_devinfo *arg,
|
||||||
array of subdevice info structures at 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)
|
void *file)
|
||||||
{
|
{
|
||||||
int ret, i;
|
int ret, i;
|
||||||
comedi_subdinfo *tmp, *us;
|
struct comedi_subdinfo *tmp, *us;
|
||||||
comedi_subdevice *s;
|
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)
|
if (!tmp)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
@ -459,7 +469,7 @@ static int do_subdinfo_ioctl(comedi_device *dev, comedi_subdinfo *arg,
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = copy_to_user(arg, tmp,
|
ret = copy_to_user(arg, tmp,
|
||||||
dev->n_subdevices * sizeof(comedi_subdinfo));
|
dev->n_subdevices * sizeof(struct comedi_subdinfo));
|
||||||
|
|
||||||
kfree(tmp);
|
kfree(tmp);
|
||||||
|
|
||||||
|
@ -480,12 +490,12 @@ static int do_subdinfo_ioctl(comedi_device *dev, comedi_subdinfo *arg,
|
||||||
arrays at elements of chaninfo structure
|
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;
|
struct comedi_subdevice *s;
|
||||||
comedi_chaninfo it;
|
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;
|
return -EFAULT;
|
||||||
|
|
||||||
if (it.subdev >= dev->n_subdevices)
|
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)
|
if (s->maxdata || !s->maxdata_list)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (copy_to_user(it.maxdata_list, s->maxdata_list,
|
if (copy_to_user(it.maxdata_list, s->maxdata_list,
|
||||||
s->n_chan * sizeof(lsampl_t)))
|
s->n_chan * sizeof(unsigned int)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -544,13 +554,13 @@ static int do_chaninfo_ioctl(comedi_device *dev, comedi_chaninfo *arg)
|
||||||
modified bufinfo at 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;
|
struct comedi_bufinfo bi;
|
||||||
comedi_subdevice *s;
|
struct comedi_subdevice *s;
|
||||||
comedi_async *async;
|
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;
|
return -EFAULT;
|
||||||
|
|
||||||
if (bi.subdevice >= dev->n_subdevices || bi.subdevice < 0)
|
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;
|
bi.buf_read_ptr = async->buf_read_ptr;
|
||||||
|
|
||||||
copyback:
|
copyback:
|
||||||
if (copy_to_user(arg, &bi, sizeof(comedi_bufinfo)))
|
if (copy_to_user(arg, &bi, sizeof(struct comedi_bufinfo)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
return 0;
|
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);
|
void *file);
|
||||||
/*
|
/*
|
||||||
* COMEDI_INSNLIST
|
* COMEDI_INSNLIST
|
||||||
|
@ -616,25 +626,25 @@ static int parse_insn(comedi_device *dev, comedi_insn *insn, lsampl_t *data,
|
||||||
*/
|
*/
|
||||||
/* arbitrary limits */
|
/* arbitrary limits */
|
||||||
#define MAX_SAMPLES 256
|
#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;
|
struct comedi_insnlist insnlist;
|
||||||
comedi_insn *insns = NULL;
|
struct comedi_insn *insns = NULL;
|
||||||
lsampl_t *data = NULL;
|
unsigned int *data = NULL;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
int ret = 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;
|
return -EFAULT;
|
||||||
|
|
||||||
data = kmalloc(sizeof(lsampl_t) * MAX_SAMPLES, GFP_KERNEL);
|
data = kmalloc(sizeof(unsigned int) * MAX_SAMPLES, GFP_KERNEL);
|
||||||
if (!data) {
|
if (!data) {
|
||||||
DPRINTK("kmalloc failed\n");
|
DPRINTK("kmalloc failed\n");
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto error;
|
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) {
|
if (!insns) {
|
||||||
DPRINTK("kmalloc failed\n");
|
DPRINTK("kmalloc failed\n");
|
||||||
ret = -ENOMEM;
|
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,
|
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");
|
DPRINTK("copy_from_user failed\n");
|
||||||
ret = -EFAULT;
|
ret = -EFAULT;
|
||||||
goto error;
|
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 (insns[i].insn & INSN_MASK_WRITE) {
|
||||||
if (copy_from_user(data, insns[i].data,
|
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");
|
DPRINTK("copy_from_user failed\n");
|
||||||
ret = -EFAULT;
|
ret = -EFAULT;
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -667,7 +677,7 @@ static int do_insnlist_ioctl(comedi_device *dev, void *arg, void *file)
|
||||||
goto error;
|
goto error;
|
||||||
if (insns[i].insn & INSN_MASK_READ) {
|
if (insns[i].insn & INSN_MASK_READ) {
|
||||||
if (copy_to_user(insns[i].data, data,
|
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");
|
DPRINTK("copy_to_user failed\n");
|
||||||
ret = -EFAULT;
|
ret = -EFAULT;
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -686,7 +696,7 @@ error:
|
||||||
return i;
|
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)
|
if (insn->n < 1)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -747,10 +757,10 @@ static int check_insn_config_length(comedi_insn *insn, lsampl_t *data)
|
||||||
return -EINVAL;
|
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)
|
void *file)
|
||||||
{
|
{
|
||||||
comedi_subdevice *s;
|
struct comedi_subdevice *s;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
@ -815,7 +825,7 @@ static int parse_insn(comedi_device *dev, comedi_insn *insn, lsampl_t *data,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* a subdevice instruction */
|
/* a subdevice instruction */
|
||||||
lsampl_t maxdata;
|
unsigned int maxdata;
|
||||||
|
|
||||||
if (insn->subdev >= dev->n_subdevices) {
|
if (insn->subdev >= dev->n_subdevices) {
|
||||||
DPRINTK("subdevice %d out of range\n", insn->subdev);
|
DPRINTK("subdevice %d out of range\n", insn->subdev);
|
||||||
|
@ -901,25 +911,25 @@ out:
|
||||||
* pointer to insn
|
* pointer to insn
|
||||||
*
|
*
|
||||||
* reads:
|
* reads:
|
||||||
* comedi_insn struct at arg
|
* struct comedi_insn struct at arg
|
||||||
* data (for writes)
|
* data (for writes)
|
||||||
*
|
*
|
||||||
* writes:
|
* writes:
|
||||||
* data (for reads)
|
* 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;
|
struct comedi_insn insn;
|
||||||
lsampl_t *data = NULL;
|
unsigned int *data = NULL;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
data = kmalloc(sizeof(lsampl_t) * MAX_SAMPLES, GFP_KERNEL);
|
data = kmalloc(sizeof(unsigned int) * MAX_SAMPLES, GFP_KERNEL);
|
||||||
if (!data) {
|
if (!data) {
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (copy_from_user(&insn, arg, sizeof(comedi_insn))) {
|
if (copy_from_user(&insn, arg, sizeof(struct comedi_insn))) {
|
||||||
ret = -EFAULT;
|
ret = -EFAULT;
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
@ -928,7 +938,7 @@ static int do_insn_ioctl(comedi_device *dev, void *arg, void *file)
|
||||||
if (insn.n > MAX_SAMPLES)
|
if (insn.n > MAX_SAMPLES)
|
||||||
insn.n = MAX_SAMPLES;
|
insn.n = MAX_SAMPLES;
|
||||||
if (insn.insn & INSN_MASK_WRITE) {
|
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;
|
ret = -EFAULT;
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
@ -937,7 +947,7 @@ static int do_insn_ioctl(comedi_device *dev, void *arg, void *file)
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto error;
|
goto error;
|
||||||
if (insn.insn & INSN_MASK_READ) {
|
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;
|
ret = -EFAULT;
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
@ -965,15 +975,15 @@ error:
|
||||||
modified cmd structure at arg
|
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;
|
struct comedi_cmd user_cmd;
|
||||||
comedi_subdevice *s;
|
struct comedi_subdevice *s;
|
||||||
comedi_async *async;
|
struct comedi_async *async;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
unsigned int *chanlist_saver = 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");
|
DPRINTK("bad cmd address\n");
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
|
@ -1062,7 +1072,7 @@ static int do_cmd_ioctl(comedi_device *dev, void *arg, void *file)
|
||||||
/* restore chanlist pointer before copying back */
|
/* restore chanlist pointer before copying back */
|
||||||
user_cmd.chanlist = chanlist_saver;
|
user_cmd.chanlist = chanlist_saver;
|
||||||
user_cmd.data = NULL;
|
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");
|
DPRINTK("fault writing cmd\n");
|
||||||
ret = -EFAULT;
|
ret = -EFAULT;
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
@ -1119,15 +1129,15 @@ cleanup:
|
||||||
modified cmd structure at arg
|
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;
|
struct comedi_cmd user_cmd;
|
||||||
comedi_subdevice *s;
|
struct comedi_subdevice *s;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
unsigned int *chanlist = NULL;
|
unsigned int *chanlist = NULL;
|
||||||
unsigned int *chanlist_saver = 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");
|
DPRINTK("bad cmd address\n");
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
|
@ -1191,7 +1201,7 @@ static int do_cmdtest_ioctl(comedi_device *dev, void *arg, void *file)
|
||||||
/* restore chanlist pointer before copying back */
|
/* restore chanlist pointer before copying back */
|
||||||
user_cmd.chanlist = chanlist_saver;
|
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");
|
DPRINTK("bad cmd address\n");
|
||||||
ret = -EFAULT;
|
ret = -EFAULT;
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
@ -1217,11 +1227,11 @@ cleanup:
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
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;
|
int ret = 0;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
comedi_subdevice *s;
|
struct comedi_subdevice *s;
|
||||||
|
|
||||||
if (arg >= dev->n_subdevices)
|
if (arg >= dev->n_subdevices)
|
||||||
return -EINVAL;
|
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
|
This function isn't protected by the semaphore, since
|
||||||
we already own the lock.
|
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)
|
if (arg >= dev->n_subdevices)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -1301,9 +1311,9 @@ static int do_unlock_ioctl(comedi_device *dev, unsigned int arg, void *file)
|
||||||
nothing
|
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)
|
if (arg >= dev->n_subdevices)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -1337,9 +1347,9 @@ static int do_cancel_ioctl(comedi_device *dev, unsigned int arg, void *file)
|
||||||
nothing
|
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)
|
if (arg >= dev->n_subdevices)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -1360,7 +1370,7 @@ static int do_poll_ioctl(comedi_device *dev, unsigned int arg, void *file)
|
||||||
return -EINVAL;
|
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;
|
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)
|
void comedi_unmap(struct vm_area_struct *area)
|
||||||
{
|
{
|
||||||
comedi_async *async;
|
struct comedi_async *async;
|
||||||
comedi_device *dev;
|
struct comedi_device *dev;
|
||||||
|
|
||||||
async = area->vm_private_data;
|
async = area->vm_private_data;
|
||||||
dev = async->subdevice->device;
|
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);
|
const unsigned minor = iminor(file->f_dentry->d_inode);
|
||||||
struct comedi_device_file_info *dev_file_info =
|
struct comedi_device_file_info *dev_file_info =
|
||||||
comedi_get_device_file_info(minor);
|
comedi_get_device_file_info(minor);
|
||||||
comedi_device *dev = dev_file_info->device;
|
struct comedi_device *dev = dev_file_info->device;
|
||||||
comedi_async *async = NULL;
|
struct comedi_async *async = NULL;
|
||||||
unsigned long start = vma->vm_start;
|
unsigned long start = vma->vm_start;
|
||||||
unsigned long size;
|
unsigned long size;
|
||||||
int n_pages;
|
int n_pages;
|
||||||
int i;
|
int i;
|
||||||
int retval;
|
int retval;
|
||||||
comedi_subdevice *s;
|
struct comedi_subdevice *s;
|
||||||
|
|
||||||
mutex_lock(&dev->mutex);
|
mutex_lock(&dev->mutex);
|
||||||
if (!dev->attached) {
|
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);
|
const unsigned minor = iminor(file->f_dentry->d_inode);
|
||||||
struct comedi_device_file_info *dev_file_info =
|
struct comedi_device_file_info *dev_file_info =
|
||||||
comedi_get_device_file_info(minor);
|
comedi_get_device_file_info(minor);
|
||||||
comedi_device *dev = dev_file_info->device;
|
struct comedi_device *dev = dev_file_info->device;
|
||||||
comedi_subdevice *read_subdev;
|
struct comedi_subdevice *read_subdev;
|
||||||
comedi_subdevice *write_subdev;
|
struct comedi_subdevice *write_subdev;
|
||||||
|
|
||||||
mutex_lock(&dev->mutex);
|
mutex_lock(&dev->mutex);
|
||||||
if (!dev->attached) {
|
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,
|
static ssize_t comedi_write(struct file *file, const char *buf, size_t nbytes,
|
||||||
loff_t *offset)
|
loff_t *offset)
|
||||||
{
|
{
|
||||||
comedi_subdevice *s;
|
struct comedi_subdevice *s;
|
||||||
comedi_async *async;
|
struct comedi_async *async;
|
||||||
int n, m, count = 0, retval = 0;
|
int n, m, count = 0, retval = 0;
|
||||||
DECLARE_WAITQUEUE(wait, current);
|
DECLARE_WAITQUEUE(wait, current);
|
||||||
const unsigned minor = iminor(file->f_dentry->d_inode);
|
const unsigned minor = iminor(file->f_dentry->d_inode);
|
||||||
struct comedi_device_file_info *dev_file_info =
|
struct comedi_device_file_info *dev_file_info =
|
||||||
comedi_get_device_file_info(minor);
|
comedi_get_device_file_info(minor);
|
||||||
comedi_device *dev = dev_file_info->device;
|
struct comedi_device *dev = dev_file_info->device;
|
||||||
|
|
||||||
if (!dev->attached) {
|
if (!dev->attached) {
|
||||||
DPRINTK("no driver configured on comedi%i\n", dev->minor);
|
DPRINTK("no driver configured on comedi%i\n", dev->minor);
|
||||||
|
@ -1615,14 +1625,14 @@ done:
|
||||||
static ssize_t comedi_read(struct file *file, char *buf, size_t nbytes,
|
static ssize_t comedi_read(struct file *file, char *buf, size_t nbytes,
|
||||||
loff_t *offset)
|
loff_t *offset)
|
||||||
{
|
{
|
||||||
comedi_subdevice *s;
|
struct comedi_subdevice *s;
|
||||||
comedi_async *async;
|
struct comedi_async *async;
|
||||||
int n, m, count = 0, retval = 0;
|
int n, m, count = 0, retval = 0;
|
||||||
DECLARE_WAITQUEUE(wait, current);
|
DECLARE_WAITQUEUE(wait, current);
|
||||||
const unsigned minor = iminor(file->f_dentry->d_inode);
|
const unsigned minor = iminor(file->f_dentry->d_inode);
|
||||||
struct comedi_device_file_info *dev_file_info =
|
struct comedi_device_file_info *dev_file_info =
|
||||||
comedi_get_device_file_info(minor);
|
comedi_get_device_file_info(minor);
|
||||||
comedi_device *dev = dev_file_info->device;
|
struct comedi_device *dev = dev_file_info->device;
|
||||||
|
|
||||||
if (!dev->attached) {
|
if (!dev->attached) {
|
||||||
DPRINTK("no driver configured on comedi%i\n", dev->minor);
|
DPRINTK("no driver configured on comedi%i\n", dev->minor);
|
||||||
|
@ -1723,9 +1733,9 @@ done:
|
||||||
/*
|
/*
|
||||||
This function restores a subdevice to an idle state.
|
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);
|
comedi_set_subdevice_runflags(s, SRF_RUNNING, 0);
|
||||||
#ifdef CONFIG_COMEDI_RT
|
#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)
|
static int comedi_open(struct inode *inode, struct file *file)
|
||||||
{
|
{
|
||||||
char mod[32];
|
|
||||||
const unsigned minor = iminor(inode);
|
const unsigned minor = iminor(inode);
|
||||||
struct comedi_device_file_info *dev_file_info =
|
struct comedi_device_file_info *dev_file_info =
|
||||||
comedi_get_device_file_info(minor);
|
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) {
|
if (dev == NULL) {
|
||||||
DPRINTK("invalid minor number\n");
|
DPRINTK("invalid minor number\n");
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
@ -1783,10 +1793,9 @@ static int comedi_open(struct inode *inode, struct file *file)
|
||||||
|
|
||||||
dev->in_request_module = 1;
|
dev->in_request_module = 1;
|
||||||
|
|
||||||
sprintf(mod, "char-major-%i-%i", COMEDI_MAJOR, dev->minor);
|
|
||||||
#ifdef CONFIG_KMOD
|
#ifdef CONFIG_KMOD
|
||||||
mutex_unlock(&dev->mutex);
|
mutex_unlock(&dev->mutex);
|
||||||
request_module(mod);
|
request_module("char-major-%i-%i", COMEDI_MAJOR, dev->minor);
|
||||||
mutex_lock(&dev->mutex);
|
mutex_lock(&dev->mutex);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1823,8 +1832,8 @@ static int comedi_close(struct inode *inode, struct file *file)
|
||||||
const unsigned minor = iminor(inode);
|
const unsigned minor = iminor(inode);
|
||||||
struct comedi_device_file_info *dev_file_info =
|
struct comedi_device_file_info *dev_file_info =
|
||||||
comedi_get_device_file_info(minor);
|
comedi_get_device_file_info(minor);
|
||||||
comedi_device *dev = dev_file_info->device;
|
struct comedi_device *dev = dev_file_info->device;
|
||||||
comedi_subdevice *s = NULL;
|
struct comedi_subdevice *s = NULL;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
mutex_lock(&dev->mutex);
|
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 =
|
struct comedi_device_file_info *dev_file_info =
|
||||||
comedi_get_device_file_info(minor);
|
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);
|
return fasync_helper(fd, file, on, &dev->async_queue);
|
||||||
}
|
}
|
||||||
|
@ -1893,7 +1902,7 @@ static void comedi_cleanup_legacy_minors(void)
|
||||||
{
|
{
|
||||||
unsigned i;
|
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);
|
comedi_free_board_minor(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1905,6 +1914,22 @@ static int __init comedi_init(void)
|
||||||
printk(KERN_INFO "comedi: version " COMEDI_RELEASE
|
printk(KERN_INFO "comedi: version " COMEDI_RELEASE
|
||||||
" - http://www.comedi.org\n");
|
" - 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,
|
memset(comedi_file_info_table, 0,
|
||||||
sizeof(struct comedi_device_file_info *) * COMEDI_NUM_MINORS);
|
sizeof(struct comedi_device_file_info *) * COMEDI_NUM_MINORS);
|
||||||
|
|
||||||
|
@ -1933,7 +1958,7 @@ static int __init comedi_init(void)
|
||||||
comedi_proc_init();
|
comedi_proc_init();
|
||||||
|
|
||||||
/* create devices files for legacy/manual use */
|
/* 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;
|
int minor;
|
||||||
minor = comedi_alloc_board_minor(NULL);
|
minor = comedi_alloc_board_minor(NULL);
|
||||||
if (minor < 0) {
|
if (minor < 0) {
|
||||||
|
@ -1975,15 +2000,15 @@ static void __exit comedi_cleanup(void)
|
||||||
module_init(comedi_init);
|
module_init(comedi_init);
|
||||||
module_exit(comedi_cleanup);
|
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,
|
rt_printk("comedi%d: %s: %s\n", dev->minor, dev->driver->driver_name,
|
||||||
s);
|
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 = 0;
|
||||||
unsigned runflags_mask = 0;
|
unsigned runflags_mask = 0;
|
||||||
|
|
||||||
|
@ -2042,7 +2067,7 @@ void comedi_event(comedi_device *dev, comedi_subdevice *s)
|
||||||
s->async->events = 0;
|
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 bits)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
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);
|
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 long flags;
|
||||||
unsigned runflags;
|
unsigned runflags;
|
||||||
|
@ -2064,9 +2089,9 @@ unsigned comedi_get_subdevice_runflags(comedi_subdevice *s)
|
||||||
return runflags;
|
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;
|
int i;
|
||||||
|
|
||||||
if (!dev->attached)
|
if (!dev->attached)
|
||||||
|
@ -2083,15 +2108,15 @@ static int is_device_busy(comedi_device *dev)
|
||||||
return 0;
|
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);
|
spin_lock_init(&dev->spinlock);
|
||||||
mutex_init(&dev->mutex);
|
mutex_init(&dev->mutex);
|
||||||
dev->minor = -1;
|
dev->minor = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void comedi_device_cleanup(comedi_device *dev)
|
void comedi_device_cleanup(struct comedi_device *dev)
|
||||||
{
|
{
|
||||||
if (dev == NULL)
|
if (dev == NULL)
|
||||||
return;
|
return;
|
||||||
|
@ -2105,13 +2130,13 @@ int comedi_alloc_board_minor(struct device *hardware_device)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
struct comedi_device_file_info *info;
|
struct comedi_device_file_info *info;
|
||||||
device_create_result_type *csdev;
|
struct device *csdev;
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
|
||||||
info = kzalloc(sizeof(struct comedi_device_file_info), GFP_KERNEL);
|
info = kzalloc(sizeof(struct comedi_device_file_info), GFP_KERNEL);
|
||||||
if (info == NULL)
|
if (info == NULL)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
info->device = kzalloc(sizeof(comedi_device), GFP_KERNEL);
|
info->device = kzalloc(sizeof(struct comedi_device), GFP_KERNEL);
|
||||||
if (info->device == NULL) {
|
if (info->device == NULL) {
|
||||||
kfree(info);
|
kfree(info);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
@ -2155,7 +2180,7 @@ void comedi_free_board_minor(unsigned minor)
|
||||||
comedi_spin_unlock_irqrestore(&comedi_file_info_table_lock, flags);
|
comedi_spin_unlock_irqrestore(&comedi_file_info_table_lock, flags);
|
||||||
|
|
||||||
if (info) {
|
if (info) {
|
||||||
comedi_device *dev = info->device;
|
struct comedi_device *dev = info->device;
|
||||||
if (dev) {
|
if (dev) {
|
||||||
if (dev->class_dev) {
|
if (dev->class_dev) {
|
||||||
device_destroy(comedi_class,
|
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;
|
unsigned long flags;
|
||||||
struct comedi_device_file_info *info;
|
struct comedi_device_file_info *info;
|
||||||
device_create_result_type *csdev;
|
struct device *csdev;
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
|
||||||
info = kmalloc(sizeof(struct comedi_device_file_info), GFP_KERNEL);
|
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->read_subdevice = s;
|
||||||
info->write_subdevice = s;
|
info->write_subdevice = s;
|
||||||
comedi_spin_lock_irqsave(&comedi_file_info_table_lock, flags);
|
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) {
|
if (comedi_file_info_table[i] == NULL) {
|
||||||
comedi_file_info_table[i] = info;
|
comedi_file_info_table[i] = info;
|
||||||
break;
|
break;
|
||||||
|
@ -2206,7 +2231,7 @@ int comedi_alloc_subdevice_minor(comedi_device *dev, comedi_subdevice *s)
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
void comedi_free_subdevice_minor(comedi_subdevice *s)
|
void comedi_free_subdevice_minor(struct comedi_subdevice *s)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
struct comedi_device_file_info *info;
|
struct comedi_device_file_info *info;
|
||||||
|
|
|
@ -4,5 +4,6 @@
|
||||||
|
|
||||||
extern struct class *comedi_class;
|
extern struct class *comedi_class;
|
||||||
extern const struct file_operations comedi_fops;
|
extern const struct file_operations comedi_fops;
|
||||||
|
extern int comedi_autoconfig;
|
||||||
|
|
||||||
#endif /* _COMEDI_FOPS_H */
|
#endif /* _COMEDI_FOPS_H */
|
||||||
|
|
|
@ -31,12 +31,12 @@
|
||||||
/* for drivers */
|
/* for drivers */
|
||||||
EXPORT_SYMBOL(comedi_driver_register);
|
EXPORT_SYMBOL(comedi_driver_register);
|
||||||
EXPORT_SYMBOL(comedi_driver_unregister);
|
EXPORT_SYMBOL(comedi_driver_unregister);
|
||||||
//EXPORT_SYMBOL(comedi_bufcheck);
|
/* EXPORT_SYMBOL(comedi_bufcheck); */
|
||||||
//EXPORT_SYMBOL(comedi_done);
|
/* EXPORT_SYMBOL(comedi_done); */
|
||||||
//EXPORT_SYMBOL(comedi_error_done);
|
/* EXPORT_SYMBOL(comedi_error_done); */
|
||||||
EXPORT_SYMBOL(comedi_error);
|
EXPORT_SYMBOL(comedi_error);
|
||||||
//EXPORT_SYMBOL(comedi_eobuf);
|
/* EXPORT_SYMBOL(comedi_eobuf); */
|
||||||
//EXPORT_SYMBOL(comedi_eos);
|
/* EXPORT_SYMBOL(comedi_eos); */
|
||||||
EXPORT_SYMBOL(comedi_event);
|
EXPORT_SYMBOL(comedi_event);
|
||||||
EXPORT_SYMBOL(comedi_get_subdevice_runflags);
|
EXPORT_SYMBOL(comedi_get_subdevice_runflags);
|
||||||
EXPORT_SYMBOL(comedi_set_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_free_board_minor);
|
||||||
EXPORT_SYMBOL_GPL(comedi_pci_auto_config);
|
EXPORT_SYMBOL_GPL(comedi_pci_auto_config);
|
||||||
EXPORT_SYMBOL_GPL(comedi_pci_auto_unconfig);
|
EXPORT_SYMBOL_GPL(comedi_pci_auto_unconfig);
|
||||||
|
EXPORT_SYMBOL_GPL(comedi_usb_auto_config);
|
||||||
|
EXPORT_SYMBOL_GPL(comedi_usb_auto_unconfig);
|
||||||
|
|
||||||
/* for kcomedilib */
|
/* for kcomedilib */
|
||||||
EXPORT_SYMBOL(check_chanlist);
|
EXPORT_SYMBOL(check_chanlist);
|
||||||
|
|
|
@ -28,7 +28,6 @@
|
||||||
#error comedi_rt.h should only be included by comedidev.h
|
#error comedi_rt.h should only be included by comedidev.h
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <linux/version.h>
|
|
||||||
#include <linux/kdev_t.h>
|
#include <linux/kdev_t.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
|
@ -59,12 +58,12 @@
|
||||||
|
|
||||||
int comedi_request_irq(unsigned int irq, irqreturn_t(*handler) (int,
|
int comedi_request_irq(unsigned int irq, irqreturn_t(*handler) (int,
|
||||||
void *PT_REGS_ARG), unsigned long flags, const char *device,
|
void *PT_REGS_ARG), unsigned long flags, const char *device,
|
||||||
comedi_device *dev_id);
|
struct comedi_device *dev_id);
|
||||||
void comedi_free_irq(unsigned int irq, comedi_device *dev_id);
|
void comedi_free_irq(unsigned int irq, struct comedi_device *dev_id);
|
||||||
void comedi_rt_init(void);
|
void comedi_rt_init(void);
|
||||||
void comedi_rt_cleanup(void);
|
void comedi_rt_cleanup(void);
|
||||||
int comedi_switch_to_rt(comedi_device *dev);
|
int comedi_switch_to_rt(struct comedi_device *dev);
|
||||||
void comedi_switch_to_non_rt(comedi_device *dev);
|
void comedi_switch_to_non_rt(struct comedi_device *dev);
|
||||||
void comedi_rt_pend_wakeup(wait_queue_head_t *q);
|
void comedi_rt_pend_wakeup(wait_queue_head_t *q);
|
||||||
extern int rt_pend_call(void (*func) (int arg1, void *arg2), int arg1,
|
extern int rt_pend_call(void (*func) (int arg1, void *arg2), int arg1,
|
||||||
void *arg2);
|
void *arg2);
|
||||||
|
|
|
@ -26,7 +26,6 @@
|
||||||
|
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/version.h>
|
|
||||||
#include <linux/kdev_t.h>
|
#include <linux/kdev_t.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
|
@ -36,7 +35,6 @@
|
||||||
#include <linux/mm.h>
|
#include <linux/mm.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/vmalloc.h>
|
#include <linux/vmalloc.h>
|
||||||
#include <linux/mm.h>
|
|
||||||
#include "interrupt.h"
|
#include "interrupt.h"
|
||||||
#include <linux/dma-mapping.h>
|
#include <linux/dma-mapping.h>
|
||||||
#include <linux/uaccess.h>
|
#include <linux/uaccess.h>
|
||||||
|
@ -55,9 +53,9 @@
|
||||||
|
|
||||||
#define COMEDI_INITCLEANUP_NOMODULE(x) \
|
#define COMEDI_INITCLEANUP_NOMODULE(x) \
|
||||||
static int __init x ## _init_module(void) \
|
static int __init x ## _init_module(void) \
|
||||||
{return comedi_driver_register(&(x));} \
|
{return comedi_driver_register(&(x)); } \
|
||||||
static void __exit x ## _cleanup_module(void) \
|
static void __exit x ## _cleanup_module(void) \
|
||||||
{comedi_driver_unregister(&(x));} \
|
{comedi_driver_unregister(&(x)); } \
|
||||||
module_init(x ## _init_module); \
|
module_init(x ## _init_module); \
|
||||||
module_exit(x ## _cleanup_module); \
|
module_exit(x ## _cleanup_module); \
|
||||||
|
|
||||||
|
@ -120,23 +118,14 @@
|
||||||
#define PCI_VENDOR_ID_MEILHAUS 0x1402
|
#define PCI_VENDOR_ID_MEILHAUS 0x1402
|
||||||
|
|
||||||
#define COMEDI_NUM_MINORS 0x100
|
#define COMEDI_NUM_MINORS 0x100
|
||||||
#define COMEDI_NUM_LEGACY_MINORS 0x10
|
|
||||||
#define COMEDI_NUM_BOARD_MINORS 0x30
|
#define COMEDI_NUM_BOARD_MINORS 0x30
|
||||||
#define COMEDI_FIRST_SUBDEVICE_MINOR COMEDI_NUM_BOARD_MINORS
|
#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...) \
|
#define COMEDI_DEVICE_CREATE(cs, parent, devt, drvdata, device, fmt...) \
|
||||||
device_create(cs, ((parent) ? (parent) : (device)), devt, drvdata, fmt)
|
device_create(cs, ((parent) ? (parent) : (device)), devt, drvdata, fmt)
|
||||||
|
|
||||||
struct comedi_subdevice_struct {
|
struct comedi_subdevice {
|
||||||
comedi_device *device;
|
struct comedi_device *device;
|
||||||
int type;
|
int type;
|
||||||
int n_chan;
|
int n_chan;
|
||||||
volatile int subdev_flags;
|
volatile int subdev_flags;
|
||||||
|
@ -144,7 +133,7 @@ struct comedi_subdevice_struct {
|
||||||
|
|
||||||
void *private;
|
void *private;
|
||||||
|
|
||||||
comedi_async *async;
|
struct comedi_async *async;
|
||||||
|
|
||||||
void *lock;
|
void *lock;
|
||||||
void *busy;
|
void *busy;
|
||||||
|
@ -153,46 +142,46 @@ struct comedi_subdevice_struct {
|
||||||
|
|
||||||
int io_bits;
|
int io_bits;
|
||||||
|
|
||||||
lsampl_t maxdata; /* if maxdata==0, use list */
|
unsigned int maxdata; /* if maxdata==0, use list */
|
||||||
const lsampl_t *maxdata_list; /* list is channel specific */
|
const unsigned int *maxdata_list; /* list is channel specific */
|
||||||
|
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
const unsigned int *flaglist;
|
const unsigned int *flaglist;
|
||||||
|
|
||||||
unsigned int settling_time_0;
|
unsigned int settling_time_0;
|
||||||
|
|
||||||
const comedi_lrange *range_table;
|
const struct comedi_lrange *range_table;
|
||||||
const comedi_lrange *const *range_table_list;
|
const struct comedi_lrange *const *range_table_list;
|
||||||
|
|
||||||
unsigned int *chanlist; /* driver-owned chanlist (not used) */
|
unsigned int *chanlist; /* driver-owned chanlist (not used) */
|
||||||
|
|
||||||
int (*insn_read) (comedi_device *, comedi_subdevice *, comedi_insn *,
|
int (*insn_read) (struct comedi_device *, struct comedi_subdevice *, struct comedi_insn *,
|
||||||
lsampl_t *);
|
unsigned int *);
|
||||||
int (*insn_write) (comedi_device *, comedi_subdevice *, comedi_insn *,
|
int (*insn_write) (struct comedi_device *, struct comedi_subdevice *, struct comedi_insn *,
|
||||||
lsampl_t *);
|
unsigned int *);
|
||||||
int (*insn_bits) (comedi_device *, comedi_subdevice *, comedi_insn *,
|
int (*insn_bits) (struct comedi_device *, struct comedi_subdevice *, struct comedi_insn *,
|
||||||
lsampl_t *);
|
unsigned int *);
|
||||||
int (*insn_config) (comedi_device *, comedi_subdevice *, comedi_insn *,
|
int (*insn_config) (struct comedi_device *, struct comedi_subdevice *, struct comedi_insn *,
|
||||||
lsampl_t *);
|
unsigned int *);
|
||||||
|
|
||||||
int (*do_cmd) (comedi_device *, comedi_subdevice *);
|
int (*do_cmd) (struct comedi_device *, struct comedi_subdevice *);
|
||||||
int (*do_cmdtest) (comedi_device *, comedi_subdevice *, comedi_cmd *);
|
int (*do_cmdtest) (struct comedi_device *, struct comedi_subdevice *, struct comedi_cmd *);
|
||||||
int (*poll) (comedi_device *, comedi_subdevice *);
|
int (*poll) (struct comedi_device *, struct comedi_subdevice *);
|
||||||
int (*cancel) (comedi_device *, comedi_subdevice *);
|
int (*cancel) (struct comedi_device *, struct comedi_subdevice *);
|
||||||
/* int (*do_lock)(comedi_device *,comedi_subdevice *); */
|
/* int (*do_lock)(struct comedi_device *,struct comedi_subdevice *); */
|
||||||
/* int (*do_unlock)(comedi_device *,comedi_subdevice *); */
|
/* int (*do_unlock)(struct comedi_device *,struct comedi_subdevice *); */
|
||||||
|
|
||||||
/* called when the buffer changes */
|
/* 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);
|
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);
|
unsigned int num_bytes, unsigned int start_chan_index);
|
||||||
enum dma_data_direction async_dma_dir;
|
enum dma_data_direction async_dma_dir;
|
||||||
|
|
||||||
unsigned int state;
|
unsigned int state;
|
||||||
|
|
||||||
device_create_result_type *class_dev;
|
struct device *class_dev;
|
||||||
int minor;
|
int minor;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -201,8 +190,8 @@ struct comedi_buf_page {
|
||||||
dma_addr_t dma_addr;
|
dma_addr_t dma_addr;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct comedi_async_struct {
|
struct comedi_async {
|
||||||
comedi_subdevice *subdevice;
|
struct comedi_subdevice *subdevice;
|
||||||
|
|
||||||
void *prealloc_buf; /* pre-allocated buffer */
|
void *prealloc_buf; /* pre-allocated buffer */
|
||||||
unsigned int prealloc_bufsz; /* buffer size, in bytes */
|
unsigned int prealloc_bufsz; /* buffer size, in bytes */
|
||||||
|
@ -232,7 +221,7 @@ struct comedi_async_struct {
|
||||||
|
|
||||||
unsigned int events; /* events that have occurred */
|
unsigned int events; /* events that have occurred */
|
||||||
|
|
||||||
comedi_cmd cmd;
|
struct comedi_cmd cmd;
|
||||||
|
|
||||||
wait_queue_head_t wait_head;
|
wait_queue_head_t wait_head;
|
||||||
|
|
||||||
|
@ -241,17 +230,17 @@ struct comedi_async_struct {
|
||||||
int (*cb_func) (unsigned int flags, void *);
|
int (*cb_func) (unsigned int flags, void *);
|
||||||
void *cb_arg;
|
void *cb_arg;
|
||||||
|
|
||||||
int (*inttrig) (comedi_device *dev, comedi_subdevice *s,
|
int (*inttrig) (struct comedi_device *dev, struct comedi_subdevice *s,
|
||||||
unsigned int x);
|
unsigned int x);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct comedi_driver_struct {
|
struct comedi_driver {
|
||||||
struct comedi_driver_struct *next;
|
struct comedi_driver *next;
|
||||||
|
|
||||||
const char *driver_name;
|
const char *driver_name;
|
||||||
struct module *module;
|
struct module *module;
|
||||||
int (*attach) (comedi_device *, comedi_devconfig *);
|
int (*attach) (struct comedi_device *, struct comedi_devconfig *);
|
||||||
int (*detach) (comedi_device *);
|
int (*detach) (struct comedi_device *);
|
||||||
|
|
||||||
/* number of elements in board_name and board_id arrays */
|
/* number of elements in board_name and board_id arrays */
|
||||||
unsigned int num_names;
|
unsigned int num_names;
|
||||||
|
@ -260,12 +249,12 @@ struct comedi_driver_struct {
|
||||||
int offset;
|
int offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct comedi_device_struct {
|
struct comedi_device {
|
||||||
int use_count;
|
int use_count;
|
||||||
comedi_driver *driver;
|
struct comedi_driver *driver;
|
||||||
void *private;
|
void *private;
|
||||||
|
|
||||||
device_create_result_type *class_dev;
|
struct device *class_dev;
|
||||||
int minor;
|
int minor;
|
||||||
/* hw_dev is passed to dma_alloc_coherent when allocating async buffers
|
/* hw_dev is passed to dma_alloc_coherent when allocating async buffers
|
||||||
* for subdevices that have async_dma_dir set to something other than
|
* 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 in_request_module;
|
||||||
|
|
||||||
int n_subdevices;
|
int n_subdevices;
|
||||||
comedi_subdevice *subdevices;
|
struct comedi_subdevice *subdevices;
|
||||||
|
|
||||||
/* dumb */
|
/* dumb */
|
||||||
unsigned long iobase;
|
unsigned long iobase;
|
||||||
unsigned int irq;
|
unsigned int irq;
|
||||||
|
|
||||||
comedi_subdevice *read_subdev;
|
struct comedi_subdevice *read_subdev;
|
||||||
comedi_subdevice *write_subdev;
|
struct comedi_subdevice *write_subdev;
|
||||||
|
|
||||||
struct fasync_struct *async_queue;
|
struct fasync_struct *async_queue;
|
||||||
|
|
||||||
void (*open) (comedi_device *dev);
|
void (*open) (struct comedi_device *dev);
|
||||||
void (*close) (comedi_device *dev);
|
void (*close) (struct comedi_device *dev);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct comedi_device_file_info {
|
struct comedi_device_file_info {
|
||||||
comedi_device *device;
|
struct comedi_device *device;
|
||||||
comedi_subdevice *read_subdevice;
|
struct comedi_subdevice *read_subdevice;
|
||||||
comedi_subdevice *write_subdevice;
|
struct comedi_subdevice *write_subdevice;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef CONFIG_COMEDI_DEBUG
|
#ifdef CONFIG_COMEDI_DEBUG
|
||||||
|
@ -312,8 +301,8 @@ static const int comedi_debug;
|
||||||
* function prototypes
|
* function prototypes
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void comedi_event(comedi_device *dev, comedi_subdevice *s);
|
void comedi_event(struct comedi_device *dev, struct comedi_subdevice *s);
|
||||||
void comedi_error(const comedi_device *dev, const char *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
|
/* 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
|
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);
|
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)
|
const struct comedi_device_file_info *info)
|
||||||
{
|
{
|
||||||
if (info->read_subdevice)
|
if (info->read_subdevice)
|
||||||
|
@ -337,7 +326,7 @@ static inline comedi_subdevice *comedi_get_read_subdevice(
|
||||||
return info->device->read_subdev;
|
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)
|
const struct comedi_device_file_info *info)
|
||||||
{
|
{
|
||||||
if (info->write_subdevice)
|
if (info->write_subdevice)
|
||||||
|
@ -347,17 +336,17 @@ static inline comedi_subdevice *comedi_get_write_subdevice(
|
||||||
return info->device->write_subdev;
|
return info->device->write_subdev;
|
||||||
}
|
}
|
||||||
|
|
||||||
void comedi_device_detach(comedi_device *dev);
|
void comedi_device_detach(struct comedi_device *dev);
|
||||||
int comedi_device_attach(comedi_device *dev, comedi_devconfig *it);
|
int comedi_device_attach(struct comedi_device *dev, struct comedi_devconfig *it);
|
||||||
int comedi_driver_register(comedi_driver *);
|
int comedi_driver_register(struct comedi_driver *);
|
||||||
int comedi_driver_unregister(comedi_driver *);
|
int comedi_driver_unregister(struct comedi_driver *);
|
||||||
|
|
||||||
void init_polling(void);
|
void init_polling(void);
|
||||||
void cleanup_polling(void);
|
void cleanup_polling(void);
|
||||||
void start_polling(comedi_device *);
|
void start_polling(struct comedi_device *);
|
||||||
void stop_polling(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);
|
new_size);
|
||||||
|
|
||||||
#ifdef CONFIG_PROC_FS
|
#ifdef CONFIG_PROC_FS
|
||||||
|
@ -386,13 +375,13 @@ enum subdevice_runflags {
|
||||||
various internal comedi functions
|
various internal comedi functions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int do_rangeinfo_ioctl(comedi_device *dev, comedi_rangeinfo *arg);
|
int do_rangeinfo_ioctl(struct comedi_device *dev, struct comedi_rangeinfo *arg);
|
||||||
int check_chanlist(comedi_subdevice *s, int n, unsigned int *chanlist);
|
int check_chanlist(struct comedi_subdevice *s, int n, unsigned int *chanlist);
|
||||||
void comedi_set_subdevice_runflags(comedi_subdevice *s, unsigned mask,
|
void comedi_set_subdevice_runflags(struct comedi_subdevice *s, unsigned mask,
|
||||||
unsigned bits);
|
unsigned bits);
|
||||||
unsigned comedi_get_subdevice_runflags(comedi_subdevice *s);
|
unsigned comedi_get_subdevice_runflags(struct comedi_subdevice *s);
|
||||||
int insn_inval(comedi_device *dev, comedi_subdevice *s,
|
int insn_inval(struct comedi_device *dev, struct comedi_subdevice *s,
|
||||||
comedi_insn *insn, lsampl_t *data);
|
struct comedi_insn *insn, unsigned int *data);
|
||||||
|
|
||||||
/* range stuff */
|
/* 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 BIP_RANGE(a) {-(a)*1e6, (a)*1e6, 0}
|
||||||
#define UNI_RANGE(a) {0, (a)*1e6, 0}
|
#define UNI_RANGE(a) {0, (a)*1e6, 0}
|
||||||
|
|
||||||
extern const comedi_lrange range_bipolar10;
|
extern const struct comedi_lrange range_bipolar10;
|
||||||
extern const comedi_lrange range_bipolar5;
|
extern const struct comedi_lrange range_bipolar5;
|
||||||
extern const comedi_lrange range_bipolar2_5;
|
extern const struct comedi_lrange range_bipolar2_5;
|
||||||
extern const comedi_lrange range_unipolar10;
|
extern const struct comedi_lrange range_unipolar10;
|
||||||
extern const comedi_lrange range_unipolar5;
|
extern const struct comedi_lrange range_unipolar5;
|
||||||
extern const comedi_lrange range_unknown;
|
extern const struct comedi_lrange range_unknown;
|
||||||
|
|
||||||
#define range_digital range_unipolar5
|
#define range_digital range_unipolar5
|
||||||
|
|
||||||
|
@ -418,21 +407,21 @@ extern const comedi_lrange range_unknown;
|
||||||
#define GCC_ZERO_LENGTH_ARRAY 0
|
#define GCC_ZERO_LENGTH_ARRAY 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct comedi_lrange_struct {
|
struct comedi_lrange {
|
||||||
int length;
|
int length;
|
||||||
comedi_krange range[GCC_ZERO_LENGTH_ARRAY];
|
struct comedi_krange range[GCC_ZERO_LENGTH_ARRAY];
|
||||||
};
|
};
|
||||||
|
|
||||||
/* some silly little inline functions */
|
/* 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 int num_subdevices)
|
||||||
{
|
{
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
|
||||||
dev->n_subdevices = num_subdevices;
|
dev->n_subdevices = num_subdevices;
|
||||||
dev->subdevices =
|
dev->subdevices =
|
||||||
kcalloc(num_subdevices, sizeof(comedi_subdevice), GFP_KERNEL);
|
kcalloc(num_subdevices, sizeof(struct comedi_subdevice), GFP_KERNEL);
|
||||||
if (!dev->subdevices)
|
if (!dev->subdevices)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
for (i = 0; i < num_subdevices; ++i) {
|
for (i = 0; i < num_subdevices; ++i) {
|
||||||
|
@ -444,7 +433,7 @@ static inline int alloc_subdevices(comedi_device *dev,
|
||||||
return 0;
|
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);
|
dev->private = kzalloc(size, GFP_KERNEL);
|
||||||
if (!dev->private)
|
if (!dev->private)
|
||||||
|
@ -452,17 +441,17 @@ static inline int alloc_private(comedi_device *dev, int size)
|
||||||
return 0;
|
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)
|
if (subd->subdev_flags & SDF_LSAMPL)
|
||||||
return sizeof(lsampl_t);
|
return sizeof(unsigned int);
|
||||||
else
|
else
|
||||||
return sizeof(sampl_t);
|
return sizeof(short);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* must be used in attach to set dev->hw_dev if you wish to dma directly
|
/* must be used in attach to set dev->hw_dev if you wish to dma directly
|
||||||
into comedi's buffer */
|
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)
|
if (dev->hw_dev)
|
||||||
put_device(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_put(struct comedi_async *async, short x);
|
||||||
int comedi_buf_get(comedi_async *async, sampl_t *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_n_available(struct comedi_async *async);
|
||||||
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 comedi_buf_write_alloc_strict(comedi_async *async,
|
unsigned int comedi_buf_write_alloc_strict(struct comedi_async *async,
|
||||||
unsigned int nbytes);
|
unsigned int nbytes);
|
||||||
unsigned comedi_buf_write_free(comedi_async *async, unsigned int nbytes);
|
unsigned comedi_buf_write_free(struct comedi_async *async, unsigned int nbytes);
|
||||||
unsigned comedi_buf_read_alloc(comedi_async *async, unsigned nbytes);
|
unsigned comedi_buf_read_alloc(struct comedi_async *async, unsigned nbytes);
|
||||||
unsigned comedi_buf_read_free(comedi_async *async, unsigned int nbytes);
|
unsigned comedi_buf_read_free(struct comedi_async *async, unsigned int nbytes);
|
||||||
unsigned int comedi_buf_read_n_available(comedi_async *async);
|
unsigned int comedi_buf_read_n_available(struct comedi_async *async);
|
||||||
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 *source, unsigned int num_bytes);
|
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);
|
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;
|
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;
|
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)
|
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);
|
int comedi_alloc_board_minor(struct device *hardware_device);
|
||||||
void comedi_free_board_minor(unsigned minor);
|
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);
|
||||||
void comedi_free_subdevice_minor(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);
|
int comedi_pci_auto_config(struct pci_dev *pcidev, const char *board_name);
|
||||||
void comedi_pci_auto_unconfig(struct pci_dev *pcidev);
|
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"
|
#include "comedi_rt.h"
|
||||||
|
|
||||||
|
|
|
@ -36,18 +36,16 @@
|
||||||
|
|
||||||
#ifndef KCOMEDILIB_DEPRECATED
|
#ifndef KCOMEDILIB_DEPRECATED
|
||||||
|
|
||||||
typedef void comedi_t;
|
|
||||||
|
|
||||||
/* these functions may not be called at real-time priority */
|
/* these functions may not be called at real-time priority */
|
||||||
|
|
||||||
comedi_t *comedi_open(const char *path);
|
void *comedi_open(const char *path);
|
||||||
int comedi_close(comedi_t *dev);
|
int comedi_close(void *dev);
|
||||||
|
|
||||||
/* these functions may be called at any priority, but may fail at
|
/* these functions may be called at any priority, but may fail at
|
||||||
real-time priority */
|
real-time priority */
|
||||||
|
|
||||||
int comedi_lock(comedi_t *dev, unsigned int subdev);
|
int comedi_lock(void *dev, unsigned int subdev);
|
||||||
int comedi_unlock(comedi_t *dev, unsigned int subdev);
|
int comedi_unlock(void *dev, unsigned int subdev);
|
||||||
|
|
||||||
/* these functions may be called at any priority, but you must hold
|
/* these functions may be called at any priority, but you must hold
|
||||||
the lock for the subdevice */
|
the lock for the subdevice */
|
||||||
|
@ -56,68 +54,68 @@ int comedi_loglevel(int loglevel);
|
||||||
void comedi_perror(const char *s);
|
void comedi_perror(const char *s);
|
||||||
char *comedi_strerror(int errnum);
|
char *comedi_strerror(int errnum);
|
||||||
int comedi_errno(void);
|
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_cancel(void *dev, unsigned int subdev);
|
||||||
int comedi_register_callback(comedi_t *dev, unsigned int subdev,
|
int comedi_register_callback(void *dev, unsigned int subdev,
|
||||||
unsigned int mask, int (*cb) (unsigned int, void *), void *arg);
|
unsigned int mask, int (*cb) (unsigned int, void *), void *arg);
|
||||||
|
|
||||||
int comedi_command(comedi_t *dev, comedi_cmd *cmd);
|
int comedi_command(void *dev, struct comedi_cmd *cmd);
|
||||||
int comedi_command_test(comedi_t *dev, comedi_cmd *cmd);
|
int comedi_command_test(void *dev, struct comedi_cmd *cmd);
|
||||||
int comedi_trigger(comedi_t *dev, unsigned int subdev, comedi_trig *it);
|
int comedi_trigger(void *dev, unsigned int subdev, struct comedi_trig *it);
|
||||||
int __comedi_trigger(comedi_t *dev, unsigned int subdev, comedi_trig *it);
|
int __comedi_trigger(void *dev, unsigned int subdev, struct comedi_trig *it);
|
||||||
int comedi_data_write(comedi_t *dev, unsigned int subdev, unsigned int chan,
|
int comedi_data_write(void *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(comedi_t *dev, unsigned int subdev, unsigned int chan,
|
int comedi_data_read(void *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_hint(comedi_t *dev, unsigned int subdev,
|
int comedi_data_read_hint(void *dev, unsigned int subdev,
|
||||||
unsigned int chan, unsigned int range, unsigned int aref);
|
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,
|
unsigned int chan, unsigned int range, unsigned int aref,
|
||||||
lsampl_t *data, unsigned int nano_sec);
|
unsigned int *data, unsigned int nano_sec);
|
||||||
int comedi_dio_config(comedi_t *dev, unsigned int subdev, unsigned int chan,
|
int comedi_dio_config(void *dev, unsigned int subdev, unsigned int chan,
|
||||||
unsigned int io);
|
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);
|
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);
|
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);
|
unsigned int *bits);
|
||||||
int comedi_get_n_subdevices(comedi_t *dev);
|
int comedi_get_n_subdevices(void *dev);
|
||||||
int comedi_get_version_code(comedi_t *dev);
|
int comedi_get_version_code(void *dev);
|
||||||
const char *comedi_get_driver_name(comedi_t *dev);
|
const char *comedi_get_driver_name(void *dev);
|
||||||
const char *comedi_get_board_name(comedi_t *dev);
|
const char *comedi_get_board_name(void *dev);
|
||||||
int comedi_get_subdevice_type(comedi_t *dev, unsigned int subdevice);
|
int comedi_get_subdevice_type(void *dev, unsigned int subdevice);
|
||||||
int comedi_find_subdevice_by_type(comedi_t *dev, int type, unsigned int subd);
|
int comedi_find_subdevice_by_type(void *dev, int type, unsigned int subd);
|
||||||
int comedi_get_n_channels(comedi_t *dev, unsigned int subdevice);
|
int comedi_get_n_channels(void *dev, unsigned int subdevice);
|
||||||
lsampl_t comedi_get_maxdata(comedi_t *dev, unsigned int subdevice, unsigned
|
unsigned int comedi_get_maxdata(void *dev, unsigned int subdevice, unsigned
|
||||||
int chan);
|
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);
|
chan);
|
||||||
int comedi_do_insn(comedi_t *dev, comedi_insn *insn);
|
int comedi_do_insn(void *dev, struct comedi_insn *insn);
|
||||||
int comedi_poll(comedi_t *dev, unsigned int subdev);
|
int comedi_poll(void *dev, unsigned int subdev);
|
||||||
|
|
||||||
/* DEPRECATED functions */
|
/* DEPRECATED functions */
|
||||||
int comedi_get_rangetype(comedi_t *dev, unsigned int subdevice,
|
int comedi_get_rangetype(void *dev, unsigned int subdevice,
|
||||||
unsigned int chan);
|
unsigned int chan);
|
||||||
|
|
||||||
/* ALPHA functions */
|
/* ALPHA functions */
|
||||||
unsigned int comedi_get_subdevice_flags(comedi_t *dev, unsigned int subdevice);
|
unsigned int comedi_get_subdevice_flags(void *dev, unsigned int subdevice);
|
||||||
int comedi_get_len_chanlist(comedi_t *dev, unsigned int subdevice);
|
int comedi_get_len_chanlist(void *dev, unsigned int subdevice);
|
||||||
int comedi_get_krange(comedi_t *dev, unsigned int subdevice, unsigned int
|
int comedi_get_krange(void *dev, 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(comedi_t *dev, unsigned int subdevice);
|
unsigned int comedi_get_buf_head_pos(void *dev, unsigned int subdevice);
|
||||||
int comedi_set_user_int_count(comedi_t *dev, unsigned int subdevice,
|
int comedi_set_user_int_count(void *dev, unsigned int subdevice,
|
||||||
unsigned int buf_user_count);
|
unsigned int buf_user_count);
|
||||||
int comedi_map(comedi_t *dev, unsigned int subdev, void *ptr);
|
int comedi_map(void *dev, unsigned int subdev, void *ptr);
|
||||||
int comedi_unmap(comedi_t *dev, unsigned int subdev);
|
int comedi_unmap(void *dev, unsigned int subdev);
|
||||||
int comedi_get_buffer_size(comedi_t *dev, unsigned int subdev);
|
int comedi_get_buffer_size(void *dev, unsigned int subdev);
|
||||||
int comedi_mark_buffer_read(comedi_t *dev, unsigned int subdevice,
|
int comedi_mark_buffer_read(void *dev, unsigned int subdevice,
|
||||||
unsigned int num_bytes);
|
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);
|
unsigned int num_bytes);
|
||||||
int comedi_get_buffer_contents(comedi_t *dev, unsigned int subdevice);
|
int comedi_get_buffer_contents(void *dev, unsigned int subdevice);
|
||||||
int comedi_get_buffer_offset(comedi_t *dev, unsigned int subdevice);
|
int comedi_get_buffer_offset(void *dev, unsigned int subdevice);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
@ -139,14 +137,14 @@ int comedi_cancel(unsigned int minor, unsigned int subdev);
|
||||||
int comedi_register_callback(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);
|
unsigned int mask, int (*cb) (unsigned int, void *), void *arg);
|
||||||
|
|
||||||
int comedi_command(unsigned int minor, comedi_cmd *cmd);
|
int comedi_command(unsigned int minor, struct comedi_cmd *cmd);
|
||||||
int comedi_command_test(unsigned int minor, comedi_cmd *cmd);
|
int comedi_command_test(unsigned int minor, struct comedi_cmd *cmd);
|
||||||
int comedi_trigger(unsigned int minor, unsigned int subdev, comedi_trig *it);
|
int comedi_trigger(unsigned int minor, unsigned int subdev, struct comedi_trig *it);
|
||||||
int __comedi_trigger(unsigned int minor, unsigned int subdev, 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,
|
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,
|
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,
|
int comedi_dio_config(unsigned int dev, unsigned int subdev, unsigned int chan,
|
||||||
unsigned int io);
|
unsigned int io);
|
||||||
int comedi_dio_read(unsigned int dev, unsigned int subdev, unsigned int chan,
|
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,
|
int comedi_find_subdevice_by_type(unsigned int minor, int type,
|
||||||
unsigned int subd);
|
unsigned int subd);
|
||||||
int comedi_get_n_channels(unsigned int minor, unsigned int subdevice);
|
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 chan);
|
||||||
int comedi_get_n_ranges(unsigned int minor, unsigned int subdevice, unsigned int
|
int comedi_get_n_ranges(unsigned int minor, unsigned int subdevice, unsigned int
|
||||||
chan);
|
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);
|
int comedi_poll(unsigned int minor, unsigned int subdev);
|
||||||
|
|
||||||
/* DEPRECATED functions */
|
/* DEPRECATED functions */
|
||||||
|
@ -179,7 +177,7 @@ unsigned int comedi_get_subdevice_flags(unsigned int minor, unsigned int
|
||||||
subdevice);
|
subdevice);
|
||||||
int comedi_get_len_chanlist(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
|
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
|
unsigned int comedi_get_buf_head_pos(unsigned int minor, unsigned int
|
||||||
subdevice);
|
subdevice);
|
||||||
int comedi_set_user_int_count(unsigned int minor, unsigned int subdevice,
|
int comedi_set_user_int_count(unsigned int minor, unsigned int subdevice,
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/pci.h>
|
#include <linux/pci.h>
|
||||||
|
#include <linux/usb.h>
|
||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
|
@ -46,26 +47,26 @@
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
#include <asm/system.h>
|
#include <asm/system.h>
|
||||||
|
|
||||||
static int postconfig(comedi_device * dev);
|
static int postconfig(struct comedi_device *dev);
|
||||||
static int insn_rw_emulate_bits(comedi_device * dev, comedi_subdevice * s,
|
static int insn_rw_emulate_bits(struct comedi_device *dev, struct comedi_subdevice *s,
|
||||||
comedi_insn * insn, lsampl_t * data);
|
struct comedi_insn *insn, unsigned int *data);
|
||||||
static void *comedi_recognize(comedi_driver * driv, const char *name);
|
static void *comedi_recognize(struct comedi_driver * driv, const char *name);
|
||||||
static void comedi_report_boards(comedi_driver * driv);
|
static void comedi_report_boards(struct comedi_driver *driv);
|
||||||
static int poll_invalid(comedi_device * dev, comedi_subdevice * s);
|
static int poll_invalid(struct comedi_device *dev, struct comedi_subdevice *s);
|
||||||
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);
|
unsigned long new_size);
|
||||||
|
|
||||||
comedi_driver *comedi_drivers;
|
struct comedi_driver *comedi_drivers;
|
||||||
|
|
||||||
int comedi_modprobe(int minor)
|
int comedi_modprobe(int minor)
|
||||||
{
|
{
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cleanup_device(comedi_device * dev)
|
static void cleanup_device(struct comedi_device *dev)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
comedi_subdevice *s;
|
struct comedi_subdevice *s;
|
||||||
|
|
||||||
if (dev->subdevices) {
|
if (dev->subdevices) {
|
||||||
for (i = 0; i < dev->n_subdevices; i++) {
|
for (i = 0; i < dev->n_subdevices; i++) {
|
||||||
|
@ -80,10 +81,8 @@ static void cleanup_device(comedi_device * dev)
|
||||||
dev->subdevices = NULL;
|
dev->subdevices = NULL;
|
||||||
dev->n_subdevices = 0;
|
dev->n_subdevices = 0;
|
||||||
}
|
}
|
||||||
if (dev->private) {
|
kfree(dev->private);
|
||||||
kfree(dev->private);
|
dev->private = NULL;
|
||||||
dev->private = NULL;
|
|
||||||
}
|
|
||||||
dev->driver = 0;
|
dev->driver = 0;
|
||||||
dev->board_name = NULL;
|
dev->board_name = NULL;
|
||||||
dev->board_ptr = NULL;
|
dev->board_ptr = NULL;
|
||||||
|
@ -96,7 +95,7 @@ static void cleanup_device(comedi_device * dev)
|
||||||
comedi_set_hw_dev(dev, NULL);
|
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;
|
dev->attached = 0;
|
||||||
if (dev->driver) {
|
if (dev->driver) {
|
||||||
|
@ -107,16 +106,16 @@ static void __comedi_device_detach(comedi_device * dev)
|
||||||
cleanup_device(dev);
|
cleanup_device(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
void comedi_device_detach(comedi_device * dev)
|
void comedi_device_detach(struct comedi_device *dev)
|
||||||
{
|
{
|
||||||
if (!dev->attached)
|
if (!dev->attached)
|
||||||
return;
|
return;
|
||||||
__comedi_device_detach(dev);
|
__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;
|
int ret;
|
||||||
|
|
||||||
if (dev->attached)
|
if (dev->attached)
|
||||||
|
@ -139,7 +138,7 @@ int comedi_device_attach(comedi_device * dev, comedi_devconfig * it)
|
||||||
continue;
|
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;
|
dev->driver = driv;
|
||||||
ret = driv->attach(dev, it);
|
ret = driv->attach(dev, it);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
|
@ -150,8 +149,8 @@ int comedi_device_attach(comedi_device * dev, comedi_devconfig * it)
|
||||||
goto attached;
|
goto attached;
|
||||||
}
|
}
|
||||||
|
|
||||||
// recognize has failed if we get here
|
/* recognize has failed if we get here */
|
||||||
// report valid board names before returning error
|
/* report valid board names before returning error */
|
||||||
for (driv = comedi_drivers; driv; driv = driv->next) {
|
for (driv = comedi_drivers; driv; driv = driv->next) {
|
||||||
if (!try_module_get(driv->module)) {
|
if (!try_module_get(driv->module)) {
|
||||||
printk("comedi: failed to increment module count\n");
|
printk("comedi: failed to increment module count\n");
|
||||||
|
@ -181,7 +180,7 @@ attached:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int comedi_driver_register(comedi_driver * driver)
|
int comedi_driver_register(struct comedi_driver *driver)
|
||||||
{
|
{
|
||||||
driver->next = comedi_drivers;
|
driver->next = comedi_drivers;
|
||||||
comedi_drivers = driver;
|
comedi_drivers = driver;
|
||||||
|
@ -189,15 +188,15 @@ int comedi_driver_register(comedi_driver * driver)
|
||||||
return 0;
|
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;
|
int i;
|
||||||
|
|
||||||
/* check for devices using this driver */
|
/* check for devices using this driver */
|
||||||
for (i = 0; i < COMEDI_NUM_BOARD_MINORS; i++) {
|
for (i = 0; i < COMEDI_NUM_BOARD_MINORS; i++) {
|
||||||
struct comedi_device_file_info *dev_file_info = comedi_get_device_file_info(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;
|
if(dev_file_info == NULL) continue;
|
||||||
dev = dev_file_info->device;
|
dev = dev_file_info->device;
|
||||||
|
@ -225,11 +224,11 @@ int comedi_driver_unregister(comedi_driver * driver)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int postconfig(comedi_device * dev)
|
static int postconfig(struct comedi_device *dev)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
comedi_subdevice *s;
|
struct comedi_subdevice *s;
|
||||||
comedi_async *async = NULL;
|
struct comedi_async *async = NULL;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
for (i = 0; i < dev->n_subdevices; i++) {
|
for (i = 0; i < dev->n_subdevices; i++) {
|
||||||
|
@ -246,7 +245,7 @@ static int postconfig(comedi_device * dev)
|
||||||
SDF_CMD_WRITE)) == 0);
|
SDF_CMD_WRITE)) == 0);
|
||||||
BUG_ON(!s->do_cmdtest);
|
BUG_ON(!s->do_cmdtest);
|
||||||
|
|
||||||
async = kzalloc(sizeof(comedi_async), GFP_KERNEL);
|
async = kzalloc(sizeof(struct comedi_async), GFP_KERNEL);
|
||||||
if (async == NULL) {
|
if (async == NULL) {
|
||||||
printk("failed to allocate async struct\n");
|
printk("failed to allocate async struct\n");
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
@ -298,8 +297,8 @@ static int postconfig(comedi_device * dev)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// generic recognize function for drivers that register their supported board names
|
/* generic recognize function for drivers that register their supported board names */
|
||||||
void *comedi_recognize(comedi_driver * driv, const char *name)
|
void *comedi_recognize(struct comedi_driver * driv, const char *name)
|
||||||
{
|
{
|
||||||
unsigned i;
|
unsigned i;
|
||||||
const char *const *name_ptr = driv->board_name;
|
const char *const *name_ptr = driv->board_name;
|
||||||
|
@ -314,7 +313,7 @@ void *comedi_recognize(comedi_driver * driv, const char *name)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void comedi_report_boards(comedi_driver * driv)
|
void comedi_report_boards(struct comedi_driver *driv)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
const char *const *name_ptr;
|
const char *const *name_ptr;
|
||||||
|
@ -332,28 +331,28 @@ void comedi_report_boards(comedi_driver * driv)
|
||||||
printk(" %s\n", driv->driver_name);
|
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;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int insn_inval(comedi_device * dev, comedi_subdevice * s,
|
int insn_inval(struct comedi_device *dev, struct comedi_subdevice *s,
|
||||||
comedi_insn * insn, lsampl_t * data)
|
struct comedi_insn *insn, unsigned int *data)
|
||||||
{
|
{
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int insn_rw_emulate_bits(comedi_device * dev, comedi_subdevice * s,
|
static int insn_rw_emulate_bits(struct comedi_device *dev, struct comedi_subdevice *s,
|
||||||
comedi_insn * insn, lsampl_t * data)
|
struct comedi_insn *insn, unsigned int *data)
|
||||||
{
|
{
|
||||||
comedi_insn new_insn;
|
struct comedi_insn new_insn;
|
||||||
int ret;
|
int ret;
|
||||||
static const unsigned channels_per_bitfield = 32;
|
static const unsigned channels_per_bitfield = 32;
|
||||||
|
|
||||||
unsigned chan = CR_CHAN(insn->chanspec);
|
unsigned chan = CR_CHAN(insn->chanspec);
|
||||||
const unsigned base_bitfield_channel =
|
const unsigned base_bitfield_channel =
|
||||||
(chan < channels_per_bitfield) ? 0 : chan;
|
(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_data, 0, sizeof(new_data));
|
||||||
memset(&new_insn, 0, sizeof(new_insn));
|
memset(&new_insn, 0, sizeof(new_insn));
|
||||||
new_insn.insn = INSN_BITS;
|
new_insn.insn = INSN_BITS;
|
||||||
|
@ -380,7 +379,7 @@ static int insn_rw_emulate_bits(comedi_device * dev, comedi_subdevice * s,
|
||||||
return 1;
|
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;
|
unsigned long ret = 0UL;
|
||||||
pmd_t *pmd;
|
pmd_t *pmd;
|
||||||
|
@ -413,10 +412,10 @@ static inline unsigned long kvirt_to_kva(unsigned long adr)
|
||||||
return kva;
|
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)
|
unsigned long new_size)
|
||||||
{
|
{
|
||||||
comedi_async *async = s->async;
|
struct comedi_async *async = s->async;
|
||||||
|
|
||||||
/* Round up new_size to multiple of PAGE_SIZE */
|
/* Round up new_size to multiple of PAGE_SIZE */
|
||||||
new_size = (new_size + PAGE_SIZE - 1) & PAGE_MASK;
|
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) {
|
if (async->prealloc_buf && async->prealloc_bufsz == new_size) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
// deallocate old buffer
|
/* deallocate old buffer */
|
||||||
if (async->prealloc_buf) {
|
if (async->prealloc_buf) {
|
||||||
vunmap(async->prealloc_buf);
|
vunmap(async->prealloc_buf);
|
||||||
async->prealloc_buf = NULL;
|
async->prealloc_buf = NULL;
|
||||||
|
@ -454,7 +453,7 @@ int comedi_buf_alloc(comedi_device * dev, comedi_subdevice * s,
|
||||||
async->buf_page_list = NULL;
|
async->buf_page_list = NULL;
|
||||||
async->n_buf_pages = 0;
|
async->n_buf_pages = 0;
|
||||||
}
|
}
|
||||||
// allocate new buffer
|
/* allocate new buffer */
|
||||||
if (new_size) {
|
if (new_size) {
|
||||||
unsigned i = 0;
|
unsigned i = 0;
|
||||||
unsigned n_pages = new_size >> PAGE_SHIFT;
|
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
|
/* munging is applied to data by core as it passes between user
|
||||||
* and kernel space */
|
* 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;
|
unsigned int count = 0;
|
||||||
const unsigned num_sample_bytes = bytes_per_sample(s);
|
const unsigned num_sample_bytes = bytes_per_sample(s);
|
||||||
|
|
||||||
if (s->munge == NULL || (async->cmd.flags & CMDF_RAWDATA)) {
|
if (s->munge == NULL || (async->cmd.flags & CMDF_RAWDATA)) {
|
||||||
async->munge_count += num_bytes;
|
async->munge_count += num_bytes;
|
||||||
if ((int)(async->munge_count - async->buf_write_count) > 0)
|
BUG_ON((int)(async->munge_count - async->buf_write_count) > 0);
|
||||||
BUG();
|
|
||||||
return num_bytes;
|
return num_bytes;
|
||||||
}
|
}
|
||||||
/* don't munge partial samples */
|
/* 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,
|
s->munge(s->device, s, async->prealloc_buf + async->munge_ptr,
|
||||||
block_size, async->munge_chan);
|
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 += block_size / num_sample_bytes;
|
||||||
async->munge_chan %= async->cmd.chanlist_len;
|
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;
|
async->munge_ptr %= async->prealloc_bufsz;
|
||||||
count += block_size;
|
count += block_size;
|
||||||
}
|
}
|
||||||
if ((int)(async->munge_count - async->buf_write_count) > 0)
|
BUG_ON((int)(async->munge_count - async->buf_write_count) > 0);
|
||||||
BUG();
|
|
||||||
return count;
|
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 free_end;
|
||||||
unsigned int nbytes;
|
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 */
|
/* 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;
|
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 */
|
/* 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 nbytes)
|
||||||
{
|
{
|
||||||
unsigned int free_end = async->buf_read_count + async->prealloc_bufsz;
|
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 */
|
/* 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 -
|
if ((int)(async->buf_write_count + nbytes -
|
||||||
async->buf_write_alloc_count) > 0) {
|
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 */
|
/* 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) >
|
if ((int)(async->buf_read_alloc_count + nbytes - async->munge_count) >
|
||||||
0) {
|
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 */
|
/* 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();
|
smp_mb();
|
||||||
if ((int)(async->buf_read_count + nbytes -
|
if ((int)(async->buf_read_count + nbytes -
|
||||||
async->buf_read_alloc_count) > 0) {
|
async->buf_read_alloc_count) > 0) {
|
||||||
|
@ -680,7 +677,7 @@ unsigned comedi_buf_read_free(comedi_async * async, unsigned int nbytes)
|
||||||
return 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)
|
const void *data, unsigned int num_bytes)
|
||||||
{
|
{
|
||||||
unsigned int write_ptr = async->buf_write_ptr + offset;
|
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 *dest, unsigned int nbytes)
|
||||||
{
|
{
|
||||||
void *src;
|
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;
|
unsigned num_bytes;
|
||||||
|
|
||||||
|
@ -746,32 +743,32 @@ unsigned int comedi_buf_read_n_available(comedi_async * async)
|
||||||
return num_bytes;
|
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);
|
unsigned int n = comedi_buf_read_n_available(async);
|
||||||
|
|
||||||
if (n < sizeof(sampl_t))
|
if (n < sizeof(short))
|
||||||
return 0;
|
return 0;
|
||||||
comedi_buf_read_alloc(async, sizeof(sampl_t));
|
comedi_buf_read_alloc(async, sizeof(short));
|
||||||
*x = *(sampl_t *) (async->prealloc_buf + async->buf_read_ptr);
|
*x = *(short *) (async->prealloc_buf + async->buf_read_ptr);
|
||||||
comedi_buf_read_free(async, sizeof(sampl_t));
|
comedi_buf_read_free(async, sizeof(short));
|
||||||
return 1;
|
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;
|
async->events |= COMEDI_CB_ERROR;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
*(sampl_t *) (async->prealloc_buf + async->buf_write_ptr) = x;
|
*(short *) (async->prealloc_buf + async->buf_write_ptr) = x;
|
||||||
comedi_buf_write_free(async, sizeof(sampl_t));
|
comedi_buf_write_free(async, sizeof(short));
|
||||||
return 1;
|
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_alloc_count = 0;
|
||||||
async->buf_write_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)
|
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;
|
int minor;
|
||||||
struct comedi_device_file_info *dev_file_info;
|
struct comedi_device_file_info *dev_file_info;
|
||||||
int retval;
|
int retval;
|
||||||
|
unsigned *private_data = NULL;
|
||||||
|
|
||||||
|
if (!comedi_autoconfig) {
|
||||||
|
dev_set_drvdata(hardware_device, NULL);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
minor = comedi_alloc_board_minor(hardware_device);
|
minor = comedi_alloc_board_minor(hardware_device);
|
||||||
if(minor < 0) return minor;
|
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);
|
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);
|
mutex_lock(&dev_file_info->device->mutex);
|
||||||
retval = comedi_device_attach(dev_file_info->device, &it);
|
retval = comedi_device_attach(dev_file_info->device, &it);
|
||||||
mutex_unlock(&dev_file_info->device->mutex);
|
mutex_unlock(&dev_file_info->device->mutex);
|
||||||
|
|
||||||
|
cleanup:
|
||||||
if(retval < 0)
|
if(retval < 0)
|
||||||
{
|
{
|
||||||
|
kfree(private_data);
|
||||||
comedi_free_board_minor(minor);
|
comedi_free_board_minor(minor);
|
||||||
}
|
}
|
||||||
return retval;
|
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)
|
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 comedi_pci_auto_config(struct pci_dev *pcidev, const char *board_name)
|
||||||
{
|
{
|
||||||
int options[2];
|
int options[2];
|
||||||
|
|
||||||
// pci bus
|
/* pci bus */
|
||||||
options[0] = pcidev->bus->number;
|
options[0] = pcidev->bus->number;
|
||||||
// pci slot
|
/* pci slot */
|
||||||
options[1] = PCI_SLOT(pcidev->devfn);
|
options[1] = PCI_SLOT(pcidev->devfn);
|
||||||
|
|
||||||
return comedi_auto_config(&pcidev->dev, board_name, options, sizeof(options) / sizeof(options[0]));
|
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);
|
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);
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
|
@ -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);
|
|
@ -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
|
|
@ -8,12 +8,121 @@ obj-$(CONFIG_COMEDI) += comedi_test.o
|
||||||
obj-$(CONFIG_COMEDI) += comedi_parport.o
|
obj-$(CONFIG_COMEDI) += comedi_parport.o
|
||||||
|
|
||||||
# Comedi PCI drivers
|
# 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) += 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) += 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) += 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) += 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
|
# Comedi USB drivers
|
||||||
obj-$(CONFIG_COMEDI_USB_DRIVERS) += usbdux.o
|
obj-$(CONFIG_COMEDI_USB_DRIVERS) += usbdux.o
|
||||||
|
|
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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);
|
|
@ -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;
|
||||||
|
|
||||||
|
}
|
|
@ -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
|
@ -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);
|
|
@ -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);
|
||||||
|
}
|
|
@ -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
|
@ -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
|
@ -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);
|
|
@ -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);
|
||||||
|
}
|
|
@ -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);
|
|
@ -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
|
@ -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
|
@ -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
|
@ -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)
|
||||||
|
}
|
||||||
|
};
|
|
@ -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;
|
||||||
|
}
|
|
@ -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);
|
|
@ -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;
|
||||||
|
}
|
|
@ -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
|
@ -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);
|
|
@ -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;
|
||||||
|
}
|
|
@ -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
|
@ -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);
|
|
@ -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;
|
||||||
|
}
|
|
@ -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
|
|
@ -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;
|
||||||
|
}
|
|
@ -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);
|
|
@ -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;
|
||||||
|
}
|
|
@ -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);
|
|
@ -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;
|
||||||
|
}
|
|
@ -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
|
@ -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
|
@ -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);
|
|
@ -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;
|
||||||
|
}
|
|
@ -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
|
@ -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
|
|
@ -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"
|
|
@ -0,0 +1,3 @@
|
||||||
|
#define CONFIG_APCI_1032 1
|
||||||
|
|
||||||
|
#include "addi-data/addi_common.c"
|
|
@ -0,0 +1,3 @@
|
||||||
|
#define CONFIG_APCI_1500 1
|
||||||
|
|
||||||
|
#include "addi-data/addi_common.c"
|
|
@ -0,0 +1,3 @@
|
||||||
|
#define CONFIG_APCI_1516 1
|
||||||
|
|
||||||
|
#include "addi-data/addi_common.c"
|
|
@ -0,0 +1,3 @@
|
||||||
|
#define CONFIG_APCI_1564 1
|
||||||
|
|
||||||
|
#include "addi-data/addi_common.c"
|
|
@ -0,0 +1,3 @@
|
||||||
|
#define CONFIG_APCI_16XX 1
|
||||||
|
|
||||||
|
#include "addi-data/addi_common.c"
|
|
@ -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
Loading…
Reference in New Issue