diff options
author | 2009-04-05 11:06:45 -0700 | |
---|---|---|
committer | 2009-04-05 11:06:45 -0700 | |
commit | 3516c6a8dc0b1153c611c4cf0dc4a51631f052bb (patch) | |
tree | c54a5fc916cbe73e43dee20902642f367f44a551 | |
parent | Merge branch 'tracing-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip (diff) | |
parent | Staging: sxg: slicoss: Specify the license for Sahara SXG and Slicoss drivers (diff) | |
download | linux-dev-3516c6a8dc0b1153c611c4cf0dc4a51631f052bb.tar.xz linux-dev-3516c6a8dc0b1153c611c4cf0dc4a51631f052bb.zip |
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
...
713 files changed, 312473 insertions, 64562 deletions
diff --git a/Documentation/filesystems/pohmelfs/design_notes.txt b/Documentation/filesystems/pohmelfs/design_notes.txt new file mode 100644 index 000000000000..6d6db60d567d --- /dev/null +++ b/Documentation/filesystems/pohmelfs/design_notes.txt @@ -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. diff --git a/Documentation/filesystems/pohmelfs/info.txt b/Documentation/filesystems/pohmelfs/info.txt new file mode 100644 index 000000000000..4e3d50157083 --- /dev/null +++ b/Documentation/filesystems/pohmelfs/info.txt @@ -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). diff --git a/Documentation/filesystems/pohmelfs/network_protocol.txt b/Documentation/filesystems/pohmelfs/network_protocol.txt new file mode 100644 index 000000000000..40ea6c295afb --- /dev/null +++ b/Documentation/filesystems/pohmelfs/network_protocol.txt @@ -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 diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 92981c2383ee..0dcf9ca0b0ac 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -73,6 +73,8 @@ source "drivers/staging/rt2860/Kconfig" source "drivers/staging/rt2870/Kconfig" +source "drivers/staging/rt3070/Kconfig" + source "drivers/staging/comedi/Kconfig" source "drivers/staging/asus_oled/Kconfig" @@ -93,5 +95,25 @@ source "drivers/staging/epl/Kconfig" source "drivers/staging/android/Kconfig" +source "drivers/staging/dst/Kconfig" + +source "drivers/staging/pohmelfs/Kconfig" + +source "drivers/staging/stlc45xx/Kconfig" + +source "drivers/staging/uc2322/Kconfig" + +source "drivers/staging/b3dfg/Kconfig" + +source "drivers/staging/phison/Kconfig" + +source "drivers/staging/p9auth/Kconfig" + +source "drivers/staging/heci/Kconfig" + +source "drivers/staging/line6/Kconfig" + +source "drivers/staging/serqt_usb/Kconfig" + endif # !STAGING_EXCLUDE_BUILD endif # STAGING diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 47a56f5ffabc..47dfd5b4288b 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -19,6 +19,7 @@ obj-$(CONFIG_AGNX) += agnx/ obj-$(CONFIG_OTUS) += otus/ obj-$(CONFIG_RT2860) += rt2860/ obj-$(CONFIG_RT2870) += rt2870/ +obj-$(CONFIG_RT3070) += rt3070/ obj-$(CONFIG_COMEDI) += comedi/ obj-$(CONFIG_ASUS_OLED) += asus_oled/ obj-$(CONFIG_PANEL) += panel/ @@ -29,3 +30,13 @@ obj-$(CONFIG_INPUT_MIMIO) += mimio/ obj-$(CONFIG_TRANZPORT) += frontier/ obj-$(CONFIG_EPL) += epl/ obj-$(CONFIG_ANDROID) += android/ +obj-$(CONFIG_DST) += dst/ +obj-$(CONFIG_POHMELFS) += pohmelfs/ +obj-$(CONFIG_STLC45XX) += stlc45xx/ +obj-$(CONFIG_USB_SERIAL_ATEN2011) += uc2322/ +obj-$(CONFIG_B3DFG) += b3dfg/ +obj-$(CONFIG_IDE_PHISON) += phison/ +obj-$(CONFIG_PLAN9AUTH) += p9auth/ +obj-$(CONFIG_HECI) += heci/ +obj-$(CONFIG_LINE6_USB) += line6/ +obj-$(CONFIG_USB_SERIAL_QUATECH_ESU100) += serqt_usb/ diff --git a/drivers/staging/agnx/agnx.h b/drivers/staging/agnx/agnx.h index 20f36da62475..3963d2597a11 100644 --- a/drivers/staging/agnx/agnx.h +++ b/drivers/staging/agnx/agnx.h @@ -41,16 +41,16 @@ static const struct ieee80211_rate agnx_rates_80211g[] = { /* { .bitrate = 20, .hw_value = 2, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, */ /* { .bitrate = 55, .hw_value = 3, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, */ /* { .bitrate = 110, .hw_value = 4, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, */ - { .bitrate = 10, .hw_value = 1, }, - { .bitrate = 20, .hw_value = 2, }, - { .bitrate = 55, .hw_value = 3, }, - { .bitrate = 110, .hw_value = 4,}, + { .bitrate = 10, .hw_value = 1, }, + { .bitrate = 20, .hw_value = 2, }, + { .bitrate = 55, .hw_value = 3, }, + { .bitrate = 110, .hw_value = 4,}, { .bitrate = 60, .hw_value = 0xB, }, { .bitrate = 90, .hw_value = 0xF, }, { .bitrate = 120, .hw_value = 0xA }, { .bitrate = 180, .hw_value = 0xE, }, -// { .bitrate = 240, .hw_value = 0xd, }, +/* { .bitrate = 240, .hw_value = 0xd, }, */ { .bitrate = 360, .hw_value = 0xD, }, { .bitrate = 480, .hw_value = 0x8, }, { .bitrate = 540, .hw_value = 0xC, }, @@ -110,10 +110,10 @@ struct agnx_priv { /* Need volatile? */ u32 irq_status; - struct delayed_work periodic_work; /* Periodic tasks like recalibrate*/ + struct delayed_work periodic_work; /* Periodic tasks like recalibrate */ struct ieee80211_low_level_stats stats; -// unsigned int phymode; + /* unsigned int phymode; */ int mode; int channel; u8 bssid[ETH_ALEN]; diff --git a/drivers/staging/agnx/debug.h b/drivers/staging/agnx/debug.h index e3e25dda0ba0..761d99c2d3f0 100644 --- a/drivers/staging/agnx/debug.h +++ b/drivers/staging/agnx/debug.h @@ -23,7 +23,7 @@ static inline void agnx_bug(char *reason) static inline void agnx_print_desc(struct agnx_desc *desc) { - u32 reg = be32_to_cpu(desc->frag); + u32 reg = be32_to_cpu(desc->frag); PRINTK_BITS(DESC, PACKET_LEN); @@ -291,7 +291,7 @@ static inline void agnx_print_sta(struct agnx_priv *priv, unsigned int sta_idx) PRINTK_LE32(STA, sta->phy_stats_high); PRINTK_LE32(STA, sta->phy_stats_low); -// for (i = 0; i < 8; i++) + /* for (i = 0; i < 8; i++) */ agnx_print_sta_traffic(sta->traffic + 0); PRINTK_LE16(STA, sta->traffic_class0_frag_success); @@ -311,10 +311,10 @@ static inline void agnx_print_sta(struct agnx_priv *priv, unsigned int sta_idx) static inline void dump_ieee80211_hdr(struct ieee80211_hdr *hdr, char *tag) { u16 fctl; - int hdrlen; + int hdrlen; DECLARE_MAC_BUF(mac); - fctl = le16_to_cpu(hdr->frame_control); + fctl = le16_to_cpu(hdr->frame_control); switch (fctl & IEEE80211_FCTL_FTYPE) { case IEEE80211_FTYPE_DATA: printk(PFX "%s DATA ", tag); @@ -324,7 +324,7 @@ static inline void dump_ieee80211_hdr(struct ieee80211_hdr *hdr, char *tag) break; case IEEE80211_FTYPE_MGMT: printk(PFX "%s MGMT ", tag); - switch(fctl & IEEE80211_FCTL_STYPE) { + switch (fctl & IEEE80211_FCTL_STYPE) { case IEEE80211_STYPE_ASSOC_REQ: printk("SubType: ASSOC_REQ "); break; @@ -369,7 +369,7 @@ static inline void dump_ieee80211_hdr(struct ieee80211_hdr *hdr, char *tag) printk(PFX "%s Packet type: Unknow\n", tag); } - hdrlen = ieee80211_hdrlen(fctl); + hdrlen = ieee80211_hdrlen(fctl); if (hdrlen >= 4) printk("FC=0x%04x DUR=0x%04x", @@ -389,29 +389,28 @@ static inline void dump_txm_registers(struct agnx_priv *priv) { void __iomem *ctl = priv->ctl; int i; - for (i = 0; i <=0x1e8; i += 4) { + for (i = 0; i <= 0x1e8; i += 4) printk(KERN_DEBUG PFX "TXM: %x---> 0x%.8x\n", i, ioread32(ctl + i)); - } } static inline void dump_rxm_registers(struct agnx_priv *priv) { void __iomem *ctl = priv->ctl; int i; - for (i = 0; i <=0x108; i += 4) + for (i = 0; i <= 0x108; i += 4) printk(KERN_DEBUG PFX "RXM: %x---> 0x%.8x\n", i, ioread32(ctl + 0x2000 + i)); } static inline void dump_bm_registers(struct agnx_priv *priv) { void __iomem *ctl = priv->ctl; int i; - for (i = 0; i <=0x90; i += 4) + for (i = 0; i <= 0x90; i += 4) printk(KERN_DEBUG PFX "BM: %x---> 0x%.8x\n", i, ioread32(ctl + 0x2c00 + i)); } static inline void dump_cir_registers(struct agnx_priv *priv) { void __iomem *ctl = priv->ctl; int i; - for (i = 0; i <=0xb8; i += 4) + for (i = 0; i <= 0xb8; i += 4) printk(KERN_DEBUG PFX "CIR: %x---> 0x%.8x\n", i, ioread32(ctl + 0x3000 + i)); } diff --git a/drivers/staging/agnx/pci.c b/drivers/staging/agnx/pci.c index 854630cb527e..4ff4c1601423 100644 --- a/drivers/staging/agnx/pci.c +++ b/drivers/staging/agnx/pci.c @@ -39,34 +39,34 @@ static inline void agnx_interrupt_ack(struct agnx_priv *priv, u32 *reason) void __iomem *ctl = priv->ctl; u32 reg; - if ( *reason & AGNX_STAT_RX ) { + if (*reason & AGNX_STAT_RX) { /* Mark complete RX */ reg = ioread32(ctl + AGNX_CIR_RXCTL); reg |= 0x4; iowrite32(reg, ctl + AGNX_CIR_RXCTL); /* disable Rx interrupt */ } - if ( *reason & AGNX_STAT_TX ) { + if (*reason & AGNX_STAT_TX) { reg = ioread32(ctl + AGNX_CIR_TXDCTL); if (reg & 0x4) { iowrite32(reg, ctl + AGNX_CIR_TXDCTL); *reason |= AGNX_STAT_TXD; } - reg = ioread32(ctl + AGNX_CIR_TXMCTL); + reg = ioread32(ctl + AGNX_CIR_TXMCTL); if (reg & 0x4) { iowrite32(reg, ctl + AGNX_CIR_TXMCTL); *reason |= AGNX_STAT_TXM; } } - if ( *reason & AGNX_STAT_X ) { -/* reg = ioread32(ctl + AGNX_INT_STAT); */ -/* iowrite32(reg, ctl + AGNX_INT_STAT); */ -/* /\* FIXME reinit interrupt mask *\/ */ -/* reg = 0xc390bf9 & ~IRQ_TX_BEACON; */ -/* reg &= ~IRQ_TX_DISABLE; */ -/* iowrite32(reg, ctl + AGNX_INT_MASK); */ -/* iowrite32(0x800, ctl + AGNX_CIR_BLKCTL); */ - } +/* if (*reason & AGNX_STAT_X) { + reg = ioread32(ctl + AGNX_INT_STAT); + iowrite32(reg, ctl + AGNX_INT_STAT); + /* FIXME reinit interrupt mask *\/ + reg = 0xc390bf9 & ~IRQ_TX_BEACON; + reg &= ~IRQ_TX_DISABLE; + iowrite32(reg, ctl + AGNX_INT_MASK); + iowrite32(0x800, ctl + AGNX_CIR_BLKCTL); + } */ } /* agnx_interrupt_ack */ static irqreturn_t agnx_interrupt_handler(int irq, void *dev_id) @@ -79,7 +79,7 @@ static irqreturn_t agnx_interrupt_handler(int irq, void *dev_id) spin_lock(&priv->lock); -// printk(KERN_ERR PFX "Get a interrupt %s\n", __func__); +/* printk(KERN_ERR PFX "Get a interrupt %s\n", __func__); */ if (priv->init_status != AGNX_START) goto out; @@ -92,7 +92,7 @@ static irqreturn_t agnx_interrupt_handler(int irq, void *dev_id) ret = IRQ_HANDLED; priv->irq_status = ioread32(ctl + AGNX_INT_STAT); -// printk(PFX "Interrupt reason is 0x%x\n", irq_reason); +/* printk(PFX "Interrupt reason is 0x%x\n", irq_reason); */ /* Make sure the txm and txd flags don't conflict with other unknown interrupt flag, maybe is not necessary */ irq_reason &= 0xF; @@ -101,13 +101,13 @@ static irqreturn_t agnx_interrupt_handler(int irq, void *dev_id) /* TODO Make sure the card finished initialized */ agnx_interrupt_ack(priv, &irq_reason); - if ( irq_reason & AGNX_STAT_RX ) + if (irq_reason & AGNX_STAT_RX) handle_rx_irq(priv); - if ( irq_reason & AGNX_STAT_TXD ) + if (irq_reason & AGNX_STAT_TXD) handle_txd_irq(priv); - if ( irq_reason & AGNX_STAT_TXM ) + if (irq_reason & AGNX_STAT_TXM) handle_txm_irq(priv); - if ( irq_reason & AGNX_STAT_X ) + if (irq_reason & AGNX_STAT_X) handle_other_irq(priv); enable_rx_interrupt(priv); @@ -171,7 +171,7 @@ static int agnx_alloc_rings(struct agnx_priv *priv) len = priv->rx.size + priv->txm.size + priv->txd.size; -// priv->rx.info = kzalloc(sizeof(struct agnx_info) * len, GFP_KERNEL); +/* priv->rx.info = kzalloc(sizeof(struct agnx_info) * len, GFP_KERNEL); */ priv->rx.info = kzalloc(sizeof(struct agnx_info) * len, GFP_ATOMIC); if (!priv->rx.info) return -ENOMEM; @@ -210,28 +210,27 @@ static void rings_free(struct agnx_priv *priv) #if 0 static void agnx_periodic_work_handler(struct work_struct *work) { - struct agnx_priv *priv = container_of(work, struct agnx_priv, - periodic_work.work); -// unsigned long flags; + struct agnx_priv *priv = container_of(work, struct agnx_priv, periodic_work.work); +/* unsigned long flags; */ unsigned long delay; /* fixme: using mutex?? */ -// spin_lock_irqsave(&priv->lock, flags); +/* spin_lock_irqsave(&priv->lock, flags); */ /* TODO Recalibrate*/ -// calibrate_oscillator(priv); -// antenna_calibrate(priv); -// agnx_send_packet(priv, 997); +/* calibrate_oscillator(priv); */ +/* antenna_calibrate(priv); */ +/* agnx_send_packet(priv, 997); / /* FIXME */ /* if (debug == 3) */ /* delay = msecs_to_jiffies(AGNX_PERIODIC_DELAY); */ /* else */ delay = msecs_to_jiffies(AGNX_PERIODIC_DELAY); -// delay = round_jiffies(HZ * 15); +/* delay = round_jiffies(HZ * 15); */ queue_delayed_work(priv->hw->workqueue, &priv->periodic_work, delay); -// spin_unlock_irqrestore(&priv->lock, flags); +/* spin_unlock_irqrestore(&priv->lock, flags); */ } #endif @@ -255,12 +254,12 @@ static int agnx_start(struct ieee80211_hw *dev) goto out; } -// mdelay(500); +/* mdelay(500); */ might_sleep(); agnx_hw_init(priv); -// mdelay(500); +/* mdelay(500); */ might_sleep(); priv->init_status = AGNX_START; @@ -280,16 +279,16 @@ static void agnx_stop(struct ieee80211_hw *dev) /* make sure hardware will not generate irq */ agnx_hw_reset(priv); free_irq(priv->pdev->irq, dev); - flush_workqueue(priv->hw->workqueue); -// cancel_delayed_work_sync(&priv->periodic_work); + flush_workqueue(priv->hw->workqueue); +/* cancel_delayed_work_sync(&priv->periodic_work); */ unfill_rings(priv); rings_free(priv); } -static int agnx_config(struct ieee80211_hw *dev, - struct ieee80211_conf *conf) +static int agnx_config(struct ieee80211_hw *dev, u32 changed) { struct agnx_priv *priv = dev->priv; + struct ieee80211_conf *conf = &dev->conf; int channel = ieee80211_frequency_to_channel(conf->channel->center_freq); AGNX_TRACE; @@ -315,7 +314,6 @@ static int agnx_config_interface(struct ieee80211_hw *dev, spin_lock(&priv->lock); if (memcmp(conf->bssid, priv->bssid, ETH_ALEN)) { -// u32 reghi, reglo; agnx_set_bssid(priv, conf->bssid); memcpy(priv->bssid, conf->bssid, ETH_ALEN); hash_write(priv, conf->bssid, BSSID_STAID); @@ -425,7 +423,7 @@ static struct ieee80211_ops agnx_ops = { .remove_interface = agnx_remove_interface, .config = agnx_config, .config_interface = agnx_config_interface, - .configure_filter = agnx_configure_filter, + .configure_filter = agnx_configure_filter, .get_stats = agnx_get_stats, .get_tx_stats = agnx_get_tx_stats, .get_tsf = agnx_get_tsft @@ -434,11 +432,12 @@ static struct ieee80211_ops agnx_ops = { static void __devexit agnx_pci_remove(struct pci_dev *pdev) { struct ieee80211_hw *dev = pci_get_drvdata(pdev); - struct agnx_priv *priv = dev->priv; + struct agnx_priv *priv; AGNX_TRACE; if (!dev) return; + priv = dev->priv; ieee80211_unregister_hw(dev); pci_iounmap(pdev, priv->ctl); pci_iounmap(pdev, priv->data); @@ -504,7 +503,7 @@ static int __devinit agnx_pci_probe(struct pci_dev *pdev, /* Map mem #1 and #2 */ priv->ctl = pci_iomap(pdev, 0, mem_len0); -// printk(KERN_DEBUG PFX"MEM1 mapped address is 0x%p\n", priv->ctl); +/* printk(KERN_DEBUG PFX"MEM1 mapped address is 0x%p\n", priv->ctl); */ if (!priv->ctl) { printk(KERN_ERR PFX "Can't map device memory\n"); goto err_free_dev; diff --git a/drivers/staging/agnx/phy.c b/drivers/staging/agnx/phy.c index da8f10c08382..2be63312b727 100644 --- a/drivers/staging/agnx/phy.c +++ b/drivers/staging/agnx/phy.c @@ -114,7 +114,7 @@ static void mac_address_set(struct agnx_priv *priv) /* FIXME */ reg = (mac_addr[0] << 24) | (mac_addr[1] << 16) | mac_addr[2] << 8 | mac_addr[3]; iowrite32(reg, ctl + AGNX_RXM_MACHI); - reg = (mac_addr[4] << 8) | mac_addr[5]; + reg = (mac_addr[4] << 8) | mac_addr[5]; iowrite32(reg, ctl + AGNX_RXM_MACLO); } @@ -127,7 +127,7 @@ static void receiver_bssid_set(struct agnx_priv *priv, u8 *bssid) /* FIXME */ reg = bssid[0] << 24 | (bssid[1] << 16) | (bssid[2] << 8) | bssid[3]; iowrite32(reg, ctl + AGNX_RXM_BSSIDHI); - reg = (bssid[4] << 8) | bssid[5]; + reg = (bssid[4] << 8) | bssid[5]; iowrite32(reg, ctl + AGNX_RXM_BSSIDLO); /* Enable the receiver */ @@ -401,9 +401,9 @@ static void rx_management_init(struct agnx_priv *priv) agnx_write32(ctl, 0x2074, 0x1f171710); agnx_write32(ctl, 0x2078, 0x10100d0d); agnx_write32(ctl, 0x207c, 0x11111010); - } - else + } else { agnx_write32(ctl, AGNX_RXM_DELAY11, 0x0); + } agnx_write32(ctl, AGNX_RXM_REQRATE, 0x8195e00); } @@ -476,7 +476,7 @@ static void gain_ctlcnt_init(struct agnx_priv *priv) /* It seemed if we set other bit to 1 the bit 0 will be auto change to 0 */ agnx_write32(ctl, AGNX_BM_TXTOPEER, 0x2 | 0x1); -// agnx_write32(ctl, AGNX_BM_TXTOPEER, 0x1); +/* agnx_write32(ctl, AGNX_BM_TXTOPEER, 0x1); */ } /* gain_ctlcnt_init */ @@ -490,7 +490,7 @@ static void phy_init(struct agnx_priv *priv) /* Load InitialGainTable */ gain_table_init(priv); - agnx_write32(ctl, AGNX_CIR_ADDRWIN, 0x2000000); + agnx_write32(ctl, AGNX_CIR_ADDRWIN, 0x2000000); /* Clear the following offsets in Memory Range #2: */ memset_io(data + 0x5040, 0, 0xa * 4); @@ -586,7 +586,7 @@ static void phy_init(struct agnx_priv *priv) agnx_write32(ctl, AGNX_GCR_SIFST11B, 0x28); agnx_write32(ctl, AGNX_GCR_CWDETEC, 0x0); agnx_write32(ctl, AGNX_GCR_0X38, 0x1e); -// agnx_write32(ctl, AGNX_GCR_BOACT, 0x26); +/* agnx_write32(ctl, AGNX_GCR_BOACT, 0x26);*/ agnx_write32(ctl, AGNX_GCR_DISCOVMOD, 0x3); agnx_write32(ctl, AGNX_GCR_THCAP11A, 0x32); @@ -810,10 +810,10 @@ static void card_interface_init(struct agnx_priv *priv) } print_hex_dump_bytes(PFX "EEPROM: ", DUMP_PREFIX_NONE, eeprom, ARRAY_SIZE(eeprom)); - } while(0); + } while (0); spi_rc_write(ctl, RF_CHIP0, 0x26); - reg = agnx_read32(ctl, AGNX_SPI_RLSW); + reg = agnx_read32(ctl, AGNX_SPI_RLSW); /* Initialize the system interface */ system_itf_init(priv); @@ -874,19 +874,19 @@ static void card_interface_init(struct agnx_priv *priv) /* FIXME Enable the request */ /* Check packet length */ /* Set maximum packet length */ -/* agnx_write32(ctl, AGNX_RXM_REQRATE, 0x88195e00); */ -/* enable_receiver(priv); */ +/* agnx_write32(ctl, AGNX_RXM_REQRATE, 0x88195e00); */ +/* enable_receiver(priv); */ /* Set the Receiver BSSID */ receiver_bssid_set(priv, bssid); /* FIXME Set to managed mode */ set_managed_mode(priv); -// set_promiscuous_mode(priv); -/* set_scan_mode(priv); */ -/* set_learn_mode(priv); */ -// set_promis_and_managed(priv); -// set_adhoc_mode(priv); +/* set_promiscuous_mode(priv); */ +/* set_scan_mode(priv); */ +/* set_learn_mode(priv); */ +/* set_promis_and_managed(priv); */ +/* set_adhoc_mode(priv); */ /* Set the recieve request rate */ /* Check packet length */ diff --git a/drivers/staging/agnx/rf.c b/drivers/staging/agnx/rf.c index 8294b6e2eb9d..42e457a1844f 100644 --- a/drivers/staging/agnx/rf.c +++ b/drivers/staging/agnx/rf.c @@ -109,12 +109,12 @@ void rf_chips_init(struct agnx_priv *priv) } /* Set SPI clock speed to 200NS */ - reg = agnx_read32(ctl, AGNX_SPI_CFG); - reg &= ~0xF; - reg |= 0x3; - agnx_write32(ctl, AGNX_SPI_CFG, reg); + reg = agnx_read32(ctl, AGNX_SPI_CFG); + reg &= ~0xF; + reg |= 0x3; + agnx_write32(ctl, AGNX_SPI_CFG, reg); - /* Set SPI clock speed to 50NS */ + /* Set SPI clock speed to 50NS */ reg = agnx_read32(ctl, AGNX_SPI_CFG); reg &= ~0xF; reg |= 0x1; @@ -256,7 +256,7 @@ static void antenna_init(struct agnx_priv *priv, int num_antenna) agnx_write32(ctl, AGNX_GCR_THD0BTFEST, 70); agnx_write32(ctl, AGNX_GCR_SIGHTH, 100); agnx_write32(ctl, AGNX_GCR_SIGLTH, 48); -// agnx_write32(ctl, AGNX_GCR_SIGLTH, 16); +/* agnx_write32(ctl, AGNX_GCR_SIGLTH, 16); */ break; default: printk(KERN_WARNING PFX "Unknow antenna number\n"); @@ -275,8 +275,8 @@ static void chain_update(struct agnx_priv *priv, u32 chain) if (reg == 0x4) spi_rf_write(ctl, RF_CHIP0|RF_CHIP1, reg|0x1000); else if (reg != 0x0) - spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, reg|0x1000); - else { + spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, reg|0x1000); + else { if (chain == 3 || chain == 6) { spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, reg|0x1000); agnx_write32(ctl, AGNX_GCR_RXOVERIDE, 0x0); @@ -634,8 +634,7 @@ static void chain_calibrate(struct agnx_priv *priv, struct chains *chains, } } /* chain_calibrate */ - -static void inline get_calibrete_value(struct agnx_priv *priv, struct chains *chains, +static inline void get_calibrete_value(struct agnx_priv *priv, struct chains *chains, unsigned int num) { void __iomem *ctl = priv->ctl; @@ -652,7 +651,7 @@ static void inline get_calibrete_value(struct agnx_priv *priv, struct chains *ch } if (num == 0 || num == 1 || num == 2) { - if ( 0 == chains[num].cali) + if (0 == chains[num].cali) chains[num].cali = 0xff; else chains[num].cali--; @@ -669,7 +668,7 @@ static inline void calibra_delay(struct agnx_priv *priv) unsigned int i = 100; wmb(); - while (i--) { + while (--i) { reg = (ioread32(ctl + AGNX_ACI_STATUS)); if (reg == 0x4000) break; diff --git a/drivers/staging/agnx/sta.c b/drivers/staging/agnx/sta.c index d3ac675e45bd..5b2d54a587c8 100644 --- a/drivers/staging/agnx/sta.c +++ b/drivers/staging/agnx/sta.c @@ -18,7 +18,7 @@ void hash_read(struct agnx_priv *priv, u32 reghi, u32 reglo, u8 sta_id) iowrite32(reglo, ctl + AGNX_RXM_HASH_CMD_LOW); reghi = ioread32(ctl + AGNX_RXM_HASH_CMD_HIGH); - reglo = ioread32(ctl + AGNX_RXM_HASH_CMD_LOW); + reglo = ioread32(ctl + AGNX_RXM_HASH_CMD_LOW); printk(PFX "RX hash cmd are : %.8x%.8x\n", reghi, reglo); } @@ -40,7 +40,7 @@ void hash_write(struct agnx_priv *priv, u8 *mac_addr, u8 sta_id) iowrite32(reghi, ctl + AGNX_RXM_HASH_CMD_HIGH); iowrite32(reglo, ctl + AGNX_RXM_HASH_CMD_LOW); - reglo = ioread32(ctl + AGNX_RXM_HASH_CMD_LOW); + reglo = ioread32(ctl + AGNX_RXM_HASH_CMD_LOW); if (!(reglo & 0x80000000)) printk(KERN_WARNING PFX "Update hash table failed\n"); } @@ -59,7 +59,7 @@ void hash_delete(struct agnx_priv *priv, u32 reghi, u32 reglo, u8 sta_id) iowrite32(reglo, ctl + AGNX_RXM_HASH_CMD_LOW); reghi = ioread32(ctl + AGNX_RXM_HASH_CMD_HIGH); - reglo = ioread32(ctl + AGNX_RXM_HASH_CMD_LOW); + reglo = ioread32(ctl + AGNX_RXM_HASH_CMD_LOW); printk(PFX "RX hash cmd are : %.8x%.8x\n", reghi, reglo); } @@ -69,15 +69,14 @@ void hash_dump(struct agnx_priv *priv, u8 sta_id) void __iomem *ctl = priv->ctl; u32 reghi, reglo; - reglo = 0x0; /* dump command */ - reglo|= 0x40000000; /* status bit */ + reglo = 0x40000000; /* status bit */ iowrite32(reglo, ctl + AGNX_RXM_HASH_CMD_LOW); iowrite32(sta_id << 16, ctl + AGNX_RXM_HASH_DUMP_DATA); udelay(80); reghi = ioread32(ctl + AGNX_RXM_HASH_CMD_HIGH); - reglo = ioread32(ctl + AGNX_RXM_HASH_CMD_LOW); + reglo = ioread32(ctl + AGNX_RXM_HASH_CMD_LOW); printk(PFX "hash cmd are : %.8x%.8x\n", reghi, reglo); reghi = ioread32(ctl + AGNX_RXM_HASH_CMD_FLAG); printk(PFX "hash flag is : %.8x\n", reghi); @@ -91,7 +90,7 @@ void hash_dump(struct agnx_priv *priv, u8 sta_id) void get_sta_power(struct agnx_priv *priv, struct agnx_sta_power *power, unsigned int sta_idx) { void __iomem *ctl = priv->ctl; - memcpy_fromio(power, ctl + AGNX_TXM_STAPOWTEMP + sizeof(*power) * sta_idx, + memcpy_fromio(power, ctl + AGNX_TXM_STAPOWTEMP + sizeof(*power) * sta_idx, sizeof(*power)); } @@ -100,7 +99,7 @@ set_sta_power(struct agnx_priv *priv, struct agnx_sta_power *power, unsigned int { void __iomem *ctl = priv->ctl; /* FIXME 2. Write Template to offset + station number */ - memcpy_toio(ctl + AGNX_TXM_STAPOWTEMP + sizeof(*power) * sta_idx, + memcpy_toio(ctl + AGNX_TXM_STAPOWTEMP + sizeof(*power) * sta_idx, power, sizeof(*power)); } @@ -135,7 +134,7 @@ inline void set_sta(struct agnx_priv *priv, struct agnx_sta *sta, unsigned int s { void __iomem *data = priv->data; - memcpy_toio(data + AGNX_PDUPOOL + sizeof(*sta) * sta_idx, + memcpy_toio(data + AGNX_PDUPOOL + sizeof(*sta) * sta_idx, sta, sizeof(*sta)); } @@ -165,7 +164,7 @@ static void sta_tx_workqueue_init(struct agnx_priv *priv, unsigned int sta_idx) reg = agnx_set_bits(WORK_QUEUE_VALID, WORK_QUEUE_VALID_SHIFT, 1); reg |= agnx_set_bits(WORK_QUEUE_ACK_TYPE, WORK_QUEUE_ACK_TYPE_SHIFT, 1); -// reg |= agnx_set_bits(WORK_QUEUE_ACK_TYPE, WORK_QUEUE_ACK_TYPE_SHIFT, 0); +/* reg |= agnx_set_bits(WORK_QUEUE_ACK_TYPE, WORK_QUEUE_ACK_TYPE_SHIFT, 0); */ tx_wq.reg2 |= cpu_to_le32(reg); /* Suppose all 8 traffic class are used */ @@ -181,7 +180,7 @@ static void sta_traffic_init(struct agnx_sta_traffic *traffic) reg = agnx_set_bits(NEW_PACKET, NEW_PACKET_SHIFT, 1); reg |= agnx_set_bits(TRAFFIC_VALID, TRAFFIC_VALID_SHIFT, 1); -// reg |= agnx_set_bits(TRAFFIC_ACK_TYPE, TRAFFIC_ACK_TYPE_SHIFT, 1); +/* reg |= agnx_set_bits(TRAFFIC_ACK_TYPE, TRAFFIC_ACK_TYPE_SHIFT, 1); */ traffic->reg0 = cpu_to_le32(reg); /* 3. setting RX Sequence Number to 4095 */ diff --git a/drivers/staging/agnx/sta.h b/drivers/staging/agnx/sta.h index 58d0b12900df..94e2cf1f973f 100644 --- a/drivers/staging/agnx/sta.h +++ b/drivers/staging/agnx/sta.h @@ -16,7 +16,7 @@ struct agnx_hash_cmd { #define PASS 0x00000001 #define PASS_SHIFT 1 __be32 cmdlo; -}__attribute__((__packed__)); +} __attribute__((__packed__)); /* diff --git a/drivers/staging/agnx/table.c b/drivers/staging/agnx/table.c index c60048487b5a..b52fef9db0e3 100644 --- a/drivers/staging/agnx/table.c +++ b/drivers/staging/agnx/table.c @@ -80,7 +80,7 @@ void routing_table_init(struct agnx_priv *priv) disable_receiver(priv); - for ( type = 0; type < 0x3; type++ ) { + for (type = 0; type < 0x3; type++) { for (subtype = 0; subtype < 0x10; subtype++) { /* 1. Set Routing table to R/W and to Return status on Read */ reg = (type << ROUTAB_TYPE_SHIFT) | @@ -89,7 +89,7 @@ void routing_table_init(struct agnx_priv *priv) if (type == ROUTAB_TYPE_DATA) { /* NULL goes to RFP */ if (subtype == ROUTAB_SUBTYPE_NULL) -// reg |= ROUTAB_ROUTE_RFP; +/* reg |= ROUTAB_ROUTE_RFP; */ reg |= ROUTAB_ROUTE_CPU; /* QOS NULL goes to CPU */ else if (subtype == ROUTAB_SUBTYPE_QOSNULL) @@ -104,7 +104,7 @@ void routing_table_init(struct agnx_priv *priv) (subtype == ROUTAB_SUBTYPE_QOSDATAPOLL) || (subtype == ROUTAB_SUBTYPE_QOSDATAACKPOLL)) reg |= ROUTAB_ROUTE_ENCRY; -// reg |= ROUTAB_ROUTE_CPU; +/* reg |= ROUTAB_ROUTE_CPU; */ /*Drop NULL and QOS NULL ack, poll and poll ack*/ else if ((subtype == ROUTAB_SUBTYPE_NULLACK) || (subtype == ROUTAB_SUBTYPE_QOSNULLACK) || @@ -112,11 +112,11 @@ void routing_table_init(struct agnx_priv *priv) (subtype == ROUTAB_SUBTYPE_QOSNULLPOLL) || (subtype == ROUTAB_SUBTYPE_NULLPOLLACK) || (subtype == ROUTAB_SUBTYPE_QOSNULLPOLLACK)) -// reg |= ROUTAB_ROUTE_DROP; +/* reg |= ROUTAB_ROUTE_DROP; */ reg |= ROUTAB_ROUTE_CPU; - } - else + } else { reg |= (ROUTAB_ROUTE_CPU); + } iowrite32(reg, ctl + AGNX_RXM_ROUTAB); /* Check to verify that the status bit cleared */ routing_table_delay(); diff --git a/drivers/staging/agnx/xmit.c b/drivers/staging/agnx/xmit.c index 7f01528b8a46..0e034081f3a5 100644 --- a/drivers/staging/agnx/xmit.c +++ b/drivers/staging/agnx/xmit.c @@ -17,8 +17,8 @@ #include "debug.h" #include "phy.h" -unsigned int rx_frame_cnt = 0; -//unsigned int local_tx_sent_cnt = 0; +unsigned int rx_frame_cnt; +/* unsigned int local_tx_sent_cnt = 0; */ static inline void disable_rx_engine(struct agnx_priv *priv) { @@ -242,15 +242,15 @@ static void get_rx_stats(struct agnx_priv *priv, struct agnx_hdr *hdr, memset(stat, 0, sizeof(*stat)); /* RSSI */ rssi = (u8 *)&hdr->phy_stats_lo; -// stat->ssi = (rssi[0] + rssi[1] + rssi[2]) / 3; +/* stat->ssi = (rssi[0] + rssi[1] + rssi[2]) / 3; */ /* Noise */ noise = ioread32(ctl + AGNX_GCR_NOISE0); noise += ioread32(ctl + AGNX_GCR_NOISE1); noise += ioread32(ctl + AGNX_GCR_NOISE2); stat->noise = noise / 3; /* Signal quality */ - //snr = stat->ssi - stat->noise; - if (snr >=0 && snr < 40) +/* snr = stat->ssi - stat->noise; */ + if (snr >= 0 && snr < 40) stat->signal = 5 * snr / 2; else if (snr >= 40) stat->signal = 100; @@ -269,10 +269,9 @@ static void get_rx_stats(struct agnx_priv *priv, struct agnx_hdr *hdr, stat->band = IEEE80211_BAND_2GHZ; stat->freq = agnx_channels[priv->channel - 1].center_freq; -// stat->antenna = 3; -// stat->mactime = be32_to_cpu(hdr->time_stamp); -// stat->channel = priv->channel; - +/* stat->antenna = 3; + stat->mactime = be32_to_cpu(hdr->time_stamp); + stat->channel = priv->channel; */ } static inline void combine_hdr_frag(struct ieee80211_hdr *ieeehdr, @@ -296,7 +295,7 @@ static inline void combine_hdr_frag(struct ieee80211_hdr *ieeehdr, static inline int agnx_packet_check(struct agnx_priv *priv, struct agnx_hdr *agnxhdr, unsigned packet_len) { - if (agnx_get_bits(CRC_FAIL, CRC_FAIL_SHIFT, be32_to_cpu(agnxhdr->reg1)) == 1){ + if (agnx_get_bits(CRC_FAIL, CRC_FAIL_SHIFT, be32_to_cpu(agnxhdr->reg1)) == 1) { printk(PFX "RX: CRC check fail\n"); goto drop; } @@ -320,7 +319,7 @@ void handle_rx_irq(struct agnx_priv *priv) { struct ieee80211_rx_status status; unsigned int len; -// AGNX_TRACE; +/* AGNX_TRACE; */ do { struct agnx_desc *desc; @@ -341,54 +340,54 @@ void handle_rx_irq(struct agnx_priv *priv) len = (frag & PACKET_LEN) >> PACKET_LEN_SHIFT; if (agnx_packet_check(priv, hdr, len) == -1) { - rx_desc_reusing(priv, i); + rx_desc_reusing(priv, i); continue; } skb_put(skb, len); do { - u16 fctl; + u16 fctl; fctl = le16_to_cpu(((struct ieee80211_hdr *)hdr->mac_hdr)->frame_control); - if ((fctl & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_BEACON)// && !(fctl & IEEE80211_STYPE_BEACON)) + if ((fctl & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_BEACON)/* && !(fctl & IEEE80211_STYPE_BEACON)) */ dump_ieee80211_hdr((struct ieee80211_hdr *)hdr->mac_hdr, "RX"); } while (0); if (hdr->_11b0 && !hdr->_11g0) { -/* int j; */ -/* u16 fctl = le16_to_cpu(((struct ieee80211_hdr *)hdr->mac_hdr) */ -/* ->frame_control); */ -/* if ( (fctl & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) { */ -/* agnx_print_rx_hdr(hdr); */ -// agnx_print_sta(priv, BSSID_STAID); -/* for (j = 0; j < 8; j++) */ -/* agnx_print_sta_tx_wq(priv, BSSID_STAID, j); */ -/* } */ +/* int j; + u16 fctl = le16_to_cpu(((struct ieee80211_hdr *)hdr->mac_hdr) + ->frame_control); + if ( (fctl & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) { + agnx_print_rx_hdr(hdr); + agnx_print_sta(priv, BSSID_STAID); + for (j = 0; j < 8; j++) + agnx_print_sta_tx_wq(priv, BSSID_STAID, j); + } */ get_rx_stats(priv, hdr, &status); skb_pull(skb, sizeof(*hdr)); combine_hdr_frag((struct ieee80211_hdr *)hdr->mac_hdr, skb); } else if (!hdr->_11b0 && hdr->_11g0) { -// int j; +/* int j; */ agnx_print_rx_hdr(hdr); agnx_print_sta(priv, BSSID_STAID); -// for (j = 0; j < 8; j++) +/* for (j = 0; j < 8; j++) */ agnx_print_sta_tx_wq(priv, BSSID_STAID, 0); print_hex_dump_bytes("agnx: RX_PACKET: ", DUMP_PREFIX_NONE, skb->data, skb->len + 8); -// if (agnx_plcp_get_bitrate_ofdm(&hdr->_11g0) == 0) +/* if (agnx_plcp_get_bitrate_ofdm(&hdr->_11g0) == 0) */ get_rx_stats(priv, hdr, &status); skb_pull(skb, sizeof(*hdr)); combine_hdr_frag((struct ieee80211_hdr *) ((void *)&hdr->mac_hdr), skb); -// dump_ieee80211_hdr((struct ieee80211_hdr *)skb->data, "RX G"); +/* dump_ieee80211_hdr((struct ieee80211_hdr *)skb->data, "RX G"); */ } else agnx_bug("Unknown packets type"); ieee80211_rx_irqsafe(priv->hw, skb, &status); rx_desc_reinit(priv, i); - } while ( priv->rx.idx++ ); + } while (priv->rx.idx++); } /* handle_rx_irq */ static inline void handle_tx_irq(struct agnx_priv *priv, struct agnx_ring *ring) @@ -415,40 +414,40 @@ static inline void handle_tx_irq(struct agnx_priv *priv, struct agnx_ring *ring) pci_unmap_single(priv->pdev, info->mapping, info->dma_len, PCI_DMA_TODEVICE); do { -// int j; +/* int j; */ size_t len; len = info->skb->len - sizeof(struct agnx_hdr) + info->hdr_len; - // if (len == 614) { -// agnx_print_desc(desc); +/* if (len == 614) { */ +/* agnx_print_desc(desc); */ if (info->type == PACKET) { -// agnx_print_tx_hdr((struct agnx_hdr *)info->skb->data); -/* agnx_print_sta_power(priv, LOCAL_STAID); */ -/* agnx_print_sta(priv, LOCAL_STAID); */ -/* // for (j = 0; j < 8; j++) */ -/* agnx_print_sta_tx_wq(priv, LOCAL_STAID, 0); */ -// agnx_print_sta_power(priv, BSSID_STAID); -// agnx_print_sta(priv, BSSID_STAID); -// for (j = 0; j < 8; j++) -// agnx_print_sta_tx_wq(priv, BSSID_STAID, 0); +/* agnx_print_tx_hdr((struct agnx_hdr *)info->skb->data); */ +/* agnx_print_sta_power(priv, LOCAL_STAID); */ +/* agnx_print_sta(priv, LOCAL_STAID); */ +/* for (j = 0; j < 8; j++) */ +/* agnx_print_sta_tx_wq(priv, LOCAL_STAID, 0); */ +/* agnx_print_sta_power(priv, BSSID_STAID); */ +/* agnx_print_sta(priv, BSSID_STAID); */ +/* for (j = 0; j < 8; j++) */ +/* agnx_print_sta_tx_wq(priv, BSSID_STAID, 0); */ } -// } +/* } */ } while (0); if (info->type == PACKET) { -// dump_txm_registers(priv); -// dump_rxm_registers(priv); -// dump_bm_registers(priv); -// dump_cir_registers(priv); +/* dump_txm_registers(priv); + dump_rxm_registers(priv); + dump_bm_registers(priv); + dump_cir_registers(priv); */ } if (info->type == PACKET) { -// struct ieee80211_hdr *hdr; +/* struct ieee80211_hdr *hdr; */ struct ieee80211_tx_info *txi = IEEE80211_SKB_CB(info->skb); skb_pull(info->skb, sizeof(struct agnx_hdr)); memcpy(skb_push(info->skb, info->hdr_len), &info->hdr, info->hdr_len); -// dump_ieee80211_hdr((struct ieee80211_hdr *)info->skb->data, "TX_HANDLE"); +/* dump_ieee80211_hdr((struct ieee80211_hdr *)info->skb->data, "TX_HANDLE"); */ /* print_hex_dump_bytes("agnx: TX_HANDLE: ", DUMP_PREFIX_NONE, */ /* info->skb->data, info->skb->len); */ @@ -462,7 +461,7 @@ static inline void handle_tx_irq(struct agnx_priv *priv, struct agnx_ring *ring) /* ieee80211_tx_status_irqsafe(priv->hw, info->skb, &(info->tx_status)); */ /* } else */ /* dev_kfree_skb_irq(info->skb); */ - } + } memset(desc, 0, sizeof(*desc)); memset(info, 0, sizeof(*info)); } @@ -485,7 +484,7 @@ void handle_txd_irq(struct agnx_priv *priv) void handle_other_irq(struct agnx_priv *priv) { -// void __iomem *ctl = priv->ctl; +/* void __iomem *ctl = priv->ctl; */ u32 status = priv->irq_status; void __iomem *ctl = priv->ctl; u32 reg; @@ -526,11 +525,11 @@ void handle_other_irq(struct agnx_priv *priv) iowrite32(reg, ctl + AGNX_INT_MASK); iowrite32(IRQ_RX_FRAME, ctl + AGNX_INT_STAT); printk(PFX "IRQ: RX Frame\n"); - rx_frame_cnt++; + rx_frame_cnt++; } if (status & IRQ_ERR_INT) { iowrite32(IRQ_ERR_INT, ctl + AGNX_INT_STAT); -// agnx_hw_reset(priv); +/* agnx_hw_reset(priv); */ printk(PFX "IRQ: Error Interrupt\n"); } if (status & IRQ_TX_QUE_FULL) @@ -558,14 +557,14 @@ void handle_other_irq(struct agnx_priv *priv) static inline void route_flag_set(struct agnx_hdr *txhdr) { -// u32 reg = 0; +/* u32 reg = 0; */ /* FIXME */ -/* reg = (0x7 << ROUTE_COMPRESSION_SHIFT) & ROUTE_COMPRESSION; */ -/* txhdr->reg5 = cpu_to_be32(reg); */ - txhdr->reg5 = (0xa << 0x0) | (0x7 << 0x18); -// txhdr->reg5 = cpu_to_be32((0xa << 0x0) | (0x7 << 0x18)); -// txhdr->reg5 = cpu_to_be32(0x7 << 0x0); +/* reg = (0x7 << ROUTE_COMPRESSION_SHIFT) & ROUTE_COMPRESSION; */ +/* txhdr->reg5 = cpu_to_be32(reg); */ + txhdr->reg5 = (0xa << 0x0) | (0x7 << 0x18); +/* txhdr->reg5 = cpu_to_be32((0xa << 0x0) | (0x7 << 0x18)); */ +/* txhdr->reg5 = cpu_to_be32(0x7 << 0x0); */ } /* Return 0 if no match */ @@ -579,12 +578,29 @@ static inline unsigned int get_power_level(unsigned int rate, unsigned int anten case 55: case 60: case 90: - case 120: power_level = 22; break; - case 180: power_level = 19; break; - case 240: power_level = 18; break; - case 360: power_level = 16; break; - case 480: power_level = 15; break; - case 540: power_level = 14; break; + case 120: + power_level = 22; + break; + + case 180: + power_level = 19; + break; + + case 240: + power_level = 18; + break; + + case 360: + power_level = 16; + break; + + case 480: + power_level = 15; + break; + + case 540: + power_level = 14; + break; default: agnx_bug("Error rate setting\n"); } @@ -604,30 +620,30 @@ static inline void fill_agnx_hdr(struct agnx_priv *priv, struct agnx_info *tx_in memset(txhdr, 0, sizeof(*txhdr)); -// reg = agnx_set_bits(STATION_ID, STATION_ID_SHIFT, LOCAL_STAID); +/* reg = agnx_set_bits(STATION_ID, STATION_ID_SHIFT, LOCAL_STAID); */ reg = agnx_set_bits(STATION_ID, STATION_ID_SHIFT, BSSID_STAID); reg |= agnx_set_bits(WORKQUEUE_ID, WORKQUEUE_ID_SHIFT, 0); txhdr->reg4 = cpu_to_be32(reg); /* Set the Hardware Sequence Number to 1? */ reg = agnx_set_bits(SEQUENCE_NUMBER, SEQUENCE_NUMBER_SHIFT, 0); -// reg = agnx_set_bits(SEQUENCE_NUMBER, SEQUENCE_NUMBER_SHIFT, 1); +/* reg = agnx_set_bits(SEQUENCE_NUMBER, SEQUENCE_NUMBER_SHIFT, 1); */ reg |= agnx_set_bits(MAC_HDR_LEN, MAC_HDR_LEN_SHIFT, tx_info->hdr_len); txhdr->reg1 = cpu_to_be32(reg); /* Set the agnx_hdr's MAC header */ memcpy(txhdr->mac_hdr, &tx_info->hdr, tx_info->hdr_len); reg = agnx_set_bits(ACK, ACK_SHIFT, 1); -// reg = agnx_set_bits(ACK, ACK_SHIFT, 0); +/* reg = agnx_set_bits(ACK, ACK_SHIFT, 0); */ reg |= agnx_set_bits(MULTICAST, MULTICAST_SHIFT, 0); -// reg |= agnx_set_bits(MULTICAST, MULTICAST_SHIFT, 1); +/* reg |= agnx_set_bits(MULTICAST, MULTICAST_SHIFT, 1); */ reg |= agnx_set_bits(RELAY, RELAY_SHIFT, 0); reg |= agnx_set_bits(TM, TM_SHIFT, 0); txhdr->reg0 = cpu_to_be32(reg); /* Set the long and short retry limits */ - txhdr->tx.short_retry_limit = tx_info->txi->control.rates[0].count; - txhdr->tx.long_retry_limit = tx_info->txi->control.rates[0].count; + txhdr->tx.short_retry_limit = tx_info->txi->control.rates[0].count; + txhdr->tx.long_retry_limit = tx_info->txi->control.rates[0].count; /* FIXME */ len = tx_info->skb->len - sizeof(*txhdr) + tx_info->hdr_len + FCS_LEN; @@ -652,23 +668,23 @@ static void txm_power_set(struct agnx_priv *priv, if (txi->control.rates[0].idx < 0) { /* For B mode Short Preamble */ reg = agnx_set_bits(PHY_MODE, PHY_MODE_SHIFT, AGNX_MODE_80211B_SHORT); -// control->tx_rate = -control->tx_rate; +/* control->tx_rate = -control->tx_rate; */ } else reg = agnx_set_bits(PHY_MODE, PHY_MODE_SHIFT, AGNX_MODE_80211G); -// reg = agnx_set_bits(PHY_MODE, PHY_MODE_SHIFT, AGNX_MODE_80211B_LONG); +/* reg = agnx_set_bits(PHY_MODE, PHY_MODE_SHIFT, AGNX_MODE_80211B_LONG); */ reg |= agnx_set_bits(SIGNAL, SIGNAL_SHIFT, 0xB); reg |= agnx_set_bits(RATE, RATE_SHIFT, 0xB); -// reg |= agnx_set_bits(POWER_LEVEL, POWER_LEVEL_SHIFT, 15); +/* reg |= agnx_set_bits(POWER_LEVEL, POWER_LEVEL_SHIFT, 15); */ reg |= agnx_set_bits(POWER_LEVEL, POWER_LEVEL_SHIFT, 20); /* if rate < 11M set it to 0 */ reg |= agnx_set_bits(NUM_TRANSMITTERS, NUM_TRANSMITTERS_SHIFT, 1); -// reg |= agnx_set_bits(EDCF, EDCF_SHIFT, 1); -// reg |= agnx_set_bits(TIFS, TIFS_SHIFT, 1); +/* reg |= agnx_set_bits(EDCF, EDCF_SHIFT, 1); */ +/* reg |= agnx_set_bits(TIFS, TIFS_SHIFT, 1); */ power.reg = reg; -// power.reg = cpu_to_le32(reg); +/* power.reg = cpu_to_le32(reg); */ -// set_sta_power(priv, &power, LOCAL_STAID); +/* set_sta_power(priv, &power, LOCAL_STAID); */ set_sta_power(priv, &power, BSSID_STAID); } @@ -759,24 +775,24 @@ static int __agnx_tx(struct agnx_priv *priv, struct sk_buff *skb, txm_power_set(priv, txi); -/* do { */ -/* int j; */ -/* size_t len; */ -/* len = skb->len - hdr_info->dma_len + hdr_info->hdr_len; */ -/* // if (len == 614) { */ -/* agnx_print_desc(hdr_desc); */ -/* agnx_print_desc(frag_desc); */ -/* agnx_print_tx_hdr((struct agnx_hdr *)skb->data); */ -/* agnx_print_sta_power(priv, LOCAL_STAID); */ -/* agnx_print_sta(priv, LOCAL_STAID); */ -/* for (j = 0; j < 8; j++) */ -/* agnx_print_sta_tx_wq(priv, LOCAL_STAID, j); */ -/* agnx_print_sta_power(priv, BSSID_STAID); */ -/* agnx_print_sta(priv, BSSID_STAID); */ -/* for (j = 0; j < 8; j++) */ -/* agnx_print_sta_tx_wq(priv, BSSID_STAID, j); */ -/* // } */ -/* } while (0); */ +/* do { */ +/* int j; */ +/* size_t len; */ +/* len = skb->len - hdr_info->dma_len + hdr_info->hdr_len; */ +/* if (len == 614) { */ +/* agnx_print_desc(hdr_desc); */ +/* agnx_print_desc(frag_desc); */ +/* agnx_print_tx_hdr((struct agnx_hdr *)skb->data); */ +/* agnx_print_sta_power(priv, LOCAL_STAID); */ +/* agnx_print_sta(priv, LOCAL_STAID); */ +/* for (j = 0; j < 8; j++) */ +/* agnx_print_sta_tx_wq(priv, LOCAL_STAID, j); */ +/* agnx_print_sta_power(priv, BSSID_STAID); */ +/* agnx_print_sta(priv, BSSID_STAID); */ +/* for (j = 0; j < 8; j++) */ +/* agnx_print_sta_tx_wq(priv, BSSID_STAID, j); */ +/* } */ +/* } while (0); */ spin_unlock_irqrestore(&priv->lock, flags); @@ -787,7 +803,7 @@ static int __agnx_tx(struct agnx_priv *priv, struct sk_buff *skb, reg = (ioread32(priv->ctl + AGNX_CIR_TXMCTL)); reg |= 0x8; iowrite32((reg), priv->ctl + AGNX_CIR_TXMCTL); - }while (0); + } while (0); /* Trigger TXD */ do { @@ -795,7 +811,7 @@ static int __agnx_tx(struct agnx_priv *priv, struct sk_buff *skb, reg = (ioread32(priv->ctl + AGNX_CIR_TXDCTL)); reg |= 0x8; iowrite32((reg), priv->ctl + AGNX_CIR_TXDCTL); - }while (0); + } while (0); return 0; } @@ -807,12 +823,12 @@ int _agnx_tx(struct agnx_priv *priv, struct sk_buff *skb) if (tx_packet_check(skb)) return 0; -/* print_hex_dump_bytes("agnx: TX_PACKET: ", DUMP_PREFIX_NONE, */ -/* skb->data, skb->len); */ +/* print_hex_dump_bytes("agnx: TX_PACKET: ", DUMP_PREFIX_NONE, */ +/* skb->data, skb->len); */ - fctl = le16_to_cpu(*((__le16 *)skb->data)); + fctl = le16_to_cpu(*((__le16 *)skb->data)); - if ( (fctl & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA ) + if ((fctl & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) return __agnx_tx(priv, skb, &priv->txd); else return __agnx_tx(priv, skb, &priv->txm); diff --git a/drivers/staging/altpciechdma/altpciechdma.c b/drivers/staging/altpciechdma/altpciechdma.c index f516140ca976..3e41e0861481 100644 --- a/drivers/staging/altpciechdma/altpciechdma.c +++ b/drivers/staging/altpciechdma/altpciechdma.c @@ -46,7 +46,6 @@ #include <linux/cdev.h> #include <linux/delay.h> #include <linux/dma-mapping.h> -#include <linux/delay.h> #include <linux/init.h> #include <linux/interrupt.h> #include <linux/io.h> @@ -313,15 +312,16 @@ static int __devinit map_bars(struct ape_dev *ape, struct pci_dev *dev) continue; /* do not map BARs with address 0 */ if (!bar_start || !bar_end) { - printk(KERN_DEBUG "BAR #%d is not present?!\n", i); + printk(KERN_DEBUG "BAR #%d is not present?!\n", i); rc = -1; goto fail; } bar_length = bar_end - bar_start + 1; /* BAR length is less than driver requires? */ if (bar_length < bar_min_len[i]) { - printk(KERN_DEBUG "BAR #%d length = %lu bytes but driver " - "requires at least %lu bytes\n", i, bar_length, bar_min_len[i]); + printk(KERN_DEBUG "BAR #%d length = %lu bytes but driver " + "requires at least %lu bytes\n", + i, bar_length, bar_min_len[i]); rc = -1; goto fail; } @@ -333,8 +333,8 @@ static int __devinit map_bars(struct ape_dev *ape, struct pci_dev *dev) rc = -1; goto fail; } - printk(KERN_DEBUG "BAR[%d] mapped at 0x%p with length %lu(/%lu).\n", i, - ape->bar[i], bar_min_len[i], bar_length); + printk(KERN_DEBUG "BAR[%d] mapped at 0x%p with length %lu(/%lu).\n", i, + ape->bar[i], bar_min_len[i], bar_length); } /* succesfully mapped all required BAR regions */ rc = 0; @@ -427,11 +427,13 @@ static int ape_sg_to_chdma_table(struct scatterlist *sgl, int nents, int first, dma_addr_t next = sg_dma_address(&sgl[i + 1]); /* length of this entry i */ len = sg_dma_len(&sgl[i]); - printk(KERN_DEBUG "%04d: addr=0x%08x length=0x%08x\n", i, addr, len); + printk(KERN_DEBUG "%04d: addr=0x%Lx length=0x%08x\n", i, + (unsigned long long)addr, len); /* entry i + 1 is non-contiguous with entry i? */ if (next != addr + len) { /* TODO create entry here (we could overwrite i) */ - printk(KERN_DEBUG "%4d: cont_addr=0x%08x cont_len=0x%08x\n", j, cont_addr, cont_len); + printk(KERN_DEBUG "%4d: cont_addr=0x%Lx cont_len=0x%08x\n", j, + (unsigned long long)cont_addr, cont_len); /* set descriptor for contiguous transfer */ ape_chdma_desc_set(&desc[j], cont_addr, ep_addr, cont_len); /* next end point memory address */ @@ -447,8 +449,10 @@ static int ape_sg_to_chdma_table(struct scatterlist *sgl, int nents, int first, addr = next; } /* TODO create entry here (we could overwrite i) */ - printk(KERN_DEBUG "%04d: addr=0x%08x length=0x%08x\n", i, addr, len); - printk(KERN_DEBUG "%4d: cont_addr=0x%08x length=0x%08x\n", j, cont_addr, cont_len); + printk(KERN_DEBUG "%04d: addr=0x%Lx length=0x%08x\n", i, + (unsigned long long)addr, len); + printk(KERN_DEBUG "%4d: cont_addr=0x%Lx length=0x%08x\n", j, + (unsigned long long)cont_addr, cont_len); j++; return j; } @@ -467,15 +471,14 @@ static inline int compare(u32 *p, u32 *q, int len) } else { fail++; /* show the first few miscompares */ - if (fail < 10) { - printk(KERN_DEBUG "[%p] = 0x%08x != [%p] = 0x%08x ?!\n", p, *p, q, *q); - /* but stop after a while */ - } else if (fail == 10) { - printk(KERN_DEBUG "---more errors follow! not printed---\n"); - } else { + if (fail < 10) + printk(KERN_DEBUG "[%p] = 0x%08x != [%p] = 0x%08x ?!\n", p, *p, q, *q); + /* but stop after a while */ + else if (fail == 10) + printk(KERN_DEBUG "---more errors follow! not printed---\n"); + else /* stop compare after this many errors */ - break; - } + break; } p++; q++; @@ -528,7 +531,7 @@ static int __devinit dma_test(struct ape_dev *ape, struct pci_dev *dev) printk(KERN_DEBUG "ape->table_virt = 0x%p.\n", ape->table_virt); if (!write_header || !read_header || !ape->table_virt) - goto fail; + goto fail; /* allocate and map coherently-cached memory for a DMA-able buffer */ /* @see Documentation/PCI/PCI-DMA-mapping.txt, near line 318 */ @@ -565,9 +568,8 @@ static int __devinit dma_test(struct ape_dev *ape, struct pci_dev *dev) /* read 8192 bytes from RC buffer to EP address 4096 */ ape_chdma_desc_set(&ape->table_virt->desc[n], buffer_bus, 4096, 2 * PAGE_SIZE); #if 1 - for (i = 0; i < 255; i++) { + for (i = 0; i < 255; i++) ape_chdma_desc_set(&ape->table_virt->desc[i], buffer_bus, 4096, 2 * PAGE_SIZE); - } /* index of last descriptor */ n = i - 1; #endif @@ -647,7 +649,7 @@ static int __devinit dma_test(struct ape_dev *ape, struct pci_dev *dev) printk(KERN_DEBUG "EPLAST = %u, n = %d\n", eplast, n); if (eplast == n) { printk(KERN_DEBUG "DONE\n"); - /* print IRQ count before the transfer */ + /* print IRQ count before the transfer */ printk(KERN_DEBUG "#IRQs during transfer: %d\n", ape->irq_count - irq_count); break; } @@ -661,9 +663,9 @@ static int __devinit dma_test(struct ape_dev *ape, struct pci_dev *dev) n = 0; ape_chdma_desc_set(&ape->table_virt->desc[n], buffer_bus + 8192, 4096, 2 * PAGE_SIZE); #if 1 - for (i = 0; i < 255; i++) { + for (i = 0; i < 255; i++) ape_chdma_desc_set(&ape->table_virt->desc[i], buffer_bus + 8192, 4096, 2 * PAGE_SIZE); - } + /* index of last descriptor */ n = i - 1; #endif @@ -691,7 +693,7 @@ static int __devinit dma_test(struct ape_dev *ape, struct pci_dev *dev) w = (u32)(n + 1); /* enable updates of eplast for each descriptor completion */ w |= (u32)(1UL << 18)/*global EPLAST_EN*/; -#if 0 // test variable, make a module option later +#if 0 /* test variable, make a module option later */ /* enable MSI for each descriptor completion */ if (ape->msi_enabled) w |= (1UL << 17)/*global MSI*/; @@ -715,7 +717,7 @@ static int __devinit dma_test(struct ape_dev *ape, struct pci_dev *dev) /** memory write barrier */ wmb(); /** dummy read to flush posted writes */ - //(void)ioread32(); + /* (void) ioread32(); */ printk(KERN_DEBUG "POLL FOR WRITE:\n"); /* poll for completion, 1000 times 1 millisecond */ @@ -844,7 +846,7 @@ static int __devinit probe(struct pci_dev *dev, const struct pci_device_id *id) } ape->got_regions = 1; -#if 1 // @todo For now, disable 64-bit, because I do not understand the implications (DAC!) +#if 1 /* @todo For now, disable 64-bit, because I do not understand the implications (DAC!) */ /* query for DMA transfer */ /* @see Documentation/PCI/PCI-DMA-mapping.txt */ if (!pci_set_dma_mask(dev, DMA_64BIT_MASK)) { @@ -947,7 +949,8 @@ static void __devexit remove(struct pci_dev *dev) struct ape_dev *ape; printk(KERN_DEBUG "remove(0x%p)\n", dev); if ((dev == 0) || (dev->dev.driver_data == 0)) { - printk(KERN_DEBUG "remove(dev = 0x%p) dev->dev.driver_data = 0x%p\n", dev, dev->dev.driver_data); + printk(KERN_DEBUG "remove(dev = 0x%p) dev->dev.driver_data = 0x%p\n", + dev, (dev? dev->dev.driver_data: NULL)); return; } ape = (struct ape_dev *)dev->dev.driver_data; @@ -1048,10 +1051,9 @@ static ssize_t sg_write(struct file *file, const char __user *buf, size_t count, printk(KERN_DEBUG DRV_NAME "_write(buf=0x%p, count=%lld, pos=%llu)\n", buf, (s64)count, (u64)*pos); /* TODO transfer boundaries at PAGE_SIZE granularity */ - while (remaining > 0) - { + while (remaining > 0) { /* limit DMA transfer size */ - transfer_len = (remaining < APE_CHDMA_MAX_TRANSFER_LEN)? remaining: + transfer_len = (remaining < APE_CHDMA_MAX_TRANSFER_LEN) ? remaining : APE_CHDMA_MAX_TRANSFER_LEN; /* get all user space buffer pages and create a scattergather list */ sgm_map_user_pages(ape->sgm, transfer_addr, transfer_len, 0/*read from userspace*/); @@ -1085,12 +1087,12 @@ static ssize_t sg_write(struct file *file, const char __user *buf, size_t count, /* * character device file operations */ -static struct file_operations sg_fops = { - .owner = THIS_MODULE, - .open = sg_open, - .release = sg_close, - .read = sg_read, - .write = sg_write, +static const struct file_operations sg_fops = { + .owner = THIS_MODULE, + .open = sg_open, + .release = sg_close, + .read = sg_read, + .write = sg_write, }; /* sg_init() - Initialize character device @@ -1158,12 +1160,12 @@ static struct pci_driver pci_driver = { */ static int __init alterapciechdma_init(void) { - int rc = 0; + int rc = 0; printk(KERN_DEBUG DRV_NAME " init(), built at " __DATE__ " " __TIME__ "\n"); /* register this driver with the PCI bus driver */ rc = pci_register_driver(&pci_driver); if (rc < 0) - return rc; + return rc; return 0; } diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c index 758131cad08a..79e90fed27d3 100644 --- a/drivers/staging/android/binder.c +++ b/drivers/staging/android/binder.c @@ -2649,14 +2649,22 @@ static void binder_vma_open(struct vm_area_struct *vma) { struct binder_proc *proc = vma->vm_private_data; if (binder_debug_mask & BINDER_DEBUG_OPEN_CLOSE) - printk(KERN_INFO "binder: %d open vm area %lx-%lx (%ld K) vma %lx pagep %lx\n", proc->pid, vma->vm_start, vma->vm_end, (vma->vm_end - vma->vm_start) / SZ_1K, vma->vm_flags, pgprot_val(vma->vm_page_prot)); + printk(KERN_INFO + "binder: %d open vm area %lx-%lx (%ld K) vma %lx pagep %lx\n", + proc->pid, vma->vm_start, vma->vm_end, + (vma->vm_end - vma->vm_start) / SZ_1K, vma->vm_flags, + (unsigned long)pgprot_val(vma->vm_page_prot)); dump_stack(); } static void binder_vma_close(struct vm_area_struct *vma) { struct binder_proc *proc = vma->vm_private_data; if (binder_debug_mask & BINDER_DEBUG_OPEN_CLOSE) - printk(KERN_INFO "binder: %d close vm area %lx-%lx (%ld K) vma %lx pagep %lx\n", proc->pid, vma->vm_start, vma->vm_end, (vma->vm_end - vma->vm_start) / SZ_1K, vma->vm_flags, pgprot_val(vma->vm_page_prot)); + printk(KERN_INFO + "binder: %d close vm area %lx-%lx (%ld K) vma %lx pagep %lx\n", + proc->pid, vma->vm_start, vma->vm_end, + (vma->vm_end - vma->vm_start) / SZ_1K, vma->vm_flags, + (unsigned long)pgprot_val(vma->vm_page_prot)); proc->vma = NULL; } @@ -2677,7 +2685,11 @@ static int binder_mmap(struct file *filp, struct vm_area_struct *vma) vma->vm_end = vma->vm_start + SZ_4M; if (binder_debug_mask & BINDER_DEBUG_OPEN_CLOSE) - printk(KERN_INFO "binder_mmap: %d %lx-%lx (%ld K) vma %lx pagep %lx\n", proc->pid, vma->vm_start, vma->vm_end, (vma->vm_end - vma->vm_start) / SZ_1K, vma->vm_flags, pgprot_val(vma->vm_page_prot)); + printk(KERN_INFO + "binder_mmap: %d %lx-%lx (%ld K) vma %lx pagep %lx\n", + proc->pid, vma->vm_start, vma->vm_end, + (vma->vm_end - vma->vm_start) / SZ_1K, vma->vm_flags, + (unsigned long)pgprot_val(vma->vm_page_prot)); if (vma->vm_flags & FORBIDDEN_MMAP_FLAGS) { ret = -EPERM; diff --git a/drivers/staging/android/ram_console.c b/drivers/staging/android/ram_console.c index 643ac5ce381d..3375c1cce2b3 100644 --- a/drivers/staging/android/ram_console.c +++ b/drivers/staging/android/ram_console.c @@ -225,7 +225,7 @@ static int __init ram_console_init(struct ram_console_buffer *buffer, buffer_size - sizeof(struct ram_console_buffer); if (ram_console_buffer_size > buffer_size) { - pr_err("ram_console: buffer %p, invalid size %d, datasize %d\n", + pr_err("ram_console: buffer %p, invalid size %zu, datasize %zu\n", buffer, buffer_size, ram_console_buffer_size); return 0; } @@ -235,8 +235,8 @@ static int __init ram_console_init(struct ram_console_buffer *buffer, ECC_BLOCK_SIZE) + 1) * ECC_SIZE; if (ram_console_buffer_size > buffer_size) { - pr_err("ram_console: buffer %p, invalid size %d, " - "non-ecc datasize %d\n", + pr_err("ram_console: buffer %p, invalid size %zu, " + "non-ecc datasize %zu\n", buffer, buffer_size, ram_console_buffer_size); return 0; } @@ -322,7 +322,7 @@ static int ram_console_driver_probe(struct platform_device *pdev) } buffer_size = res->end - res->start + 1; start = res->start; - printk(KERN_INFO "ram_console: got buffer at %x, size %x\n", + printk(KERN_INFO "ram_console: got buffer at %zx, size %zx\n", start, buffer_size); buffer = ioremap(res->start, buffer_size); if (buffer == NULL) { diff --git a/drivers/staging/asus_oled/asus_oled.c b/drivers/staging/asus_oled/asus_oled.c index 666a186e212b..04dde4b82817 100644 --- a/drivers/staging/asus_oled/asus_oled.c +++ b/drivers/staging/asus_oled/asus_oled.c @@ -56,10 +56,10 @@ MODULE_AUTHOR("Jakub Schmidtke, sjakub@gmail.com"); MODULE_DESCRIPTION("Asus OLED Driver v" ASUS_OLED_VERSION); MODULE_LICENSE("GPL"); -static struct class *oled_class = 0; -static int oled_num = 0; +static struct class *oled_class; +static int oled_num; -static uint start_off = 0; +static uint start_off; module_param(start_off, uint, 0644); @@ -80,20 +80,20 @@ struct oled_dev_desc_str { }; /* table of devices that work with this driver */ -static struct usb_device_id id_table [] = { +static struct usb_device_id id_table[] = { { USB_DEVICE(0x0b05, 0x1726) }, // Asus G1/G2 (and variants) { USB_DEVICE(0x0b05, 0x175b) }, // Asus G50V (and possibly others - G70? G71?) { }, }; /* parameters of specific devices */ -static struct oled_dev_desc_str oled_dev_desc_table [] = { +static struct oled_dev_desc_str oled_dev_desc_table[] = { { 0x0b05, 0x1726, 128, PACK_MODE_G1, "G1/G2" }, { 0x0b05, 0x175b, 256, PACK_MODE_G50, "G50" }, { }, }; -MODULE_DEVICE_TABLE (usb, id_table); +MODULE_DEVICE_TABLE(usb, id_table); #define SETUP_PACKET_HEADER(packet, val1, val2, val3, val4, val5, val6, val7) \ do { \ @@ -107,7 +107,7 @@ MODULE_DEVICE_TABLE (usb, id_table); packet->header.value6 = val5; \ packet->header.value7 = val6; \ packet->header.value8 = val7; \ - } while(0); + } while (0); struct asus_oled_header { uint8_t magic1; @@ -160,10 +160,12 @@ static void enable_oled(struct asus_oled_dev *odev, uint8_t enabl) SETUP_PACKET_HEADER(packet, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00); - if (enabl) packet->bitmap[0] = 0xaf; - else packet->bitmap[0] = 0xae; + if (enabl) + packet->bitmap[0] = 0xaf; + else + packet->bitmap[0] = 0xae; - for (a=0; a<1; a++) { + for (a = 0; a < 1; a++) { retval = usb_bulk_msg(odev->udev, usb_sndbulkpipe(odev->udev, 2), packet, @@ -252,7 +254,7 @@ static void send_packets(struct usb_device *udev, struct asus_oled_packet *packe } } -static void send_packet(struct usb_device *udev, struct asus_oled_packet *packet, size_t offset, size_t len, char *buf, uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5, uint8_t b6){ +static void send_packet(struct usb_device *udev, struct asus_oled_packet *packet, size_t offset, size_t len, char *buf, uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5, uint8_t b6) { int retval; int act_len; @@ -294,7 +296,7 @@ static void send_data(struct asus_oled_dev *odev) return; } - if (odev->pack_mode==PACK_MODE_G1){ + if (odev->pack_mode == PACK_MODE_G1) { // When sending roll-mode data the display updated only first packet. // I have no idea why, but when static picture is send just before // rolling picture - everything works fine. @@ -308,7 +310,7 @@ static void send_data(struct asus_oled_dev *odev) send_packets(odev->udev, packet, odev->buf, odev->pic_mode, packet_num); } else - if (odev->pack_mode==PACK_MODE_G50){ + if (odev->pack_mode == PACK_MODE_G50) { send_packets_g50(odev->udev, packet, odev->buf); } @@ -326,7 +328,7 @@ static int append_values(struct asus_oled_dev *odev, uint8_t val, size_t count) x += odev->x_shift; y += odev->y_shift; - switch(odev->pack_mode) + switch (odev->pack_mode) { case PACK_MODE_G1: // i = (x/128)*640 + 127 - x + (y/8)*128; @@ -377,30 +379,32 @@ static ssize_t odev_set_picture(struct asus_oled_dev *odev, const char *buf, siz { size_t offs = 0, max_offs; - if (count < 1) return 0; + if (count < 1) + return 0; - if (tolower(buf[0]) == 'b'){ + if (tolower(buf[0]) == 'b') { // binary mode, set the entire memory size_t i; odev->buf_size = (odev->dev_width * ASUS_OLED_DISP_HEIGHT) / 8; - if (odev->buf) kfree(odev->buf); + if (odev->buf) + kfree(odev->buf); odev->buf = kmalloc(odev->buf_size, GFP_KERNEL); memset(odev->buf, 0xff, odev->buf_size); - for (i=1; i < count && i<=32*32; i++){ + for (i = 1; i < count && i <= 32 * 32; i++) { odev->buf[i-1] = buf[i]; odev->buf_offs = i-1; } - odev->width=odev->dev_width / 8; - odev->height=ASUS_OLED_DISP_HEIGHT; - odev->x_shift=0; - odev->y_shift=0; - odev->last_val=0; + odev->width = odev->dev_width / 8; + odev->height = ASUS_OLED_DISP_HEIGHT; + odev->x_shift = 0; + odev->y_shift = 0; + odev->last_val = 0; send_data(odev); @@ -416,7 +420,7 @@ static ssize_t odev_set_picture(struct asus_oled_dev *odev, const char *buf, siz goto error_header; } - switch(tolower(buf[1])) { + switch (tolower(buf[1])) { case ASUS_OLED_STATIC: case ASUS_OLED_ROLL: case ASUS_OLED_FLASH: @@ -432,27 +436,36 @@ static ssize_t odev_set_picture(struct asus_oled_dev *odev, const char *buf, siz if (buf[i] >= '0' && buf[i] <= '9') { w = 10*w + (buf[i] - '0'); - if (w > ASUS_OLED_MAX_WIDTH) goto error_width; + if (w > ASUS_OLED_MAX_WIDTH) + goto error_width; } - else if (tolower(buf[i]) == 'x') break; - else goto error_width; + else if (tolower(buf[i]) == 'x') + break; + else + goto error_width; } for (++i; i < count; ++i) { if (buf[i] >= '0' && buf[i] <= '9') { h = 10*h + (buf[i] - '0'); - if (h > ASUS_OLED_DISP_HEIGHT) goto error_height; + if (h > ASUS_OLED_DISP_HEIGHT) + goto error_height; } - else if (tolower(buf[i]) == '>') break; - else goto error_height; + else if (tolower(buf[i]) == '>') + break; + else + goto error_height; } - if (w < 1 || w > ASUS_OLED_MAX_WIDTH) goto error_width; + if (w < 1 || w > ASUS_OLED_MAX_WIDTH) + goto error_width; - if (h < 1 || h > ASUS_OLED_DISP_HEIGHT) goto error_height; + if (h < 1 || h > ASUS_OLED_DISP_HEIGHT) + goto error_height; - if (i >= count || buf[i] != '>') goto error_header; + if (i >= count || buf[i] != '>') + goto error_header; offs = i+1; @@ -468,7 +481,8 @@ static ssize_t odev_set_picture(struct asus_oled_dev *odev, const char *buf, siz odev->buf_size = w_mem * h_mem / 8; - if (odev->buf) kfree(odev->buf); + if (odev->buf) + kfree(odev->buf); odev->buf = kmalloc(odev->buf_size, GFP_KERNEL); if (odev->buf == NULL) { @@ -505,23 +519,30 @@ static ssize_t odev_set_picture(struct asus_oled_dev *odev, const char *buf, siz int ret; if (buf[offs] == '1' || buf[offs] == '#') { - if ( (ret = append_values(odev, 1, 1)) < 0) return ret; + ret = append_values(odev, 1, 1); + if (ret < 0) + return ret; } else if (buf[offs] == '0' || buf[offs] == ' ') { - if ( (ret = append_values(odev, 0, 1)) < 0) return ret; + ret = append_values(odev, 0, 1); + if (ret < 0) + return ret; } else if (buf[offs] == '\n') { // New line detected. Lets assume, that all characters till the end of the // line were equal to the last character in this line. if (odev->buf_offs % odev->width != 0) - if ( (ret = append_values(odev, odev->last_val, - odev->width - (odev->buf_offs % odev->width))) < 0) return ret; + ret = append_values(odev, odev->last_val, + odev->width - (odev->buf_offs % odev->width)); + if (ret < 0) + return ret; } offs++; } - if (odev->buf_offs >= max_offs) send_data(odev); + if (odev->buf_offs >= max_offs) + send_data(odev); return count; @@ -566,9 +587,9 @@ static int asus_oled_probe(struct usb_interface *interface, const struct usb_dev uint16_t dev_width = 0; oled_pack_mode_t pack_mode = PACK_MODE_LAST; const struct oled_dev_desc_str * dev_desc = oled_dev_desc_table; - const char *desc = 0; + const char *desc = NULL; - if (id == 0) { + if (!id) { // Even possible? Just to make sure... dev_err(&interface->dev, "No usb_device_id provided!\n"); return -ENODEV; @@ -586,7 +607,7 @@ static int asus_oled_probe(struct usb_interface *interface, const struct usb_dev } } - if ( !desc || dev_width < 1 || pack_mode == PACK_MODE_LAST) { + if (!desc || dev_width < 1 || pack_mode == PACK_MODE_LAST) { dev_err(&interface->dev, "Missing or incomplete device description!\n"); return -ENODEV; } @@ -611,20 +632,20 @@ static int asus_oled_probe(struct usb_interface *interface, const struct usb_dev odev->last_val = 0; odev->buf = NULL; odev->enabled = 1; - odev->dev = 0; + odev->dev = NULL; - usb_set_intfdata (interface, odev); + usb_set_intfdata(interface, odev); - if ((retval = device_create_file(&interface->dev, &ASUS_OLED_DEVICE_ATTR(enabled)))) { + retval = device_create_file(&interface->dev, &ASUS_OLED_DEVICE_ATTR(enabled)); + if (retval) goto err_files; - } - if ((retval = device_create_file(&interface->dev, &ASUS_OLED_DEVICE_ATTR(picture)))) { + retval = device_create_file(&interface->dev, &ASUS_OLED_DEVICE_ATTR(picture)); + if (retval) goto err_files; - } - odev->dev = device_create(oled_class, &interface->dev, MKDEV(0,0), - NULL,"oled_%d", ++oled_num); + odev->dev = device_create(oled_class, &interface->dev, MKDEV(0, 0), + NULL, "oled_%d", ++oled_num); if (IS_ERR(odev->dev)) { retval = PTR_ERR(odev->dev); @@ -633,13 +654,13 @@ static int asus_oled_probe(struct usb_interface *interface, const struct usb_dev dev_set_drvdata(odev->dev, odev); - if ( (retval = device_create_file(odev->dev, &dev_attr_enabled))) { + retval = device_create_file(odev->dev, &dev_attr_enabled); + if (retval) goto err_class_enabled; - } - if ( (retval = device_create_file(odev->dev, &dev_attr_picture))) { + retval = device_create_file(odev->dev, &dev_attr_picture); + if (retval) goto err_class_picture; - } dev_info(&interface->dev, "Attached Asus OLED device: %s [width %u, pack_mode %d]\n", desc, odev->dev_width, odev->pack_mode); @@ -659,7 +680,7 @@ err_files: device_remove_file(&interface->dev, &ASUS_OLED_DEVICE_ATTR(enabled)); device_remove_file(&interface->dev, &ASUS_OLED_DEVICE_ATTR(picture)); - usb_set_intfdata (interface, NULL); + usb_set_intfdata(interface, NULL); usb_put_dev(odev->udev); kfree(odev); @@ -670,19 +691,20 @@ static void asus_oled_disconnect(struct usb_interface *interface) { struct asus_oled_dev *odev; - odev = usb_get_intfdata (interface); - usb_set_intfdata (interface, NULL); + odev = usb_get_intfdata(interface); + usb_set_intfdata(interface, NULL); device_remove_file(odev->dev, &dev_attr_picture); device_remove_file(odev->dev, &dev_attr_enabled); device_unregister(odev->dev); - device_remove_file(&interface->dev, & ASUS_OLED_DEVICE_ATTR(picture)); - device_remove_file(&interface->dev, & ASUS_OLED_DEVICE_ATTR(enabled)); + device_remove_file(&interface->dev, &ASUS_OLED_DEVICE_ATTR(picture)); + device_remove_file(&interface->dev, &ASUS_OLED_DEVICE_ATTR(enabled)); usb_put_dev(odev->udev); - if (odev->buf) kfree(odev->buf); + if (odev->buf) + kfree(odev->buf); kfree(odev); @@ -713,7 +735,8 @@ static int __init asus_oled_init(void) return PTR_ERR(oled_class); } - if ((retval = class_create_file(oled_class, &class_attr_version))) { + retval = class_create_file(oled_class, &class_attr_version); + if (retval) { err("Error creating class version file"); goto error; } @@ -740,6 +763,6 @@ static void __exit asus_oled_exit(void) usb_deregister(&oled_driver); } -module_init (asus_oled_init); -module_exit (asus_oled_exit); +module_init(asus_oled_init); +module_exit(asus_oled_exit); diff --git a/drivers/staging/at76_usb/TODO b/drivers/staging/at76_usb/TODO index 6911ca71a41a..0c7ed21c3b9a 100644 --- a/drivers/staging/at76_usb/TODO +++ b/drivers/staging/at76_usb/TODO @@ -1,2 +1,7 @@ -rewrite the driver to use the proper in-kernel wireless stack -instead of using its own. +Fix the mac80211 port of at76_usb (the proper in-kernel wireless +stack) and get it included to the mainline. Patches available here: + +http://git.kernel.org/?p=linux/kernel/git/linville/wireless-legacy.git;a=shortlog;h=at76 + +Contact Kalle Valo <kalle.valo@iki.fi> and linux-wireless list +<linux-wireless@vger.kernel.org> for more information. diff --git a/drivers/staging/at76_usb/at76_usb.c b/drivers/staging/at76_usb/at76_usb.c index c8e4d31c7df2..6f6e36a3bd9f 100644 --- a/drivers/staging/at76_usb/at76_usb.c +++ b/drivers/staging/at76_usb/at76_usb.c @@ -36,7 +36,7 @@ #include <net/ieee80211_radiotap.h> #include <linux/firmware.h> #include <linux/leds.h> -#include <net/ieee80211.h> +#include <linux/ieee80211.h> #include "at76_usb.h" @@ -1727,12 +1727,12 @@ static int at76_assoc_req(struct at76_priv *priv, struct bss_info *bss) /* write TLV data elements */ - ie->id = MFIE_TYPE_SSID; + ie->id = WLAN_EID_SSID; ie->len = bss->ssid_len; memcpy(ie->data, bss->ssid, bss->ssid_len); next_ie(&ie); - ie->id = MFIE_TYPE_RATES; + ie->id = WLAN_EID_SUPP_RATES; ie->len = sizeof(hw_rates); memcpy(ie->data, hw_rates, sizeof(hw_rates)); next_ie(&ie); /* ie points behind the supp_rates field */ @@ -4397,7 +4397,7 @@ static void at76_rx_mgmt_beacon(struct at76_priv *priv, switch (ie->id) { - case MFIE_TYPE_SSID: + case WLAN_EID_SSID: if (have_ssid) break; @@ -4420,7 +4420,7 @@ static void at76_rx_mgmt_beacon(struct at76_priv *priv, have_ssid = 1; break; - case MFIE_TYPE_RATES: + case WLAN_EID_SUPP_RATES: if (have_rates) break; @@ -4433,7 +4433,7 @@ static void at76_rx_mgmt_beacon(struct at76_priv *priv, hex2str(ie->data, ie->len)); break; - case MFIE_TYPE_DS_SET: + case WLAN_EID_DS_PARAMS: if (have_channel) break; @@ -4443,9 +4443,9 @@ static void at76_rx_mgmt_beacon(struct at76_priv *priv, priv->netdev->name, match->channel); break; - case MFIE_TYPE_CF_SET: - case MFIE_TYPE_TIM: - case MFIE_TYPE_IBSS_SET: + case WLAN_EID_CF_PARAMS: + case WLAN_EID_TIM: + case WLAN_EID_IBSS_PARAMS: default: at76_dbg(DBG_RX_BEACON, "%s: beacon IE id %d len %d %s", priv->netdev->name, ie->id, ie->len, @@ -5370,8 +5370,7 @@ static void at76_delete_device(struct at76_priv *priv) at76_dbg(DBG_PROC_ENTRY, "%s: unlinked urbs", __func__); - if (priv->rx_skb) - kfree_skb(priv->rx_skb); + kfree_skb(priv->rx_skb); at76_free_bss_list(priv); del_timer_sync(&priv->bss_list_timer); diff --git a/drivers/staging/at76_usb/at76_usb.h b/drivers/staging/at76_usb/at76_usb.h index b20be9da1fa1..6d60c6e23a04 100644 --- a/drivers/staging/at76_usb/at76_usb.h +++ b/drivers/staging/at76_usb/at76_usb.h @@ -22,6 +22,93 @@ #ifndef _AT76_USB_H #define _AT76_USB_H +/* + * ieee80211 definitions copied from net/ieee80211.h + */ + +#define WEP_KEY_LEN 13 +#define WEP_KEYS 4 + +#define IEEE80211_DATA_LEN 2304 +/* Maximum size for the MA-UNITDATA primitive, 802.11 standard section + 6.2.1.1.2. + + The figure in section 7.1.2 suggests a body size of up to 2312 + bytes is allowed, which is a bit confusing, I suspect this + represents the 2304 bytes of real data, plus a possible 8 bytes of + WEP IV and ICV. (this interpretation suggested by Ramiro Barreiro) */ + +#define IEEE80211_1ADDR_LEN 10 +#define IEEE80211_2ADDR_LEN 16 +#define IEEE80211_3ADDR_LEN 24 +#define IEEE80211_4ADDR_LEN 30 +#define IEEE80211_FCS_LEN 4 +#define IEEE80211_HLEN (IEEE80211_4ADDR_LEN) +#define IEEE80211_FRAME_LEN (IEEE80211_DATA_LEN + IEEE80211_HLEN) + +#define MIN_FRAG_THRESHOLD 256U +#define MAX_FRAG_THRESHOLD 2346U + +struct ieee80211_info_element { + u8 id; + u8 len; + u8 data[0]; +} __attribute__ ((packed)); + +struct ieee80211_hdr_3addr { + __le16 frame_ctl; + __le16 duration_id; + u8 addr1[ETH_ALEN]; + u8 addr2[ETH_ALEN]; + u8 addr3[ETH_ALEN]; + __le16 seq_ctl; + u8 payload[0]; +} __attribute__ ((packed)); + +struct ieee80211_auth { + struct ieee80211_hdr_3addr header; + __le16 algorithm; + __le16 transaction; + __le16 status; + /* challenge */ + struct ieee80211_info_element info_element[0]; +} __attribute__ ((packed)); + +struct ieee80211_assoc_request { + struct ieee80211_hdr_3addr header; + __le16 capability; + __le16 listen_interval; + /* SSID, supported rates, RSN */ + struct ieee80211_info_element info_element[0]; +} __attribute__ ((packed)); + +struct ieee80211_probe_response { + struct ieee80211_hdr_3addr header; + __le32 time_stamp[2]; + __le16 beacon_interval; + __le16 capability; + /* SSID, supported rates, FH params, DS params, + * CF params, IBSS params, TIM (if beacon), RSN */ + struct ieee80211_info_element info_element[0]; +} __attribute__ ((packed)); + +/* Alias beacon for probe_response */ +#define ieee80211_beacon ieee80211_probe_response + +struct ieee80211_assoc_response { + struct ieee80211_hdr_3addr header; + __le16 capability; + __le16 status; + __le16 aid; + /* supported rates */ + struct ieee80211_info_element info_element[0]; +} __attribute__ ((packed)); + +struct ieee80211_disassoc { + struct ieee80211_hdr_3addr header; + __le16 reason; +} __attribute__ ((packed)); + /* Board types */ enum board_type { BOARD_503_ISL3861 = 1, diff --git a/drivers/staging/b3dfg/Kconfig b/drivers/staging/b3dfg/Kconfig new file mode 100644 index 000000000000..524231047de5 --- /dev/null +++ b/drivers/staging/b3dfg/Kconfig @@ -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. diff --git a/drivers/staging/b3dfg/Makefile b/drivers/staging/b3dfg/Makefile new file mode 100644 index 000000000000..91f439ffc174 --- /dev/null +++ b/drivers/staging/b3dfg/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_B3DFG) += b3dfg.o diff --git a/drivers/staging/b3dfg/TODO b/drivers/staging/b3dfg/TODO new file mode 100644 index 000000000000..f5a9298b9ac1 --- /dev/null +++ b/drivers/staging/b3dfg/TODO @@ -0,0 +1,4 @@ + + - queue/wait buffer presents filltime results for each frame? + - counting of dropped frames + - review endianness diff --git a/drivers/staging/b3dfg/b3dfg.c b/drivers/staging/b3dfg/b3dfg.c new file mode 100644 index 000000000000..0348072b3ab5 --- /dev/null +++ b/drivers/staging/b3dfg/b3dfg.c @@ -0,0 +1,1119 @@ + /* + * Brontes PCI frame grabber driver + * + * Copyright (C) 2008 3M Company + * Contact: Justin Bronder <jsbronder@brontes3d.com> + * Original Authors: Daniel Drake <ddrake@brontes3d.com> + * Duane Griffin <duaneg@dghda.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 + */ + +#include <linux/device.h> +#include <linux/fs.h> +#include <linux/interrupt.h> +#include <linux/spinlock.h> +#include <linux/ioctl.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/pci.h> +#include <linux/types.h> +#include <linux/cdev.h> +#include <linux/list.h> +#include <linux/poll.h> +#include <linux/wait.h> +#include <linux/mm.h> +#include <linux/version.h> +#include <linux/uaccess.h> + +static unsigned int b3dfg_nbuf = 2; + +module_param_named(buffer_count, b3dfg_nbuf, uint, 0444); + +MODULE_PARM_DESC(buffer_count, "Number of buffers (min 2, default 2)\n"); + +MODULE_AUTHOR("Daniel Drake <ddrake@brontes3d.com>"); +MODULE_DESCRIPTION("Brontes frame grabber driver"); +MODULE_LICENSE("GPL"); + +#define DRIVER_NAME "b3dfg" +#define B3DFG_MAX_DEVS 4 +#define B3DFG_FRAMES_PER_BUFFER 3 + +#define B3DFG_BAR_REGS 0 +#define B3DFG_REGS_LENGTH 0x10000 + +#define B3DFG_IOC_MAGIC 0xb3 /* dfg :-) */ +#define B3DFG_IOCGFRMSZ _IOR(B3DFG_IOC_MAGIC, 1, int) +#define B3DFG_IOCTNUMBUFS _IO(B3DFG_IOC_MAGIC, 2) +#define B3DFG_IOCTTRANS _IO(B3DFG_IOC_MAGIC, 3) +#define B3DFG_IOCTQUEUEBUF _IO(B3DFG_IOC_MAGIC, 4) +#define B3DFG_IOCTPOLLBUF _IOWR(B3DFG_IOC_MAGIC, 5, struct b3dfg_poll) +#define B3DFG_IOCTWAITBUF _IOWR(B3DFG_IOC_MAGIC, 6, struct b3dfg_wait) +#define B3DFG_IOCGWANDSTAT _IOR(B3DFG_IOC_MAGIC, 7, int) + +enum { + /* number of 4kb pages per frame */ + B3D_REG_FRM_SIZE = 0x0, + + /* bit 0: set to enable interrupts + * bit 1: set to enable cable status change interrupts */ + B3D_REG_HW_CTRL = 0x4, + + /* bit 0-1 - 1-based ID of next pending frame transfer (0 = none) + * bit 2 indicates the previous DMA transfer has completed + * bit 3 indicates wand cable status change + * bit 8:15 - counter of number of discarded triplets */ + B3D_REG_DMA_STS = 0x8, + + /* bit 0: wand status (1 = present, 0 = disconnected) */ + B3D_REG_WAND_STS = 0xc, + + /* bus address for DMA transfers. lower 2 bits must be zero because DMA + * works with 32 bit word size. */ + B3D_REG_EC220_DMA_ADDR = 0x8000, + + /* bit 20:0 - number of 32 bit words to be transferred + * bit 21:31 - reserved */ + B3D_REG_EC220_TRF_SIZE = 0x8004, + + /* bit 0 - error bit + * bit 1 - interrupt bit (set to generate interrupt at end of transfer) + * bit 2 - start bit (set to start transfer) + * bit 3 - direction (0 = DMA_TO_DEVICE, 1 = DMA_FROM_DEVICE + * bit 4:31 - reserved */ + B3D_REG_EC220_DMA_STS = 0x8008, +}; + +enum b3dfg_buffer_state { + B3DFG_BUFFER_POLLED = 0, + B3DFG_BUFFER_PENDING, + B3DFG_BUFFER_POPULATED, +}; + +struct b3dfg_buffer { + unsigned char *frame[B3DFG_FRAMES_PER_BUFFER]; + struct list_head list; + u8 state; +}; + +struct b3dfg_dev { + + /* no protection needed: all finalized at initialization time */ + struct pci_dev *pdev; + struct cdev chardev; + struct device *dev; + void __iomem *regs; + unsigned int frame_size; + + /* + * Protects buffer state, including buffer_queue, triplet_ready, + * cur_dma_frame_idx & cur_dma_frame_addr. + */ + spinlock_t buffer_lock; + struct b3dfg_buffer *buffers; + struct list_head buffer_queue; + + /* Last frame in triplet transferred (-1 if none). */ + int cur_dma_frame_idx; + + /* Current frame's address for DMA. */ + dma_addr_t cur_dma_frame_addr; + + /* + * Protects cstate_tstamp. + * Nests inside buffer_lock. + */ + spinlock_t cstate_lock; + unsigned long cstate_tstamp; + + /* + * Protects triplets_dropped. + * Nests inside buffers_lock. + */ + spinlock_t triplets_dropped_lock; + unsigned int triplets_dropped; + + wait_queue_head_t buffer_waitqueue; + + unsigned int transmission_enabled:1; + unsigned int triplet_ready:1; +}; + +static u8 b3dfg_devices[B3DFG_MAX_DEVS]; + +static struct class *b3dfg_class; +static dev_t b3dfg_devt; + +static const struct pci_device_id b3dfg_ids[] __devinitdata = { + { PCI_DEVICE(0x0b3d, 0x0001) }, + { }, +}; + +MODULE_DEVICE_TABLE(pci, b3dfg_ids); + +/***** user-visible types *****/ + +struct b3dfg_poll { + int buffer_idx; + unsigned int triplets_dropped; +}; + +struct b3dfg_wait { + int buffer_idx; + unsigned int timeout; + unsigned int triplets_dropped; +}; + +/**** register I/O ****/ + +static u32 b3dfg_read32(struct b3dfg_dev *fgdev, u16 reg) +{ + return ioread32(fgdev->regs + reg); +} + +static void b3dfg_write32(struct b3dfg_dev *fgdev, u16 reg, u32 value) +{ + iowrite32(value, fgdev->regs + reg); +} + +/**** buffer management ****/ + +/* + * Program EC220 for transfer of a specific frame. + * Called with buffer_lock held. + */ +static int setup_frame_transfer(struct b3dfg_dev *fgdev, + struct b3dfg_buffer *buf, int frame) +{ + unsigned char *frm_addr; + dma_addr_t frm_addr_dma; + unsigned int frm_size = fgdev->frame_size; + + frm_addr = buf->frame[frame]; + frm_addr_dma = pci_map_single(fgdev->pdev, frm_addr, + frm_size, PCI_DMA_FROMDEVICE); + if (pci_dma_mapping_error(fgdev->pdev, frm_addr_dma)) + return -ENOMEM; + + fgdev->cur_dma_frame_addr = frm_addr_dma; + fgdev->cur_dma_frame_idx = frame; + + b3dfg_write32(fgdev, B3D_REG_EC220_DMA_ADDR, + cpu_to_le32(frm_addr_dma)); + b3dfg_write32(fgdev, B3D_REG_EC220_TRF_SIZE, + cpu_to_le32(frm_size >> 2)); + b3dfg_write32(fgdev, B3D_REG_EC220_DMA_STS, 0xf); + + return 0; +} + +/* Caller should hold buffer lock */ +static void dequeue_all_buffers(struct b3dfg_dev *fgdev) +{ + int i; + for (i = 0; i < b3dfg_nbuf; i++) { + struct b3dfg_buffer *buf = &fgdev->buffers[i]; + buf->state = B3DFG_BUFFER_POLLED; + list_del_init(&buf->list); + } +} + +/* queue a buffer to receive data */ +static int queue_buffer(struct b3dfg_dev *fgdev, int bufidx) +{ + struct device *dev = &fgdev->pdev->dev; + struct b3dfg_buffer *buf; + unsigned long flags; + int r = 0; + + spin_lock_irqsave(&fgdev->buffer_lock, flags); + if (bufidx < 0 || bufidx >= b3dfg_nbuf) { + dev_dbg(dev, "Invalid buffer index, %d\n", bufidx); + r = -ENOENT; + goto out; + } + buf = &fgdev->buffers[bufidx]; + + if (unlikely(buf->state == B3DFG_BUFFER_PENDING)) { + dev_dbg(dev, "buffer %d is already queued\n", bufidx); + r = -EINVAL; + goto out; + } + + buf->state = B3DFG_BUFFER_PENDING; + list_add_tail(&buf->list, &fgdev->buffer_queue); + + if (fgdev->transmission_enabled && fgdev->triplet_ready) { + dev_dbg(dev, "triplet is ready, pushing immediately\n"); + fgdev->triplet_ready = 0; + r = setup_frame_transfer(fgdev, buf, 0); + if (r) + dev_err(dev, "unable to map DMA buffer\n"); + } + +out: + spin_unlock_irqrestore(&fgdev->buffer_lock, flags); + return r; +} + +/* non-blocking buffer poll. returns 1 if data is present in the buffer, + * 0 otherwise */ +static int poll_buffer(struct b3dfg_dev *fgdev, void __user *arg) +{ + struct device *dev = &fgdev->pdev->dev; + struct b3dfg_poll p; + struct b3dfg_buffer *buf; + unsigned long flags; + int r = 1; + int arg_out = 0; + + if (copy_from_user(&p, arg, sizeof(p))) + return -EFAULT; + + if (unlikely(!fgdev->transmission_enabled)) { + dev_dbg(dev, "cannot poll, transmission disabled\n"); + return -EINVAL; + } + + if (p.buffer_idx < 0 || p.buffer_idx >= b3dfg_nbuf) + return -ENOENT; + + buf = &fgdev->buffers[p.buffer_idx]; + + spin_lock_irqsave(&fgdev->buffer_lock, flags); + + if (likely(buf->state == B3DFG_BUFFER_POPULATED)) { + arg_out = 1; + buf->state = B3DFG_BUFFER_POLLED; + + /* IRQs already disabled by spin_lock_irqsave above. */ + spin_lock(&fgdev->triplets_dropped_lock); + p.triplets_dropped = fgdev->triplets_dropped; + fgdev->triplets_dropped = 0; + spin_unlock(&fgdev->triplets_dropped_lock); + } else { + r = 0; + } + + spin_unlock_irqrestore(&fgdev->buffer_lock, flags); + + if (arg_out && copy_to_user(arg, &p, sizeof(p))) + r = -EFAULT; + + return r; +} + +static unsigned long get_cstate_change(struct b3dfg_dev *fgdev) +{ + unsigned long flags, when; + + spin_lock_irqsave(&fgdev->cstate_lock, flags); + when = fgdev->cstate_tstamp; + spin_unlock_irqrestore(&fgdev->cstate_lock, flags); + return when; +} + +static int is_event_ready(struct b3dfg_dev *fgdev, struct b3dfg_buffer *buf, + unsigned long when) +{ + int result; + unsigned long flags; + + spin_lock_irqsave(&fgdev->buffer_lock, flags); + spin_lock(&fgdev->cstate_lock); + result = (!fgdev->transmission_enabled || + buf->state == B3DFG_BUFFER_POPULATED || + when != fgdev->cstate_tstamp); + spin_unlock(&fgdev->cstate_lock); + spin_unlock_irqrestore(&fgdev->buffer_lock, flags); + + return result; +} + +/* sleep until a specific buffer becomes populated */ +static int wait_buffer(struct b3dfg_dev *fgdev, void __user *arg) +{ + struct device *dev = &fgdev->pdev->dev; + struct b3dfg_wait w; + struct b3dfg_buffer *buf; + unsigned long flags, when; + int r; + + if (copy_from_user(&w, arg, sizeof(w))) + return -EFAULT; + + if (!fgdev->transmission_enabled) { + dev_dbg(dev, "cannot wait, transmission disabled\n"); + return -EINVAL; + } + + if (w.buffer_idx < 0 || w.buffer_idx >= b3dfg_nbuf) + return -ENOENT; + + buf = &fgdev->buffers[w.buffer_idx]; + + spin_lock_irqsave(&fgdev->buffer_lock, flags); + + if (buf->state == B3DFG_BUFFER_POPULATED) { + r = w.timeout; + goto out_triplets_dropped; + } + + spin_unlock_irqrestore(&fgdev->buffer_lock, flags); + + when = get_cstate_change(fgdev); + if (w.timeout > 0) { + r = wait_event_interruptible_timeout(fgdev->buffer_waitqueue, + is_event_ready(fgdev, buf, when), + (w.timeout * HZ) / 1000); + + if (unlikely(r < 0)) + goto out; + + w.timeout = r * 1000 / HZ; + } else { + r = wait_event_interruptible(fgdev->buffer_waitqueue, + is_event_ready(fgdev, buf, when)); + + if (unlikely(r)) { + r = -ERESTARTSYS; + goto out; + } + } + + /* TODO: Inform the user via field(s) in w? */ + if (!fgdev->transmission_enabled || when != get_cstate_change(fgdev)) { + r = -EINVAL; + goto out; + } + + spin_lock_irqsave(&fgdev->buffer_lock, flags); + + if (buf->state != B3DFG_BUFFER_POPULATED) { + r = -ETIMEDOUT; + goto out_unlock; + } + + buf->state = B3DFG_BUFFER_POLLED; + +out_triplets_dropped: + + /* IRQs already disabled by spin_lock_irqsave above. */ + spin_lock(&fgdev->triplets_dropped_lock); + w.triplets_dropped = fgdev->triplets_dropped; + fgdev->triplets_dropped = 0; + spin_unlock(&fgdev->triplets_dropped_lock); + +out_unlock: + spin_unlock_irqrestore(&fgdev->buffer_lock, flags); + if (copy_to_user(arg, &w, sizeof(w))) + r = -EFAULT; +out: + return r; +} + +/* mmap page fault handler */ +static int b3dfg_vma_fault(struct vm_area_struct *vma, + struct vm_fault *vmf) +{ + struct b3dfg_dev *fgdev = vma->vm_file->private_data; + unsigned long off = vmf->pgoff << PAGE_SHIFT; + unsigned int frame_size = fgdev->frame_size; + unsigned int buf_size = frame_size * B3DFG_FRAMES_PER_BUFFER; + unsigned char *addr; + + /* determine which buffer the offset lies within */ + unsigned int buf_idx = off / buf_size; + /* and the offset into the buffer */ + unsigned int buf_off = off % buf_size; + + /* determine which frame inside the buffer the offset lies in */ + unsigned int frm_idx = buf_off / frame_size; + /* and the offset into the frame */ + unsigned int frm_off = buf_off % frame_size; + + if (unlikely(buf_idx >= b3dfg_nbuf)) + return VM_FAULT_SIGBUS; + + addr = fgdev->buffers[buf_idx].frame[frm_idx] + frm_off; + vm_insert_pfn(vma, (unsigned long)vmf->virtual_address, + virt_to_phys(addr) >> PAGE_SHIFT); + + return VM_FAULT_NOPAGE; +} + +static struct vm_operations_struct b3dfg_vm_ops = { + .fault = b3dfg_vma_fault, +}; + +static int get_wand_status(struct b3dfg_dev *fgdev, int __user *arg) +{ + u32 wndstat = b3dfg_read32(fgdev, B3D_REG_WAND_STS); + dev_dbg(&fgdev->pdev->dev, "wand status %x\n", wndstat); + return __put_user(wndstat & 0x1, arg); +} + +static int enable_transmission(struct b3dfg_dev *fgdev) +{ + u16 command; + unsigned long flags; + struct device *dev = &fgdev->pdev->dev; + + dev_dbg(dev, "enable transmission\n"); + + /* check the cable is plugged in. */ + if (!b3dfg_read32(fgdev, B3D_REG_WAND_STS)) { + dev_dbg(dev, "cannot start transmission without wand\n"); + return -EINVAL; + } + + /* + * Check we're a bus master. + * TODO: I think we can remove this having added the pci_set_master call + */ + pci_read_config_word(fgdev->pdev, PCI_COMMAND, &command); + if (!(command & PCI_COMMAND_MASTER)) { + dev_err(dev, "not a bus master, force-enabling\n"); + pci_write_config_word(fgdev->pdev, PCI_COMMAND, + command | PCI_COMMAND_MASTER); + } + + spin_lock_irqsave(&fgdev->buffer_lock, flags); + + /* Handle racing enable_transmission calls. */ + if (fgdev->transmission_enabled) { + spin_unlock_irqrestore(&fgdev->buffer_lock, flags); + goto out; + } + + spin_lock(&fgdev->triplets_dropped_lock); + fgdev->triplets_dropped = 0; + spin_unlock(&fgdev->triplets_dropped_lock); + + fgdev->triplet_ready = 0; + fgdev->cur_dma_frame_idx = -1; + fgdev->transmission_enabled = 1; + + spin_unlock_irqrestore(&fgdev->buffer_lock, flags); + + /* Enable DMA and cable status interrupts. */ + b3dfg_write32(fgdev, B3D_REG_HW_CTRL, 0x03); + +out: + return 0; +} + +static void disable_transmission(struct b3dfg_dev *fgdev) +{ + struct device *dev = &fgdev->pdev->dev; + unsigned long flags; + u32 tmp; + + dev_dbg(dev, "disable transmission\n"); + + /* guarantee that no more interrupts will be serviced */ + spin_lock_irqsave(&fgdev->buffer_lock, flags); + fgdev->transmission_enabled = 0; + + b3dfg_write32(fgdev, B3D_REG_HW_CTRL, 0); + + /* FIXME: temporary debugging only. if the board stops transmitting, + * hitting ctrl+c and seeing this message is useful for determining + * the state of the board. */ + tmp = b3dfg_read32(fgdev, B3D_REG_DMA_STS); + dev_dbg(dev, "DMA_STS reads %x after TX stopped\n", tmp); + + dequeue_all_buffers(fgdev); + spin_unlock_irqrestore(&fgdev->buffer_lock, flags); + + wake_up_interruptible(&fgdev->buffer_waitqueue); +} + +static int set_transmission(struct b3dfg_dev *fgdev, int enabled) +{ + int res = 0; + + if (enabled && !fgdev->transmission_enabled) + res = enable_transmission(fgdev); + else if (!enabled && fgdev->transmission_enabled) + disable_transmission(fgdev); + + return res; +} + +/* Called in interrupt context. */ +static void handle_cstate_unplug(struct b3dfg_dev *fgdev) +{ + /* Disable all interrupts. */ + b3dfg_write32(fgdev, B3D_REG_HW_CTRL, 0); + + /* Stop transmission. */ + spin_lock(&fgdev->buffer_lock); + fgdev->transmission_enabled = 0; + + fgdev->cur_dma_frame_idx = -1; + fgdev->triplet_ready = 0; + if (fgdev->cur_dma_frame_addr) { + pci_unmap_single(fgdev->pdev, fgdev->cur_dma_frame_addr, + fgdev->frame_size, PCI_DMA_FROMDEVICE); + fgdev->cur_dma_frame_addr = 0; + } + dequeue_all_buffers(fgdev); + spin_unlock(&fgdev->buffer_lock); +} + +/* Called in interrupt context. */ +static void handle_cstate_change(struct b3dfg_dev *fgdev) +{ + u32 cstate = b3dfg_read32(fgdev, B3D_REG_WAND_STS); + unsigned long when; + struct device *dev = &fgdev->pdev->dev; + + dev_dbg(dev, "cable state change: %u\n", cstate); + + /* + * When the wand is unplugged we reset our state. The hardware will + * have done the same internally. + * + * Note we should never see a cable *plugged* event, as interrupts + * should only be enabled when transmitting, which requires the cable + * to be plugged. If we do see one it probably means the cable has been + * unplugged and re-plugged very rapidly. Possibly because it has a + * broken wire and is momentarily losing contact. + * + * TODO: At the moment if you plug in the cable then enable transmission + * the hardware will raise a couple of spurious interrupts, so + * just ignore them for now. + * + * Once the hardware is fixed we should complain and treat it as an + * unplug. Or at least track how frequently it is happening and do + * so if too many come in. + */ + if (cstate) { + dev_warn(dev, "ignoring unexpected plug event\n"); + return; + } + handle_cstate_unplug(fgdev); + + /* + * Record cable state change timestamp & wake anyone waiting + * on a cable state change. Be paranoid about ensuring events + * are not missed if we somehow get two interrupts in a jiffy. + */ + spin_lock(&fgdev->cstate_lock); + when = jiffies_64; + if (when <= fgdev->cstate_tstamp) + when = fgdev->cstate_tstamp + 1; + fgdev->cstate_tstamp = when; + wake_up_interruptible(&fgdev->buffer_waitqueue); + spin_unlock(&fgdev->cstate_lock); +} + +/* Called with buffer_lock held. */ +static void transfer_complete(struct b3dfg_dev *fgdev) +{ + struct b3dfg_buffer *buf; + struct device *dev = &fgdev->pdev->dev; + + pci_unmap_single(fgdev->pdev, fgdev->cur_dma_frame_addr, + fgdev->frame_size, PCI_DMA_FROMDEVICE); + fgdev->cur_dma_frame_addr = 0; + + buf = list_entry(fgdev->buffer_queue.next, struct b3dfg_buffer, list); + if (buf) { + dev_dbg(dev, "handle frame completion\n"); + if (fgdev->cur_dma_frame_idx == B3DFG_FRAMES_PER_BUFFER - 1) { + + /* last frame of that triplet completed */ + dev_dbg(dev, "triplet completed\n"); + buf->state = B3DFG_BUFFER_POPULATED; + list_del_init(&buf->list); + wake_up_interruptible(&fgdev->buffer_waitqueue); + } + } else { + dev_err(dev, "got frame but no buffer!\n"); + } +} + +/* + * Called with buffer_lock held. + * + * Note that idx is the (1-based) *next* frame to be transferred, while + * cur_dma_frame_idx is the (0-based) *last* frame to have been transferred (or + * -1 if none). Thus there should be a difference of 2 between them. + */ +static bool setup_next_frame_transfer(struct b3dfg_dev *fgdev, int idx) +{ + struct b3dfg_buffer *buf; + struct device *dev = &fgdev->pdev->dev; + bool need_ack = 1; + + dev_dbg(dev, "program DMA transfer for next frame: %d\n", idx); + + buf = list_entry(fgdev->buffer_queue.next, struct b3dfg_buffer, list); + if (buf) { + if (idx == fgdev->cur_dma_frame_idx + 2) { + if (setup_frame_transfer(fgdev, buf, idx - 1)) + dev_err(dev, "unable to map DMA buffer\n"); + need_ack = 0; + } else { + dev_err(dev, "frame mismatch, got %d, expected %d\n", + idx, fgdev->cur_dma_frame_idx + 2); + + /* FIXME: handle dropped triplets here */ + } + } else { + dev_err(dev, "cannot setup DMA, no buffer\n"); + } + + return need_ack; +} + +static irqreturn_t b3dfg_intr(int irq, void *dev_id) +{ + struct b3dfg_dev *fgdev = dev_id; + struct device *dev = &fgdev->pdev->dev; + u32 sts; + u8 dropped; + bool need_ack = 1; + irqreturn_t res = IRQ_HANDLED; + + sts = b3dfg_read32(fgdev, B3D_REG_DMA_STS); + if (unlikely(sts == 0)) { + dev_warn(dev, "ignore interrupt, DMA status is 0\n"); + res = IRQ_NONE; + goto out; + } + + if (unlikely(!fgdev->transmission_enabled)) { + dev_warn(dev, "ignore interrupt, TX disabled\n"); + res = IRQ_HANDLED; + goto out; + } + + /* Handle dropped frames, as reported by the hardware. */ + dropped = (sts >> 8) & 0xff; + dev_dbg(dev, "intr: DMA_STS=%08x (drop=%d comp=%d next=%d)\n", + sts, dropped, !!(sts & 0x4), sts & 0x3); + if (unlikely(dropped > 0)) { + spin_lock(&fgdev->triplets_dropped_lock); + fgdev->triplets_dropped += dropped; + spin_unlock(&fgdev->triplets_dropped_lock); + } + + /* Handle a cable state change (i.e. the wand being unplugged). */ + if (sts & 0x08) { + handle_cstate_change(fgdev); + goto out; + } + + spin_lock(&fgdev->buffer_lock); + if (unlikely(list_empty(&fgdev->buffer_queue))) { + + /* FIXME need more sanity checking here */ + dev_info(dev, "buffer not ready for next transfer\n"); + fgdev->triplet_ready = 1; + goto out_unlock; + } + + /* Has a frame transfer been completed? */ + if (sts & 0x4) { + u32 dma_status = b3dfg_read32(fgdev, B3D_REG_EC220_DMA_STS); + + /* Check for DMA errors reported by the hardware. */ + if (unlikely(dma_status & 0x1)) { + dev_err(dev, "EC220 error: %08x\n", dma_status); + + /* FIXME flesh out error handling */ + goto out_unlock; + } + + /* Sanity check, we should have a frame index at this point. */ + if (unlikely(fgdev->cur_dma_frame_idx == -1)) { + dev_err(dev, "completed but no last idx?\n"); + + /* FIXME flesh out error handling */ + goto out_unlock; + } + + transfer_complete(fgdev); + } + + /* Is there another frame transfer pending? */ + if (sts & 0x3) + need_ack = setup_next_frame_transfer(fgdev, sts & 0x3); + else + fgdev->cur_dma_frame_idx = -1; + +out_unlock: + spin_unlock(&fgdev->buffer_lock); +out: + if (need_ack) { + dev_dbg(dev, "acknowledging interrupt\n"); + b3dfg_write32(fgdev, B3D_REG_EC220_DMA_STS, 0x0b); + } + return res; +} + +static int b3dfg_open(struct inode *inode, struct file *filp) +{ + struct b3dfg_dev *fgdev = + container_of(inode->i_cdev, struct b3dfg_dev, chardev); + + dev_dbg(&fgdev->pdev->dev, "open\n"); + filp->private_data = fgdev; + return 0; +} + +static int b3dfg_release(struct inode *inode, struct file *filp) +{ + struct b3dfg_dev *fgdev = filp->private_data; + dev_dbg(&fgdev->pdev->dev, "release\n"); + disable_transmission(fgdev); + return 0; +} + +static long b3dfg_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + struct b3dfg_dev *fgdev = filp->private_data; + + switch (cmd) { + case B3DFG_IOCGFRMSZ: + return __put_user(fgdev->frame_size, (int __user *) arg); + case B3DFG_IOCGWANDSTAT: + return get_wand_status(fgdev, (int __user *) arg); + case B3DFG_IOCTTRANS: + return set_transmission(fgdev, (int) arg); + case B3DFG_IOCTQUEUEBUF: + return queue_buffer(fgdev, (int) arg); + case B3DFG_IOCTPOLLBUF: + return poll_buffer(fgdev, (void __user *) arg); + case B3DFG_IOCTWAITBUF: + return wait_buffer(fgdev, (void __user *) arg); + default: + dev_dbg(&fgdev->pdev->dev, "unrecognised ioctl %x\n", cmd); + return -EINVAL; + } +} + +static unsigned int b3dfg_poll(struct file *filp, poll_table *poll_table) +{ + struct b3dfg_dev *fgdev = filp->private_data; + unsigned long flags, when; + int i; + int r = 0; + + when = get_cstate_change(fgdev); + poll_wait(filp, &fgdev->buffer_waitqueue, poll_table); + + spin_lock_irqsave(&fgdev->buffer_lock, flags); + for (i = 0; i < b3dfg_nbuf; i++) { + if (fgdev->buffers[i].state == B3DFG_BUFFER_POPULATED) { + r = POLLIN | POLLRDNORM; + break; + } + } + spin_unlock_irqrestore(&fgdev->buffer_lock, flags); + + /* TODO: Confirm this is how we want to communicate the change. */ + if (!fgdev->transmission_enabled || when != get_cstate_change(fgdev)) + r = POLLERR; + + return r; +} + +static int b3dfg_mmap(struct file *filp, struct vm_area_struct *vma) +{ + struct b3dfg_dev *fgdev = filp->private_data; + unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; + unsigned long vsize = vma->vm_end - vma->vm_start; + unsigned long bufdatalen = b3dfg_nbuf * fgdev->frame_size * 3; + unsigned long psize = bufdatalen - offset; + int r = 0; + + if (vsize <= psize) { + vma->vm_flags |= VM_IO | VM_RESERVED | VM_CAN_NONLINEAR | + VM_PFNMAP; + vma->vm_ops = &b3dfg_vm_ops; + } else { + r = -EINVAL; + } + + return r; +} + +static struct file_operations b3dfg_fops = { + .owner = THIS_MODULE, + .open = b3dfg_open, + .release = b3dfg_release, + .unlocked_ioctl = b3dfg_ioctl, + .poll = b3dfg_poll, + .mmap = b3dfg_mmap, +}; + +static void free_all_frame_buffers(struct b3dfg_dev *fgdev) +{ + int i, j; + for (i = 0; i < b3dfg_nbuf; i++) + for (j = 0; j < B3DFG_FRAMES_PER_BUFFER; j++) + kfree(fgdev->buffers[i].frame[j]); + kfree(fgdev->buffers); +} + +/* initialize device and any data structures. called before any interrupts + * are enabled. */ +static int b3dfg_init_dev(struct b3dfg_dev *fgdev) +{ + int i, j; + u32 frm_size = b3dfg_read32(fgdev, B3D_REG_FRM_SIZE); + + /* Disable interrupts. In abnormal circumstances (e.g. after a crash) + * the board may still be transmitting from the previous session. If we + * ensure that interrupts are disabled before we later enable them, we + * are sure to capture a triplet from the start, rather than starting + * from frame 2 or 3. Disabling interrupts causes the FG to throw away + * all buffered data and stop buffering more until interrupts are + * enabled again. + */ + b3dfg_write32(fgdev, B3D_REG_HW_CTRL, 0); + + fgdev->frame_size = frm_size * 4096; + fgdev->buffers = kzalloc(sizeof(struct b3dfg_buffer) * b3dfg_nbuf, + GFP_KERNEL); + if (!fgdev->buffers) + goto err_no_buf; + for (i = 0; i < b3dfg_nbuf; i++) { + struct b3dfg_buffer *buf = &fgdev->buffers[i]; + for (j = 0; j < B3DFG_FRAMES_PER_BUFFER; j++) { + buf->frame[j] = kmalloc(fgdev->frame_size, GFP_KERNEL); + if (!buf->frame[j]) + goto err_no_mem; + } + INIT_LIST_HEAD(&buf->list); + } + + INIT_LIST_HEAD(&fgdev->buffer_queue); + init_waitqueue_head(&fgdev->buffer_waitqueue); + spin_lock_init(&fgdev->buffer_lock); + spin_lock_init(&fgdev->cstate_lock); + spin_lock_init(&fgdev->triplets_dropped_lock); + return 0; + +err_no_mem: + free_all_frame_buffers(fgdev); +err_no_buf: + return -ENOMEM; +} + +/* find next free minor number, returns -1 if none are availabile */ +static int get_free_minor(void) +{ + int i; + for (i = 0; i < B3DFG_MAX_DEVS; i++) { + if (b3dfg_devices[i] == 0) + return i; + } + return -1; +} + +static int __devinit b3dfg_probe(struct pci_dev *pdev, + const struct pci_device_id *id) +{ + struct b3dfg_dev *fgdev = kzalloc(sizeof(*fgdev), GFP_KERNEL); + int r = 0; + int minor = get_free_minor(); + dev_t devno = MKDEV(MAJOR(b3dfg_devt), minor); + unsigned long res_len; + resource_size_t res_base; + + if (fgdev == NULL) + return -ENOMEM; + + if (minor < 0) { + dev_err(&pdev->dev, "too many devices found!\n"); + r = -EIO; + goto err_free; + } + + b3dfg_devices[minor] = 1; + dev_info(&pdev->dev, "probe device with IRQ %d\n", pdev->irq); + + cdev_init(&fgdev->chardev, &b3dfg_fops); + fgdev->chardev.owner = THIS_MODULE; + + r = cdev_add(&fgdev->chardev, devno, 1); + if (r) { + dev_err(&pdev->dev, "cannot add char device\n"); + goto err_release_minor; + } + + fgdev->dev = device_create( + b3dfg_class, + &pdev->dev, + devno, + dev_get_drvdata(&pdev->dev), + DRIVER_NAME "%d", minor); + + if (IS_ERR(fgdev->dev)) { + dev_err(&pdev->dev, "cannot create device\n"); + r = PTR_ERR(fgdev->dev); + goto err_del_cdev; + } + + r = pci_enable_device(pdev); + if (r) { + dev_err(&pdev->dev, "cannot enable PCI device\n"); + goto err_dev_unreg; + } + + res_len = pci_resource_len(pdev, B3DFG_BAR_REGS); + if (res_len != B3DFG_REGS_LENGTH) { + dev_err(&pdev->dev, "invalid register resource size\n"); + r = -EIO; + goto err_disable; + } + + if (pci_resource_flags(pdev, B3DFG_BAR_REGS) + != (IORESOURCE_MEM | IORESOURCE_SIZEALIGN)) { + dev_err(&pdev->dev, "invalid resource flags\n"); + r = -EIO; + goto err_disable; + } + r = pci_request_regions(pdev, DRIVER_NAME); + if (r) { + dev_err(&pdev->dev, "cannot obtain PCI resources\n"); + goto err_disable; + } + + pci_set_master(pdev); + + r = pci_set_dma_mask(pdev, DMA_32BIT_MASK); + if (r) { + dev_err(&pdev->dev, "no usable DMA configuration\n"); + goto err_free_res; + } + + res_base = pci_resource_start(pdev, B3DFG_BAR_REGS); + fgdev->regs = ioremap_nocache(res_base, res_len); + if (!fgdev->regs) { + dev_err(&pdev->dev, "regs ioremap failed\n"); + r = -EIO; + goto err_free_res; + } + + fgdev->pdev = pdev; + pci_set_drvdata(pdev, fgdev); + r = b3dfg_init_dev(fgdev); + if (r < 0) { + dev_err(&pdev->dev, "failed to initalize device\n"); + goto err_unmap; + } + + r = request_irq(pdev->irq, b3dfg_intr, IRQF_SHARED, DRIVER_NAME, fgdev); + if (r) { + dev_err(&pdev->dev, "couldn't request irq %d\n", pdev->irq); + goto err_free_bufs; + } + + return 0; + +err_free_bufs: + free_all_frame_buffers(fgdev); +err_unmap: + iounmap(fgdev->regs); +err_free_res: + pci_release_regions(pdev); +err_disable: + pci_disable_device(pdev); +err_dev_unreg: + device_destroy(b3dfg_class, devno); +err_del_cdev: + cdev_del(&fgdev->chardev); +err_release_minor: + b3dfg_devices[minor] = 0; +err_free: + kfree(fgdev); + return r; +} + +static void __devexit b3dfg_remove(struct pci_dev *pdev) +{ + struct b3dfg_dev *fgdev = pci_get_drvdata(pdev); + unsigned int minor = MINOR(fgdev->chardev.dev); + + dev_dbg(&pdev->dev, "remove\n"); + + free_irq(pdev->irq, fgdev); + iounmap(fgdev->regs); + pci_release_regions(pdev); + pci_disable_device(pdev); + device_destroy(b3dfg_class, MKDEV(MAJOR(b3dfg_devt), minor)); + cdev_del(&fgdev->chardev); + free_all_frame_buffers(fgdev); + kfree(fgdev); + b3dfg_devices[minor] = 0; +} + +static struct pci_driver b3dfg_driver = { + .name = DRIVER_NAME, + .id_table = b3dfg_ids, + .probe = b3dfg_probe, + .remove = __devexit_p(b3dfg_remove), +}; + +static int __init b3dfg_module_init(void) +{ + int r; + + if (b3dfg_nbuf < 2) { + printk(KERN_ERR DRIVER_NAME + ": buffer_count is out of range (must be >= 2)"); + return -EINVAL; + } + + printk(KERN_INFO DRIVER_NAME ": loaded\n"); + + b3dfg_class = class_create(THIS_MODULE, DRIVER_NAME); + if (IS_ERR(b3dfg_class)) + return PTR_ERR(b3dfg_class); + + r = alloc_chrdev_region(&b3dfg_devt, 0, B3DFG_MAX_DEVS, DRIVER_NAME); + if (r) + goto err1; + + r = pci_register_driver(&b3dfg_driver); + if (r) + goto err2; + + return r; + +err2: + unregister_chrdev_region(b3dfg_devt, B3DFG_MAX_DEVS); +err1: + class_destroy(b3dfg_class); + return r; +} + +static void __exit b3dfg_module_exit(void) +{ + printk(KERN_INFO DRIVER_NAME ": unloaded\n"); + pci_unregister_driver(&b3dfg_driver); + unregister_chrdev_region(b3dfg_devt, B3DFG_MAX_DEVS); + class_destroy(b3dfg_class); +} + +module_init(b3dfg_module_init); +module_exit(b3dfg_module_exit); diff --git a/drivers/staging/comedi/Kconfig b/drivers/staging/comedi/Kconfig index 83a93a5c6392..2d819d278b0e 100644 --- a/drivers/staging/comedi/Kconfig +++ b/drivers/staging/comedi/Kconfig @@ -6,6 +6,13 @@ config COMEDI Enable support a wide range of data acquisition devices for Linux. +config COMEDI_DEBUG + bool "Comedi debugging" + depends on COMEDI != n + help + This is an option for use by developers; most people should + say N here. This enables comedi core and driver debugging. + config COMEDI_RT tristate "Comedi Real-time support" depends on COMEDI && RT @@ -20,6 +27,13 @@ config COMEDI_PCI_DRIVERS ---help--- Enable lots of comedi PCI drivers to be built +config COMEDI_PCMCIA_DRIVERS + tristate "Comedi PCMCIA drivers" + depends on COMEDI && PCMCIAI + default N + ---help--- + Enable lots of comedi PCMCIA drivers to be built + config COMEDI_USB_DRIVERS tristate "Comedi USB drivers" depends on COMEDI && USB diff --git a/drivers/staging/comedi/comedi.h b/drivers/staging/comedi/comedi.h index 36d2e1b01e78..e6b5f16edb02 100644 --- a/drivers/staging/comedi/comedi.h +++ b/drivers/staging/comedi/comedi.h @@ -57,9 +57,6 @@ extern "C" { /* max length of device and driver names */ #define COMEDI_NAMELEN 20 - typedef unsigned int lsampl_t; - typedef unsigned short sampl_t; - /* packs and unpacks a channel/range number */ #define CR_PACK(chan, rng, aref) ((((aref)&0x3)<<24) | (((rng)&0xff)<<16) | (chan)) @@ -261,10 +258,11 @@ enum configuration_ids { INSN_CONFIG_GET_CLOCK_SRC = 2004, /* Get master clock source */ INSN_CONFIG_SET_OTHER_SRC = 2005, /* Set other source */ /* INSN_CONFIG_GET_OTHER_SRC = 2006,*/ /* Get other source */ - INSN_CONFIG_GET_HARDWARE_BUFFER_SIZE, /* Get size in bytes of - subdevice's on-board fifos - used during streaming - input/output */ + INSN_CONFIG_GET_HARDWARE_BUFFER_SIZE = 2006, /* Get size in bytes of + subdevice's on-board + fifos used during + streaming + input/output */ INSN_CONFIG_SET_COUNTER_MODE = 4097, INSN_CONFIG_8254_SET_MODE = INSN_CONFIG_SET_COUNTER_MODE, /* deprecated */ INSN_CONFIG_8254_READ_STATUS = 4098, @@ -293,45 +291,32 @@ enum comedi_support_level { /* ioctls */ #define CIO 'd' -#define COMEDI_DEVCONFIG _IOW(CIO, 0, comedi_devconfig) -#define COMEDI_DEVINFO _IOR(CIO, 1, comedi_devinfo) -#define COMEDI_SUBDINFO _IOR(CIO, 2, comedi_subdinfo) -#define COMEDI_CHANINFO _IOR(CIO, 3, comedi_chaninfo) +#define COMEDI_DEVCONFIG _IOW(CIO, 0, struct comedi_devconfig) +#define COMEDI_DEVINFO _IOR(CIO, 1, struct comedi_devinfo) +#define COMEDI_SUBDINFO _IOR(CIO, 2, struct comedi_subdinfo) +#define COMEDI_CHANINFO _IOR(CIO, 3, struct comedi_chaninfo) #define COMEDI_TRIG _IOWR(CIO, 4, comedi_trig) #define COMEDI_LOCK _IO(CIO, 5) #define COMEDI_UNLOCK _IO(CIO, 6) #define COMEDI_CANCEL _IO(CIO, 7) -#define COMEDI_RANGEINFO _IOR(CIO, 8, comedi_rangeinfo) -#define COMEDI_CMD _IOR(CIO, 9, comedi_cmd) -#define COMEDI_CMDTEST _IOR(CIO, 10, comedi_cmd) -#define COMEDI_INSNLIST _IOR(CIO, 11, comedi_insnlist) -#define COMEDI_INSN _IOR(CIO, 12, comedi_insn) -#define COMEDI_BUFCONFIG _IOR(CIO, 13, comedi_bufconfig) -#define COMEDI_BUFINFO _IOWR(CIO, 14, comedi_bufinfo) +#define COMEDI_RANGEINFO _IOR(CIO, 8, struct comedi_rangeinfo) +#define COMEDI_CMD _IOR(CIO, 9, struct comedi_cmd) +#define COMEDI_CMDTEST _IOR(CIO, 10, struct comedi_cmd) +#define COMEDI_INSNLIST _IOR(CIO, 11, struct comedi_insnlist) +#define COMEDI_INSN _IOR(CIO, 12, struct comedi_insn) +#define COMEDI_BUFCONFIG _IOR(CIO, 13, struct comedi_bufconfig) +#define COMEDI_BUFINFO _IOWR(CIO, 14, struct comedi_bufinfo) #define COMEDI_POLL _IO(CIO, 15) /* structures */ -typedef struct comedi_trig_struct comedi_trig; -typedef struct comedi_cmd_struct comedi_cmd; -typedef struct comedi_insn_struct comedi_insn; -typedef struct comedi_insnlist_struct comedi_insnlist; -typedef struct comedi_chaninfo_struct comedi_chaninfo; -typedef struct comedi_subdinfo_struct comedi_subdinfo; -typedef struct comedi_devinfo_struct comedi_devinfo; -typedef struct comedi_devconfig_struct comedi_devconfig; -typedef struct comedi_rangeinfo_struct comedi_rangeinfo; -typedef struct comedi_krange_struct comedi_krange; -typedef struct comedi_bufconfig_struct comedi_bufconfig; -typedef struct comedi_bufinfo_struct comedi_bufinfo; - -struct comedi_trig_struct { +struct comedi_trig { unsigned int subdev; /* subdevice */ unsigned int mode; /* mode */ unsigned int flags; unsigned int n_chan; /* number of channels */ unsigned int *chanlist; /* channel/range list */ - sampl_t *data; /* data list, size depends on subd flags */ + short *data; /* data list, size depends on subd flags */ unsigned int n; /* number of scans */ unsigned int trigsrc; unsigned int trigvar; @@ -340,21 +325,21 @@ struct comedi_trig_struct { unsigned int unused[3]; }; -struct comedi_insn_struct { +struct comedi_insn { unsigned int insn; unsigned int n; - lsampl_t *data; + unsigned int *data; unsigned int subdev; unsigned int chanspec; unsigned int unused[3]; }; -struct comedi_insnlist_struct { +struct comedi_insnlist { unsigned int n_insns; - comedi_insn *insns; + struct comedi_insn *insns; }; -struct comedi_cmd_struct { +struct comedi_cmd { unsigned int subdev; unsigned int flags; @@ -376,37 +361,37 @@ struct comedi_cmd_struct { unsigned int *chanlist; /* channel/range list */ unsigned int chanlist_len; - sampl_t *data; /* data list, size depends on subd flags */ + short *data; /* data list, size depends on subd flags */ unsigned int data_len; }; -struct comedi_chaninfo_struct { +struct comedi_chaninfo { unsigned int subdev; - lsampl_t *maxdata_list; + unsigned int *maxdata_list; unsigned int *flaglist; unsigned int *rangelist; unsigned int unused[4]; }; -struct comedi_rangeinfo_struct { +struct comedi_rangeinfo { unsigned int range_type; void *range_ptr; }; -struct comedi_krange_struct { +struct comedi_krange { int min; /* fixed point, multiply by 1e-6 */ int max; /* fixed point, multiply by 1e-6 */ unsigned int flags; }; -struct comedi_subdinfo_struct { +struct comedi_subdinfo { unsigned int type; unsigned int n_chan; unsigned int subd_flags; unsigned int timer_type; unsigned int len_chanlist; - lsampl_t maxdata; + unsigned int maxdata; unsigned int flags; /* channel flags */ unsigned int range_type; /* lookup in kernel */ unsigned int settling_time_0; @@ -414,7 +399,7 @@ struct comedi_subdinfo_struct { unsigned int unused[8]; }; -struct comedi_devinfo_struct { +struct comedi_devinfo { unsigned int version_code; unsigned int n_subdevs; char driver_name[COMEDI_NAMELEN]; @@ -424,12 +409,12 @@ struct comedi_devinfo_struct { int unused[30]; }; -struct comedi_devconfig_struct { +struct comedi_devconfig { char board_name[COMEDI_NAMELEN]; int options[COMEDI_NDEVCONFOPTS]; }; -struct comedi_bufconfig_struct { +struct comedi_bufconfig { unsigned int subdevice; unsigned int flags; @@ -439,7 +424,7 @@ struct comedi_bufconfig_struct { unsigned int unused[4]; }; -struct comedi_bufinfo_struct { +struct comedi_bufinfo { unsigned int subdevice; unsigned int bytes_read; diff --git a/drivers/staging/comedi/comedi_compat32.c b/drivers/staging/comedi/comedi_compat32.c index 7d0116bcb9ff..1b9c2a7c824f 100644 --- a/drivers/staging/comedi/comedi_compat32.c +++ b/drivers/staging/comedi/comedi_compat32.c @@ -37,31 +37,31 @@ #include <linux/ioctl32.h> /* for (un)register_ioctl32_conversion */ #endif -#define COMEDI32_CHANINFO _IOR(CIO,3,comedi32_chaninfo) -#define COMEDI32_RANGEINFO _IOR(CIO,8,comedi32_rangeinfo) +#define COMEDI32_CHANINFO _IOR(CIO, 3, struct comedi32_chaninfo_struct) +#define COMEDI32_RANGEINFO _IOR(CIO, 8, struct comedi32_rangeinfo_struct) /* N.B. COMEDI32_CMD and COMEDI_CMD ought to use _IOWR, not _IOR. * It's too late to change it now, but it only affects the command number. */ -#define COMEDI32_CMD _IOR(CIO,9,comedi32_cmd) +#define COMEDI32_CMD _IOR(CIO, 9, struct comedi32_cmd_struct) /* N.B. COMEDI32_CMDTEST and COMEDI_CMDTEST ought to use _IOWR, not _IOR. * It's too late to change it now, but it only affects the command number. */ -#define COMEDI32_CMDTEST _IOR(CIO,10,comedi32_cmd) -#define COMEDI32_INSNLIST _IOR(CIO,11,comedi32_insnlist) -#define COMEDI32_INSN _IOR(CIO,12,comedi32_insn) +#define COMEDI32_CMDTEST _IOR(CIO, 10, struct comedi32_cmd_struct) +#define COMEDI32_INSNLIST _IOR(CIO, 11, struct comedi32_insnlist_struct) +#define COMEDI32_INSN _IOR(CIO, 12, struct comedi32_insn_struct) -typedef struct comedi32_chaninfo_struct { +struct comedi32_chaninfo_struct { unsigned int subdev; - compat_uptr_t maxdata_list; /* 32-bit 'lsampl_t *' */ + compat_uptr_t maxdata_list; /* 32-bit 'unsigned int *' */ compat_uptr_t flaglist; /* 32-bit 'unsigned int *' */ compat_uptr_t rangelist; /* 32-bit 'unsigned int *' */ unsigned int unused[4]; -} comedi32_chaninfo; +}; -typedef struct comedi32_rangeinfo_struct { +struct comedi32_rangeinfo_struct { unsigned int range_type; compat_uptr_t range_ptr; /* 32-bit 'void *' */ -} comedi32_rangeinfo; +}; -typedef struct comedi32_cmd_struct { +struct comedi32_cmd_struct { unsigned int subdev; unsigned int flags; unsigned int start_src; @@ -76,37 +76,36 @@ typedef struct comedi32_cmd_struct { unsigned int stop_arg; compat_uptr_t chanlist; /* 32-bit 'unsigned int *' */ unsigned int chanlist_len; - compat_uptr_t data; /* 32-bit 'sampl_t *' */ + compat_uptr_t data; /* 32-bit 'short *' */ unsigned int data_len; -} comedi32_cmd; +}; -typedef struct comedi32_insn_struct { +struct comedi32_insn_struct { unsigned int insn; unsigned int n; - compat_uptr_t data; /* 32-bit 'lsampl_t *' */ + compat_uptr_t data; /* 32-bit 'unsigned int *' */ unsigned int subdev; unsigned int chanspec; unsigned int unused[3]; -} comedi32_insn; +}; -typedef struct comedi32_insnlist_struct { +struct comedi32_insnlist_struct { unsigned int n_insns; - compat_uptr_t insns; /* 32-bit 'comedi_insn *' */ -} comedi32_insnlist; + compat_uptr_t insns; /* 32-bit 'struct comedi_insn *' */ +}; /* Handle translated ioctl. */ static int translated_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - if (!file->f_op) { + if (!file->f_op) return -ENOTTY; - } + #ifdef HAVE_UNLOCKED_IOCTL if (file->f_op->unlocked_ioctl) { int rc = (int)(*file->f_op->unlocked_ioctl)(file, cmd, arg); - if (rc == -ENOIOCTLCMD) { + if (rc == -ENOIOCTLCMD) rc = -ENOTTY; - } return rc; } #endif @@ -124,8 +123,8 @@ static int translated_ioctl(struct file *file, unsigned int cmd, /* Handle 32-bit COMEDI_CHANINFO ioctl. */ static int compat_chaninfo(struct file *file, unsigned long arg) { - comedi_chaninfo __user *chaninfo; - comedi32_chaninfo __user *chaninfo32; + struct comedi_chaninfo __user *chaninfo; + struct comedi32_chaninfo_struct __user *chaninfo32; int err; union { unsigned int uint; @@ -150,9 +149,8 @@ static int compat_chaninfo(struct file *file, unsigned long arg) err |= __put_user(compat_ptr(temp.uptr), &chaninfo->flaglist); err |= __get_user(temp.uptr, &chaninfo32->rangelist); err |= __put_user(compat_ptr(temp.uptr), &chaninfo->rangelist); - if (err) { + if (err) return -EFAULT; - } return translated_ioctl(file, COMEDI_CHANINFO, (unsigned long)chaninfo); } @@ -160,8 +158,8 @@ static int compat_chaninfo(struct file *file, unsigned long arg) /* Handle 32-bit COMEDI_RANGEINFO ioctl. */ static int compat_rangeinfo(struct file *file, unsigned long arg) { - comedi_rangeinfo __user *rangeinfo; - comedi32_rangeinfo __user *rangeinfo32; + struct comedi_rangeinfo __user *rangeinfo; + struct comedi32_rangeinfo_struct __user *rangeinfo32; int err; union { unsigned int uint; @@ -182,17 +180,16 @@ static int compat_rangeinfo(struct file *file, unsigned long arg) err |= __put_user(temp.uint, &rangeinfo->range_type); err |= __get_user(temp.uptr, &rangeinfo32->range_ptr); err |= __put_user(compat_ptr(temp.uptr), &rangeinfo->range_ptr); - if (err) { + if (err) return -EFAULT; - } return translated_ioctl(file, COMEDI_RANGEINFO, (unsigned long)rangeinfo); } /* Copy 32-bit cmd structure to native cmd structure. */ -static int get_compat_cmd(comedi_cmd __user *cmd, - comedi32_cmd __user *cmd32) +static int get_compat_cmd(struct comedi_cmd __user *cmd, + struct comedi32_cmd_struct __user *cmd32) { int err; union { @@ -242,7 +239,7 @@ static int get_compat_cmd(comedi_cmd __user *cmd, } /* Copy native cmd structure to 32-bit cmd structure. */ -static int put_compat_cmd(comedi32_cmd __user *cmd32, comedi_cmd __user *cmd) +static int put_compat_cmd(struct comedi32_cmd_struct __user *cmd32, struct comedi_cmd __user *cmd) { int err; unsigned int temp; @@ -292,17 +289,16 @@ static int put_compat_cmd(comedi32_cmd __user *cmd32, comedi_cmd __user *cmd) /* Handle 32-bit COMEDI_CMD ioctl. */ static int compat_cmd(struct file *file, unsigned long arg) { - comedi_cmd __user *cmd; - comedi32_cmd __user *cmd32; + struct comedi_cmd __user *cmd; + struct comedi32_cmd_struct __user *cmd32; int rc; cmd32 = compat_ptr(arg); cmd = compat_alloc_user_space(sizeof(*cmd)); rc = get_compat_cmd(cmd, cmd32); - if (rc) { + if (rc) return rc; - } return translated_ioctl(file, COMEDI_CMD, (unsigned long)cmd); } @@ -310,33 +306,31 @@ static int compat_cmd(struct file *file, unsigned long arg) /* Handle 32-bit COMEDI_CMDTEST ioctl. */ static int compat_cmdtest(struct file *file, unsigned long arg) { - comedi_cmd __user *cmd; - comedi32_cmd __user *cmd32; + struct comedi_cmd __user *cmd; + struct comedi32_cmd_struct __user *cmd32; int rc, err; cmd32 = compat_ptr(arg); cmd = compat_alloc_user_space(sizeof(*cmd)); rc = get_compat_cmd(cmd, cmd32); - if (rc) { + if (rc) return rc; - } rc = translated_ioctl(file, COMEDI_CMDTEST, (unsigned long)cmd); - if (rc < 0) { + if (rc < 0) return rc; - } err = put_compat_cmd(cmd32, cmd); - if (err) { + if (err) rc = err; - } + return rc; } /* Copy 32-bit insn structure to native insn structure. */ -static int get_compat_insn(comedi_insn __user *insn, - comedi32_insn __user *insn32) +static int get_compat_insn(struct comedi_insn __user *insn, + struct comedi32_insn_struct __user *insn32) { int err; union { @@ -347,9 +341,9 @@ static int get_compat_insn(comedi_insn __user *insn, /* Copy insn structure. Ignore the unused members. */ err = 0; if (!access_ok(VERIFY_READ, insn32, sizeof(*insn32)) - || !access_ok(VERIFY_WRITE, insn, sizeof(*insn))) { + || !access_ok(VERIFY_WRITE, insn, sizeof(*insn))) return -EFAULT; - } + err |= __get_user(temp.uint, &insn32->insn); err |= __put_user(temp.uint, &insn->insn); err |= __get_user(temp.uint, &insn32->n); @@ -367,11 +361,11 @@ static int get_compat_insn(comedi_insn __user *insn, static int compat_insnlist(struct file *file, unsigned long arg) { struct combined_insnlist { - comedi_insnlist insnlist; - comedi_insn insn[1]; + struct comedi_insnlist insnlist; + struct comedi_insn insn[1]; } __user *s; - comedi32_insnlist __user *insnlist32; - comedi32_insn __user *insn32; + struct comedi32_insnlist_struct __user *insnlist32; + struct comedi32_insn_struct __user *insn32; compat_uptr_t uptr; unsigned int n_insns, n; int err, rc; @@ -386,9 +380,8 @@ static int compat_insnlist(struct file *file, unsigned long arg) err |= __get_user(n_insns, &insnlist32->n_insns); err |= __get_user(uptr, &insnlist32->insns); insn32 = compat_ptr(uptr); - if (err) { + if (err) return -EFAULT; - } /* Allocate user memory to copy insnlist and insns into. */ s = compat_alloc_user_space(offsetof(struct combined_insnlist, @@ -400,16 +393,14 @@ static int compat_insnlist(struct file *file, unsigned long arg) } err |= __put_user(n_insns, &s->insnlist.n_insns); err |= __put_user(&s->insn[0], &s->insnlist.insns); - if (err) { + if (err) return -EFAULT; - } /* Copy insn structures. */ for (n = 0; n < n_insns; n++) { rc = get_compat_insn(&s->insn[n], &insn32[n]); - if (rc) { + if (rc) return rc; - } } return translated_ioctl(file, COMEDI_INSNLIST, @@ -419,17 +410,16 @@ static int compat_insnlist(struct file *file, unsigned long arg) /* Handle 32-bit COMEDI_INSN ioctl. */ static int compat_insn(struct file *file, unsigned long arg) { - comedi_insn __user *insn; - comedi32_insn __user *insn32; + struct comedi_insn __user *insn; + struct comedi32_insn_struct __user *insn32; int rc; insn32 = compat_ptr(arg); insn = compat_alloc_user_space(sizeof(*insn)); rc = get_compat_insn(insn, insn32); - if (rc) { + if (rc) return rc; - } return translated_ioctl(file, COMEDI_INSN, (unsigned long)insn); } @@ -512,14 +502,14 @@ static int mapped_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg, int rc; /* Make sure we are dealing with a Comedi device. */ - if (imajor(file->f_dentry->d_inode) != COMEDI_MAJOR) { + if (imajor(file->f_dentry->d_inode) != COMEDI_MAJOR) return -ENOTTY; - } + rc = raw_ioctl(file, cmd, arg); /* Do not return -ENOIOCTLCMD. */ - if (rc == -ENOIOCTLCMD) { + if (rc == -ENOIOCTLCMD) rc = -ENOTTY; - } + return rc; } diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index 018c964396df..19dce2ebfc19 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -59,33 +59,39 @@ int comedi_debug; module_param(comedi_debug, int, 0644); #endif +int comedi_autoconfig = 1; +module_param(comedi_autoconfig, bool, 0444); + +int comedi_num_legacy_minors = 0; +module_param(comedi_num_legacy_minors, int, 0444); + static DEFINE_SPINLOCK(comedi_file_info_table_lock); static struct comedi_device_file_info *comedi_file_info_table[COMEDI_NUM_MINORS]; -static int do_devconfig_ioctl(comedi_device *dev, comedi_devconfig *arg); -static int do_bufconfig_ioctl(comedi_device *dev, void *arg); -static int do_devinfo_ioctl(comedi_device *dev, comedi_devinfo *arg, +static int do_devconfig_ioctl(struct comedi_device *dev, struct comedi_devconfig *arg); +static int do_bufconfig_ioctl(struct comedi_device *dev, void *arg); +static int do_devinfo_ioctl(struct comedi_device *dev, struct comedi_devinfo *arg, struct file *file); -static int do_subdinfo_ioctl(comedi_device *dev, comedi_subdinfo *arg, +static int do_subdinfo_ioctl(struct comedi_device *dev, struct comedi_subdinfo *arg, void *file); -static int do_chaninfo_ioctl(comedi_device *dev, comedi_chaninfo *arg); -static int do_bufinfo_ioctl(comedi_device *dev, void *arg); -static int do_cmd_ioctl(comedi_device *dev, void *arg, void *file); -static int do_lock_ioctl(comedi_device *dev, unsigned int arg, void *file); -static int do_unlock_ioctl(comedi_device *dev, unsigned int arg, void *file); -static int do_cancel_ioctl(comedi_device *dev, unsigned int arg, void *file); -static int do_cmdtest_ioctl(comedi_device *dev, void *arg, void *file); -static int do_insnlist_ioctl(comedi_device *dev, void *arg, void *file); -static int do_insn_ioctl(comedi_device *dev, void *arg, void *file); -static int do_poll_ioctl(comedi_device *dev, unsigned int subd, void *file); - -extern void do_become_nonbusy(comedi_device *dev, comedi_subdevice *s); -static int do_cancel(comedi_device *dev, comedi_subdevice *s); +static int do_chaninfo_ioctl(struct comedi_device *dev, struct comedi_chaninfo *arg); +static int do_bufinfo_ioctl(struct comedi_device *dev, void *arg); +static int do_cmd_ioctl(struct comedi_device *dev, void *arg, void *file); +static int do_lock_ioctl(struct comedi_device *dev, unsigned int arg, void *file); +static int do_unlock_ioctl(struct comedi_device *dev, unsigned int arg, void *file); +static int do_cancel_ioctl(struct comedi_device *dev, unsigned int arg, void *file); +static int do_cmdtest_ioctl(struct comedi_device *dev, void *arg, void *file); +static int do_insnlist_ioctl(struct comedi_device *dev, void *arg, void *file); +static int do_insn_ioctl(struct comedi_device *dev, void *arg, void *file); +static int do_poll_ioctl(struct comedi_device *dev, unsigned int subd, void *file); + +extern void do_become_nonbusy(struct comedi_device *dev, struct comedi_subdevice *s); +static int do_cancel(struct comedi_device *dev, struct comedi_subdevice *s); static int comedi_fasync(int fd, struct file *file, int on); -static int is_device_busy(comedi_device *dev); +static int is_device_busy(struct comedi_device *dev); #ifdef HAVE_UNLOCKED_IOCTL static long comedi_unlocked_ioctl(struct file *file, unsigned int cmd, @@ -98,9 +104,13 @@ static int comedi_ioctl(struct inode *inode, struct file *file, const unsigned minor = iminor(file->f_dentry->d_inode); struct comedi_device_file_info *dev_file_info = comedi_get_device_file_info(minor); - comedi_device *dev = dev_file_info->device; + struct comedi_device *dev; int rc; + if (dev_file_info == NULL || dev_file_info->device == NULL) + return -ENODEV; + dev = dev_file_info->device; + mutex_lock(&dev->mutex); /* Device config is special, because it must work on @@ -182,9 +192,9 @@ done: writes: none */ -static int do_devconfig_ioctl(comedi_device *dev, comedi_devconfig *arg) +static int do_devconfig_ioctl(struct comedi_device *dev, struct comedi_devconfig *arg) { - comedi_devconfig it; + struct comedi_devconfig it; int ret; unsigned char *aux_data = NULL; int aux_len; @@ -203,7 +213,7 @@ static int do_devconfig_ioctl(comedi_device *dev, comedi_devconfig *arg) return 0; } - if (copy_from_user(&it, arg, sizeof(comedi_devconfig))) + if (copy_from_user(&it, arg, sizeof(struct comedi_devconfig))) return -EFAULT; it.board_name[COMEDI_NAMELEN - 1] = 0; @@ -262,14 +272,14 @@ static int do_devconfig_ioctl(comedi_device *dev, comedi_devconfig *arg) modified bufconfig at arg */ -static int do_bufconfig_ioctl(comedi_device *dev, void *arg) +static int do_bufconfig_ioctl(struct comedi_device *dev, void *arg) { - comedi_bufconfig bc; - comedi_async *async; - comedi_subdevice *s; + struct comedi_bufconfig bc; + struct comedi_async *async; + struct comedi_subdevice *s; int ret = 0; - if (copy_from_user(&bc, arg, sizeof(comedi_bufconfig))) + if (copy_from_user(&bc, arg, sizeof(struct comedi_bufconfig))) return -EFAULT; if (bc.subdevice >= dev->n_subdevices || bc.subdevice < 0) @@ -330,7 +340,7 @@ static int do_bufconfig_ioctl(comedi_device *dev, void *arg) bc.maximum_size = async->max_bufsize; copyback: - if (copy_to_user(arg, &bc, sizeof(comedi_bufconfig))) + if (copy_to_user(arg, &bc, sizeof(struct comedi_bufconfig))) return -EFAULT; return 0; @@ -350,16 +360,16 @@ copyback: devinfo structure */ -static int do_devinfo_ioctl(comedi_device *dev, comedi_devinfo *arg, +static int do_devinfo_ioctl(struct comedi_device *dev, struct comedi_devinfo *arg, struct file *file) { - comedi_devinfo devinfo; + struct comedi_devinfo devinfo; const unsigned minor = iminor(file->f_dentry->d_inode); struct comedi_device_file_info *dev_file_info = comedi_get_device_file_info(minor); - comedi_subdevice *read_subdev = + struct comedi_subdevice *read_subdev = comedi_get_read_subdevice(dev_file_info); - comedi_subdevice *write_subdev = + struct comedi_subdevice *write_subdev = comedi_get_write_subdevice(dev_file_info); memset(&devinfo, 0, sizeof(devinfo)); @@ -380,7 +390,7 @@ static int do_devinfo_ioctl(comedi_device *dev, comedi_devinfo *arg, else devinfo.write_subdevice = -1; - if (copy_to_user(arg, &devinfo, sizeof(comedi_devinfo))) + if (copy_to_user(arg, &devinfo, sizeof(struct comedi_devinfo))) return -EFAULT; return 0; @@ -400,14 +410,14 @@ static int do_devinfo_ioctl(comedi_device *dev, comedi_devinfo *arg, array of subdevice info structures at arg */ -static int do_subdinfo_ioctl(comedi_device *dev, comedi_subdinfo *arg, +static int do_subdinfo_ioctl(struct comedi_device *dev, struct comedi_subdinfo *arg, void *file) { int ret, i; - comedi_subdinfo *tmp, *us; - comedi_subdevice *s; + struct comedi_subdinfo *tmp, *us; + struct comedi_subdevice *s; - tmp = kcalloc(dev->n_subdevices, sizeof(comedi_subdinfo), GFP_KERNEL); + tmp = kcalloc(dev->n_subdevices, sizeof(struct comedi_subdinfo), GFP_KERNEL); if (!tmp) return -ENOMEM; @@ -459,7 +469,7 @@ static int do_subdinfo_ioctl(comedi_device *dev, comedi_subdinfo *arg, } ret = copy_to_user(arg, tmp, - dev->n_subdevices * sizeof(comedi_subdinfo)); + dev->n_subdevices * sizeof(struct comedi_subdinfo)); kfree(tmp); @@ -480,12 +490,12 @@ static int do_subdinfo_ioctl(comedi_device *dev, comedi_subdinfo *arg, arrays at elements of chaninfo structure */ -static int do_chaninfo_ioctl(comedi_device *dev, comedi_chaninfo *arg) +static int do_chaninfo_ioctl(struct comedi_device *dev, struct comedi_chaninfo *arg) { - comedi_subdevice *s; - comedi_chaninfo it; + struct comedi_subdevice *s; + struct comedi_chaninfo it; - if (copy_from_user(&it, arg, sizeof(comedi_chaninfo))) + if (copy_from_user(&it, arg, sizeof(struct comedi_chaninfo))) return -EFAULT; if (it.subdev >= dev->n_subdevices) @@ -496,7 +506,7 @@ static int do_chaninfo_ioctl(comedi_device *dev, comedi_chaninfo *arg) if (s->maxdata || !s->maxdata_list) return -EINVAL; if (copy_to_user(it.maxdata_list, s->maxdata_list, - s->n_chan * sizeof(lsampl_t))) + s->n_chan * sizeof(unsigned int))) return -EFAULT; } @@ -544,13 +554,13 @@ static int do_chaninfo_ioctl(comedi_device *dev, comedi_chaninfo *arg) modified bufinfo at arg */ -static int do_bufinfo_ioctl(comedi_device *dev, void *arg) +static int do_bufinfo_ioctl(struct comedi_device *dev, void *arg) { - comedi_bufinfo bi; - comedi_subdevice *s; - comedi_async *async; + struct comedi_bufinfo bi; + struct comedi_subdevice *s; + struct comedi_async *async; - if (copy_from_user(&bi, arg, sizeof(comedi_bufinfo))) + if (copy_from_user(&bi, arg, sizeof(struct comedi_bufinfo))) return -EFAULT; if (bi.subdevice >= dev->n_subdevices || bi.subdevice < 0) @@ -591,13 +601,13 @@ static int do_bufinfo_ioctl(comedi_device *dev, void *arg) bi.buf_read_ptr = async->buf_read_ptr; copyback: - if (copy_to_user(arg, &bi, sizeof(comedi_bufinfo))) + if (copy_to_user(arg, &bi, sizeof(struct comedi_bufinfo))) return -EFAULT; return 0; } -static int parse_insn(comedi_device *dev, comedi_insn *insn, lsampl_t *data, +static int parse_insn(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data, void *file); /* * COMEDI_INSNLIST @@ -616,25 +626,25 @@ static int parse_insn(comedi_device *dev, comedi_insn *insn, lsampl_t *data, */ /* arbitrary limits */ #define MAX_SAMPLES 256 -static int do_insnlist_ioctl(comedi_device *dev, void *arg, void *file) +static int do_insnlist_ioctl(struct comedi_device *dev, void *arg, void *file) { - comedi_insnlist insnlist; - comedi_insn *insns = NULL; - lsampl_t *data = NULL; + struct comedi_insnlist insnlist; + struct comedi_insn *insns = NULL; + unsigned int *data = NULL; int i = 0; int ret = 0; - if (copy_from_user(&insnlist, arg, sizeof(comedi_insnlist))) + if (copy_from_user(&insnlist, arg, sizeof(struct comedi_insnlist))) return -EFAULT; - data = kmalloc(sizeof(lsampl_t) * MAX_SAMPLES, GFP_KERNEL); + data = kmalloc(sizeof(unsigned int) * MAX_SAMPLES, GFP_KERNEL); if (!data) { DPRINTK("kmalloc failed\n"); ret = -ENOMEM; goto error; } - insns = kmalloc(sizeof(comedi_insn) * insnlist.n_insns, GFP_KERNEL); + insns = kmalloc(sizeof(struct comedi_insn) * insnlist.n_insns, GFP_KERNEL); if (!insns) { DPRINTK("kmalloc failed\n"); ret = -ENOMEM; @@ -642,7 +652,7 @@ static int do_insnlist_ioctl(comedi_device *dev, void *arg, void *file) } if (copy_from_user(insns, insnlist.insns, - sizeof(comedi_insn) * insnlist.n_insns)) { + sizeof(struct comedi_insn) * insnlist.n_insns)) { DPRINTK("copy_from_user failed\n"); ret = -EFAULT; goto error; @@ -656,7 +666,7 @@ static int do_insnlist_ioctl(comedi_device *dev, void *arg, void *file) } if (insns[i].insn & INSN_MASK_WRITE) { if (copy_from_user(data, insns[i].data, - insns[i].n * sizeof(lsampl_t))) { + insns[i].n * sizeof(unsigned int))) { DPRINTK("copy_from_user failed\n"); ret = -EFAULT; goto error; @@ -667,7 +677,7 @@ static int do_insnlist_ioctl(comedi_device *dev, void *arg, void *file) goto error; if (insns[i].insn & INSN_MASK_READ) { if (copy_to_user(insns[i].data, data, - insns[i].n * sizeof(lsampl_t))) { + insns[i].n * sizeof(unsigned int))) { DPRINTK("copy_to_user failed\n"); ret = -EFAULT; goto error; @@ -686,7 +696,7 @@ error: return i; } -static int check_insn_config_length(comedi_insn *insn, lsampl_t *data) +static int check_insn_config_length(struct comedi_insn *insn, unsigned int *data) { if (insn->n < 1) return -EINVAL; @@ -747,10 +757,10 @@ static int check_insn_config_length(comedi_insn *insn, lsampl_t *data) return -EINVAL; } -static int parse_insn(comedi_device *dev, comedi_insn *insn, lsampl_t *data, +static int parse_insn(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data, void *file) { - comedi_subdevice *s; + struct comedi_subdevice *s; int ret = 0; int i; @@ -815,7 +825,7 @@ static int parse_insn(comedi_device *dev, comedi_insn *insn, lsampl_t *data, } } else { /* a subdevice instruction */ - lsampl_t maxdata; + unsigned int maxdata; if (insn->subdev >= dev->n_subdevices) { DPRINTK("subdevice %d out of range\n", insn->subdev); @@ -901,25 +911,25 @@ out: * pointer to insn * * reads: - * comedi_insn struct at arg + * struct comedi_insn struct at arg * data (for writes) * * writes: * data (for reads) */ -static int do_insn_ioctl(comedi_device *dev, void *arg, void *file) +static int do_insn_ioctl(struct comedi_device *dev, void *arg, void *file) { - comedi_insn insn; - lsampl_t *data = NULL; + struct comedi_insn insn; + unsigned int *data = NULL; int ret = 0; - data = kmalloc(sizeof(lsampl_t) * MAX_SAMPLES, GFP_KERNEL); + data = kmalloc(sizeof(unsigned int) * MAX_SAMPLES, GFP_KERNEL); if (!data) { ret = -ENOMEM; goto error; } - if (copy_from_user(&insn, arg, sizeof(comedi_insn))) { + if (copy_from_user(&insn, arg, sizeof(struct comedi_insn))) { ret = -EFAULT; goto error; } @@ -928,7 +938,7 @@ static int do_insn_ioctl(comedi_device *dev, void *arg, void *file) if (insn.n > MAX_SAMPLES) insn.n = MAX_SAMPLES; if (insn.insn & INSN_MASK_WRITE) { - if (copy_from_user(data, insn.data, insn.n * sizeof(lsampl_t))) { + if (copy_from_user(data, insn.data, insn.n * sizeof(unsigned int))) { ret = -EFAULT; goto error; } @@ -937,7 +947,7 @@ static int do_insn_ioctl(comedi_device *dev, void *arg, void *file) if (ret < 0) goto error; if (insn.insn & INSN_MASK_READ) { - if (copy_to_user(insn.data, data, insn.n * sizeof(lsampl_t))) { + if (copy_to_user(insn.data, data, insn.n * sizeof(unsigned int))) { ret = -EFAULT; goto error; } @@ -965,15 +975,15 @@ error: modified cmd structure at arg */ -static int do_cmd_ioctl(comedi_device *dev, void *arg, void *file) +static int do_cmd_ioctl(struct comedi_device *dev, void *arg, void *file) { - comedi_cmd user_cmd; - comedi_subdevice *s; - comedi_async *async; + struct comedi_cmd user_cmd; + struct comedi_subdevice *s; + struct comedi_async *async; int ret = 0; unsigned int *chanlist_saver = NULL; - if (copy_from_user(&user_cmd, arg, sizeof(comedi_cmd))) { + if (copy_from_user(&user_cmd, arg, sizeof(struct comedi_cmd))) { DPRINTK("bad cmd address\n"); return -EFAULT; } @@ -1062,7 +1072,7 @@ static int do_cmd_ioctl(comedi_device *dev, void *arg, void *file) /* restore chanlist pointer before copying back */ user_cmd.chanlist = chanlist_saver; user_cmd.data = NULL; - if (copy_to_user(arg, &user_cmd, sizeof(comedi_cmd))) { + if (copy_to_user(arg, &user_cmd, sizeof(struct comedi_cmd))) { DPRINTK("fault writing cmd\n"); ret = -EFAULT; goto cleanup; @@ -1119,15 +1129,15 @@ cleanup: modified cmd structure at arg */ -static int do_cmdtest_ioctl(comedi_device *dev, void *arg, void *file) +static int do_cmdtest_ioctl(struct comedi_device *dev, void *arg, void *file) { - comedi_cmd user_cmd; - comedi_subdevice *s; + struct comedi_cmd user_cmd; + struct comedi_subdevice *s; int ret = 0; unsigned int *chanlist = NULL; unsigned int *chanlist_saver = NULL; - if (copy_from_user(&user_cmd, arg, sizeof(comedi_cmd))) { + if (copy_from_user(&user_cmd, arg, sizeof(struct comedi_cmd))) { DPRINTK("bad cmd address\n"); return -EFAULT; } @@ -1191,7 +1201,7 @@ static int do_cmdtest_ioctl(comedi_device *dev, void *arg, void *file) /* restore chanlist pointer before copying back */ user_cmd.chanlist = chanlist_saver; - if (copy_to_user(arg, &user_cmd, sizeof(comedi_cmd))) { + if (copy_to_user(arg, &user_cmd, sizeof(struct comedi_cmd))) { DPRINTK("bad cmd address\n"); ret = -EFAULT; goto cleanup; @@ -1217,11 +1227,11 @@ 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; unsigned long flags; - comedi_subdevice *s; + struct comedi_subdevice *s; if (arg >= dev->n_subdevices) return -EINVAL; @@ -1261,9 +1271,9 @@ static int do_lock_ioctl(comedi_device *dev, unsigned int arg, void *file) This function isn't protected by the semaphore, since we already own the lock. */ -static int do_unlock_ioctl(comedi_device *dev, unsigned int arg, void *file) +static int do_unlock_ioctl(struct comedi_device *dev, unsigned int arg, void *file) { - comedi_subdevice *s; + struct comedi_subdevice *s; if (arg >= dev->n_subdevices) return -EINVAL; @@ -1301,9 +1311,9 @@ static int do_unlock_ioctl(comedi_device *dev, unsigned int arg, void *file) nothing */ -static int do_cancel_ioctl(comedi_device *dev, unsigned int arg, void *file) +static int do_cancel_ioctl(struct comedi_device *dev, unsigned int arg, void *file) { - comedi_subdevice *s; + struct comedi_subdevice *s; if (arg >= dev->n_subdevices) return -EINVAL; @@ -1337,9 +1347,9 @@ static int do_cancel_ioctl(comedi_device *dev, unsigned int arg, void *file) nothing */ -static int do_poll_ioctl(comedi_device *dev, unsigned int arg, void *file) +static int do_poll_ioctl(struct comedi_device *dev, unsigned int arg, void *file) { - comedi_subdevice *s; + struct comedi_subdevice *s; if (arg >= dev->n_subdevices) return -EINVAL; @@ -1360,7 +1370,7 @@ static int do_poll_ioctl(comedi_device *dev, unsigned int arg, void *file) return -EINVAL; } -static int do_cancel(comedi_device *dev, comedi_subdevice *s) +static int do_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { int ret = 0; @@ -1374,8 +1384,8 @@ static int do_cancel(comedi_device *dev, comedi_subdevice *s) void comedi_unmap(struct vm_area_struct *area) { - comedi_async *async; - comedi_device *dev; + struct comedi_async *async; + struct comedi_device *dev; async = area->vm_private_data; dev = async->subdevice->device; @@ -1394,14 +1404,14 @@ static int comedi_mmap(struct file *file, struct vm_area_struct *vma) const unsigned minor = iminor(file->f_dentry->d_inode); struct comedi_device_file_info *dev_file_info = comedi_get_device_file_info(minor); - comedi_device *dev = dev_file_info->device; - comedi_async *async = NULL; + struct comedi_device *dev = dev_file_info->device; + struct comedi_async *async = NULL; unsigned long start = vma->vm_start; unsigned long size; int n_pages; int i; int retval; - comedi_subdevice *s; + struct comedi_subdevice *s; mutex_lock(&dev->mutex); if (!dev->attached) { @@ -1470,9 +1480,9 @@ static unsigned int comedi_poll(struct file *file, poll_table *wait) const unsigned minor = iminor(file->f_dentry->d_inode); struct comedi_device_file_info *dev_file_info = comedi_get_device_file_info(minor); - comedi_device *dev = dev_file_info->device; - comedi_subdevice *read_subdev; - comedi_subdevice *write_subdev; + struct comedi_device *dev = dev_file_info->device; + struct comedi_subdevice *read_subdev; + struct comedi_subdevice *write_subdev; mutex_lock(&dev->mutex); if (!dev->attached) { @@ -1513,14 +1523,14 @@ static unsigned int comedi_poll(struct file *file, poll_table *wait) static ssize_t comedi_write(struct file *file, const char *buf, size_t nbytes, loff_t *offset) { - comedi_subdevice *s; - comedi_async *async; + struct comedi_subdevice *s; + struct comedi_async *async; int n, m, count = 0, retval = 0; DECLARE_WAITQUEUE(wait, current); const unsigned minor = iminor(file->f_dentry->d_inode); struct comedi_device_file_info *dev_file_info = comedi_get_device_file_info(minor); - comedi_device *dev = dev_file_info->device; + struct comedi_device *dev = dev_file_info->device; if (!dev->attached) { DPRINTK("no driver configured on comedi%i\n", dev->minor); @@ -1615,14 +1625,14 @@ done: static ssize_t comedi_read(struct file *file, char *buf, size_t nbytes, loff_t *offset) { - comedi_subdevice *s; - comedi_async *async; + struct comedi_subdevice *s; + struct comedi_async *async; int n, m, count = 0, retval = 0; DECLARE_WAITQUEUE(wait, current); const unsigned minor = iminor(file->f_dentry->d_inode); struct comedi_device_file_info *dev_file_info = comedi_get_device_file_info(minor); - comedi_device *dev = dev_file_info->device; + struct comedi_device *dev = dev_file_info->device; if (!dev->attached) { DPRINTK("no driver configured on comedi%i\n", dev->minor); @@ -1723,9 +1733,9 @@ done: /* This function restores a subdevice to an idle state. */ -void do_become_nonbusy(comedi_device *dev, comedi_subdevice *s) +void do_become_nonbusy(struct comedi_device *dev, struct comedi_subdevice *s) { - comedi_async *async = s->async; + struct comedi_async *async = s->async; comedi_set_subdevice_runflags(s, SRF_RUNNING, 0); #ifdef CONFIG_COMEDI_RT @@ -1747,11 +1757,11 @@ void do_become_nonbusy(comedi_device *dev, comedi_subdevice *s) static int comedi_open(struct inode *inode, struct file *file) { - char mod[32]; const unsigned minor = iminor(inode); struct comedi_device_file_info *dev_file_info = comedi_get_device_file_info(minor); - comedi_device *dev = dev_file_info->device; + struct comedi_device *dev = dev_file_info ? dev_file_info->device : NULL; + if (dev == NULL) { DPRINTK("invalid minor number\n"); return -ENODEV; @@ -1783,10 +1793,9 @@ static int comedi_open(struct inode *inode, struct file *file) dev->in_request_module = 1; - sprintf(mod, "char-major-%i-%i", COMEDI_MAJOR, dev->minor); #ifdef CONFIG_KMOD mutex_unlock(&dev->mutex); - request_module(mod); + request_module("char-major-%i-%i", COMEDI_MAJOR, dev->minor); mutex_lock(&dev->mutex); #endif @@ -1823,8 +1832,8 @@ static int comedi_close(struct inode *inode, struct file *file) const unsigned minor = iminor(inode); struct comedi_device_file_info *dev_file_info = comedi_get_device_file_info(minor); - comedi_device *dev = dev_file_info->device; - comedi_subdevice *s = NULL; + struct comedi_device *dev = dev_file_info->device; + struct comedi_subdevice *s = NULL; int i; mutex_lock(&dev->mutex); @@ -1862,7 +1871,7 @@ static int comedi_fasync(int fd, struct file *file, int on) struct comedi_device_file_info *dev_file_info = comedi_get_device_file_info(minor); - comedi_device *dev = dev_file_info->device; + struct comedi_device *dev = dev_file_info->device; return fasync_helper(fd, file, on, &dev->async_queue); } @@ -1893,7 +1902,7 @@ static void comedi_cleanup_legacy_minors(void) { unsigned i; - for (i = 0; i < COMEDI_NUM_LEGACY_MINORS; i++) + for (i = 0; i < comedi_num_legacy_minors; i++) comedi_free_board_minor(i); } @@ -1905,6 +1914,22 @@ static int __init comedi_init(void) printk(KERN_INFO "comedi: version " COMEDI_RELEASE " - http://www.comedi.org\n"); + if (comedi_num_legacy_minors < 0 || + comedi_num_legacy_minors > COMEDI_NUM_BOARD_MINORS) { + printk(KERN_ERR "comedi: error: invalid value for module " + "parameter \"comedi_num_legacy_minors\". Valid values " + "are 0 through %i.\n", COMEDI_NUM_BOARD_MINORS); + return -EINVAL; + } + + /* + * comedi is unusable if both comedi_autoconfig and + * comedi_num_legacy_minors are zero, so we might as well adjust the + * defaults in that case + */ + if (comedi_autoconfig == 0 && comedi_num_legacy_minors == 0) + comedi_num_legacy_minors = 16; + memset(comedi_file_info_table, 0, sizeof(struct comedi_device_file_info *) * COMEDI_NUM_MINORS); @@ -1933,7 +1958,7 @@ static int __init comedi_init(void) comedi_proc_init(); /* create devices files for legacy/manual use */ - for (i = 0; i < COMEDI_NUM_LEGACY_MINORS; i++) { + for (i = 0; i < comedi_num_legacy_minors; i++) { int minor; minor = comedi_alloc_board_minor(NULL); if (minor < 0) { @@ -1975,15 +2000,15 @@ static void __exit comedi_cleanup(void) module_init(comedi_init); module_exit(comedi_cleanup); -void comedi_error(const comedi_device *dev, const char *s) +void comedi_error(const struct comedi_device *dev, const char *s) { rt_printk("comedi%d: %s: %s\n", dev->minor, dev->driver->driver_name, s); } -void comedi_event(comedi_device *dev, comedi_subdevice *s) +void comedi_event(struct comedi_device *dev, struct comedi_subdevice *s) { - comedi_async *async = s->async; + struct comedi_async *async = s->async; unsigned runflags = 0; unsigned runflags_mask = 0; @@ -2042,7 +2067,7 @@ void comedi_event(comedi_device *dev, comedi_subdevice *s) s->async->events = 0; } -void comedi_set_subdevice_runflags(comedi_subdevice *s, unsigned mask, +void comedi_set_subdevice_runflags(struct comedi_subdevice *s, unsigned mask, unsigned bits) { unsigned long flags; @@ -2053,7 +2078,7 @@ void comedi_set_subdevice_runflags(comedi_subdevice *s, unsigned mask, comedi_spin_unlock_irqrestore(&s->spin_lock, flags); } -unsigned comedi_get_subdevice_runflags(comedi_subdevice *s) +unsigned comedi_get_subdevice_runflags(struct comedi_subdevice *s) { unsigned long flags; unsigned runflags; @@ -2064,9 +2089,9 @@ unsigned comedi_get_subdevice_runflags(comedi_subdevice *s) return runflags; } -static int is_device_busy(comedi_device *dev) +static int is_device_busy(struct comedi_device *dev) { - comedi_subdevice *s; + struct comedi_subdevice *s; int i; if (!dev->attached) @@ -2083,15 +2108,15 @@ static int is_device_busy(comedi_device *dev) return 0; } -void comedi_device_init(comedi_device *dev) +void comedi_device_init(struct comedi_device *dev) { - memset(dev, 0, sizeof(comedi_device)); + memset(dev, 0, sizeof(struct comedi_device)); spin_lock_init(&dev->spinlock); mutex_init(&dev->mutex); dev->minor = -1; } -void comedi_device_cleanup(comedi_device *dev) +void comedi_device_cleanup(struct comedi_device *dev) { if (dev == NULL) return; @@ -2105,13 +2130,13 @@ int comedi_alloc_board_minor(struct device *hardware_device) { unsigned long flags; struct comedi_device_file_info *info; - device_create_result_type *csdev; + struct device *csdev; unsigned i; info = kzalloc(sizeof(struct comedi_device_file_info), GFP_KERNEL); if (info == NULL) return -ENOMEM; - info->device = kzalloc(sizeof(comedi_device), GFP_KERNEL); + info->device = kzalloc(sizeof(struct comedi_device), GFP_KERNEL); if (info->device == NULL) { kfree(info); return -ENOMEM; @@ -2155,7 +2180,7 @@ void comedi_free_board_minor(unsigned minor) comedi_spin_unlock_irqrestore(&comedi_file_info_table_lock, flags); if (info) { - comedi_device *dev = info->device; + struct comedi_device *dev = info->device; if (dev) { if (dev->class_dev) { device_destroy(comedi_class, @@ -2168,11 +2193,11 @@ void comedi_free_board_minor(unsigned minor) } } -int comedi_alloc_subdevice_minor(comedi_device *dev, comedi_subdevice *s) +int comedi_alloc_subdevice_minor(struct comedi_device *dev, struct comedi_subdevice *s) { unsigned long flags; struct comedi_device_file_info *info; - device_create_result_type *csdev; + struct device *csdev; unsigned i; info = kmalloc(sizeof(struct comedi_device_file_info), GFP_KERNEL); @@ -2182,7 +2207,7 @@ int comedi_alloc_subdevice_minor(comedi_device *dev, comedi_subdevice *s) info->read_subdevice = s; info->write_subdevice = s; comedi_spin_lock_irqsave(&comedi_file_info_table_lock, flags); - for (i = COMEDI_FIRST_SUBDEVICE_MINOR; i < COMEDI_NUM_BOARD_MINORS; ++i) { + for (i = COMEDI_FIRST_SUBDEVICE_MINOR; i < COMEDI_NUM_MINORS; ++i) { if (comedi_file_info_table[i] == NULL) { comedi_file_info_table[i] = info; break; @@ -2206,7 +2231,7 @@ int comedi_alloc_subdevice_minor(comedi_device *dev, comedi_subdevice *s) return i; } -void comedi_free_subdevice_minor(comedi_subdevice *s) +void comedi_free_subdevice_minor(struct comedi_subdevice *s) { unsigned long flags; struct comedi_device_file_info *info; diff --git a/drivers/staging/comedi/comedi_fops.h b/drivers/staging/comedi/comedi_fops.h index 63f8df558e85..cb503c88c7f4 100644 --- a/drivers/staging/comedi/comedi_fops.h +++ b/drivers/staging/comedi/comedi_fops.h @@ -4,5 +4,6 @@ extern struct class *comedi_class; extern const struct file_operations comedi_fops; +extern int comedi_autoconfig; #endif /* _COMEDI_FOPS_H */ diff --git a/drivers/staging/comedi/comedi_ksyms.c b/drivers/staging/comedi/comedi_ksyms.c index 90d57282efb8..6e6fb979ef54 100644 --- a/drivers/staging/comedi/comedi_ksyms.c +++ b/drivers/staging/comedi/comedi_ksyms.c @@ -31,12 +31,12 @@ /* for drivers */ EXPORT_SYMBOL(comedi_driver_register); EXPORT_SYMBOL(comedi_driver_unregister); -//EXPORT_SYMBOL(comedi_bufcheck); -//EXPORT_SYMBOL(comedi_done); -//EXPORT_SYMBOL(comedi_error_done); +/* EXPORT_SYMBOL(comedi_bufcheck); */ +/* EXPORT_SYMBOL(comedi_done); */ +/* EXPORT_SYMBOL(comedi_error_done); */ EXPORT_SYMBOL(comedi_error); -//EXPORT_SYMBOL(comedi_eobuf); -//EXPORT_SYMBOL(comedi_eos); +/* EXPORT_SYMBOL(comedi_eobuf); */ +/* EXPORT_SYMBOL(comedi_eos); */ EXPORT_SYMBOL(comedi_event); EXPORT_SYMBOL(comedi_get_subdevice_runflags); EXPORT_SYMBOL(comedi_set_subdevice_runflags); @@ -60,6 +60,8 @@ EXPORT_SYMBOL_GPL(comedi_alloc_board_minor); EXPORT_SYMBOL_GPL(comedi_free_board_minor); EXPORT_SYMBOL_GPL(comedi_pci_auto_config); EXPORT_SYMBOL_GPL(comedi_pci_auto_unconfig); +EXPORT_SYMBOL_GPL(comedi_usb_auto_config); +EXPORT_SYMBOL_GPL(comedi_usb_auto_unconfig); /* for kcomedilib */ EXPORT_SYMBOL(check_chanlist); diff --git a/drivers/staging/comedi/comedi_rt.h b/drivers/staging/comedi/comedi_rt.h index 61852bf5adcc..169ca963312a 100644 --- a/drivers/staging/comedi/comedi_rt.h +++ b/drivers/staging/comedi/comedi_rt.h @@ -28,7 +28,6 @@ #error comedi_rt.h should only be included by comedidev.h #endif -#include <linux/version.h> #include <linux/kdev_t.h> #include <linux/slab.h> #include <linux/errno.h> @@ -59,12 +58,12 @@ int comedi_request_irq(unsigned int irq, irqreturn_t(*handler) (int, void *PT_REGS_ARG), unsigned long flags, const char *device, - comedi_device *dev_id); -void comedi_free_irq(unsigned int irq, comedi_device *dev_id); + struct comedi_device *dev_id); +void comedi_free_irq(unsigned int irq, struct comedi_device *dev_id); void comedi_rt_init(void); void comedi_rt_cleanup(void); -int comedi_switch_to_rt(comedi_device *dev); -void comedi_switch_to_non_rt(comedi_device *dev); +int comedi_switch_to_rt(struct comedi_device *dev); +void comedi_switch_to_non_rt(struct comedi_device *dev); void comedi_rt_pend_wakeup(wait_queue_head_t *q); extern int rt_pend_call(void (*func) (int arg1, void *arg2), int arg1, void *arg2); diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h index 3735355d3c58..ea319360ae68 100644 --- a/drivers/staging/comedi/comedidev.h +++ b/drivers/staging/comedi/comedidev.h @@ -26,7 +26,6 @@ #include <linux/kernel.h> #include <linux/module.h> -#include <linux/version.h> #include <linux/kdev_t.h> #include <linux/slab.h> #include <linux/errno.h> @@ -36,7 +35,6 @@ #include <linux/mm.h> #include <linux/init.h> #include <linux/vmalloc.h> -#include <linux/mm.h> #include "interrupt.h" #include <linux/dma-mapping.h> #include <linux/uaccess.h> @@ -55,9 +53,9 @@ #define COMEDI_INITCLEANUP_NOMODULE(x) \ static int __init x ## _init_module(void) \ - {return comedi_driver_register(&(x));} \ + {return comedi_driver_register(&(x)); } \ static void __exit x ## _cleanup_module(void) \ - {comedi_driver_unregister(&(x));} \ + {comedi_driver_unregister(&(x)); } \ module_init(x ## _init_module); \ module_exit(x ## _cleanup_module); \ @@ -120,23 +118,14 @@ #define PCI_VENDOR_ID_MEILHAUS 0x1402 #define COMEDI_NUM_MINORS 0x100 -#define COMEDI_NUM_LEGACY_MINORS 0x10 #define COMEDI_NUM_BOARD_MINORS 0x30 #define COMEDI_FIRST_SUBDEVICE_MINOR COMEDI_NUM_BOARD_MINORS -typedef struct comedi_device_struct comedi_device; -typedef struct comedi_subdevice_struct comedi_subdevice; -typedef struct comedi_async_struct comedi_async; -typedef struct comedi_driver_struct comedi_driver; -typedef struct comedi_lrange_struct comedi_lrange; - -typedef struct device device_create_result_type; - #define COMEDI_DEVICE_CREATE(cs, parent, devt, drvdata, device, fmt...) \ device_create(cs, ((parent) ? (parent) : (device)), devt, drvdata, fmt) -struct comedi_subdevice_struct { - comedi_device *device; +struct comedi_subdevice { + struct comedi_device *device; int type; int n_chan; volatile int subdev_flags; @@ -144,7 +133,7 @@ struct comedi_subdevice_struct { void *private; - comedi_async *async; + struct comedi_async *async; void *lock; void *busy; @@ -153,46 +142,46 @@ struct comedi_subdevice_struct { int io_bits; - lsampl_t maxdata; /* if maxdata==0, use list */ - const lsampl_t *maxdata_list; /* list is channel specific */ + unsigned int maxdata; /* if maxdata==0, use list */ + const unsigned int *maxdata_list; /* list is channel specific */ unsigned int flags; const unsigned int *flaglist; unsigned int settling_time_0; - const comedi_lrange *range_table; - const comedi_lrange *const *range_table_list; + const struct comedi_lrange *range_table; + const struct comedi_lrange *const *range_table_list; unsigned int *chanlist; /* driver-owned chanlist (not used) */ - int (*insn_read) (comedi_device *, comedi_subdevice *, comedi_insn *, - lsampl_t *); - int (*insn_write) (comedi_device *, comedi_subdevice *, comedi_insn *, - lsampl_t *); - int (*insn_bits) (comedi_device *, comedi_subdevice *, comedi_insn *, - lsampl_t *); - int (*insn_config) (comedi_device *, comedi_subdevice *, comedi_insn *, - lsampl_t *); - - int (*do_cmd) (comedi_device *, comedi_subdevice *); - int (*do_cmdtest) (comedi_device *, comedi_subdevice *, comedi_cmd *); - int (*poll) (comedi_device *, comedi_subdevice *); - int (*cancel) (comedi_device *, comedi_subdevice *); - /* int (*do_lock)(comedi_device *,comedi_subdevice *); */ - /* int (*do_unlock)(comedi_device *,comedi_subdevice *); */ + int (*insn_read) (struct comedi_device *, struct comedi_subdevice *, struct comedi_insn *, + unsigned int *); + int (*insn_write) (struct comedi_device *, struct comedi_subdevice *, struct comedi_insn *, + unsigned int *); + int (*insn_bits) (struct comedi_device *, struct comedi_subdevice *, struct comedi_insn *, + unsigned int *); + int (*insn_config) (struct comedi_device *, struct comedi_subdevice *, struct comedi_insn *, + unsigned int *); + + int (*do_cmd) (struct comedi_device *, struct comedi_subdevice *); + int (*do_cmdtest) (struct comedi_device *, struct comedi_subdevice *, struct comedi_cmd *); + int (*poll) (struct comedi_device *, struct comedi_subdevice *); + int (*cancel) (struct comedi_device *, struct comedi_subdevice *); + /* int (*do_lock)(struct comedi_device *,struct comedi_subdevice *); */ + /* int (*do_unlock)(struct comedi_device *,struct comedi_subdevice *); */ /* called when the buffer changes */ - int (*buf_change) (comedi_device *dev, comedi_subdevice *s, + int (*buf_change) (struct comedi_device *dev, struct comedi_subdevice *s, unsigned long new_size); - void (*munge) (comedi_device *dev, comedi_subdevice *s, void *data, + void (*munge) (struct comedi_device *dev, struct comedi_subdevice *s, void *data, unsigned int num_bytes, unsigned int start_chan_index); enum dma_data_direction async_dma_dir; unsigned int state; - device_create_result_type *class_dev; + struct device *class_dev; int minor; }; @@ -201,8 +190,8 @@ struct comedi_buf_page { dma_addr_t dma_addr; }; -struct comedi_async_struct { - comedi_subdevice *subdevice; +struct comedi_async { + struct comedi_subdevice *subdevice; void *prealloc_buf; /* pre-allocated buffer */ unsigned int prealloc_bufsz; /* buffer size, in bytes */ @@ -232,7 +221,7 @@ struct comedi_async_struct { unsigned int events; /* events that have occurred */ - comedi_cmd cmd; + struct comedi_cmd cmd; wait_queue_head_t wait_head; @@ -241,17 +230,17 @@ struct comedi_async_struct { int (*cb_func) (unsigned int flags, void *); void *cb_arg; - int (*inttrig) (comedi_device *dev, comedi_subdevice *s, + int (*inttrig) (struct comedi_device *dev, struct comedi_subdevice *s, unsigned int x); }; -struct comedi_driver_struct { - struct comedi_driver_struct *next; +struct comedi_driver { + struct comedi_driver *next; const char *driver_name; struct module *module; - int (*attach) (comedi_device *, comedi_devconfig *); - int (*detach) (comedi_device *); + int (*attach) (struct comedi_device *, struct comedi_devconfig *); + int (*detach) (struct comedi_device *); /* number of elements in board_name and board_id arrays */ unsigned int num_names; @@ -260,12 +249,12 @@ struct comedi_driver_struct { int offset; }; -struct comedi_device_struct { +struct comedi_device { int use_count; - comedi_driver *driver; + struct comedi_driver *driver; void *private; - device_create_result_type *class_dev; + struct device *class_dev; int minor; /* hw_dev is passed to dma_alloc_coherent when allocating async buffers * for subdevices that have async_dma_dir set to something other than @@ -281,25 +270,25 @@ struct comedi_device_struct { int in_request_module; int n_subdevices; - comedi_subdevice *subdevices; + struct comedi_subdevice *subdevices; /* dumb */ unsigned long iobase; unsigned int irq; - comedi_subdevice *read_subdev; - comedi_subdevice *write_subdev; + struct comedi_subdevice *read_subdev; + struct comedi_subdevice *write_subdev; struct fasync_struct *async_queue; - void (*open) (comedi_device *dev); - void (*close) (comedi_device *dev); + void (*open) (struct comedi_device *dev); + void (*close) (struct comedi_device *dev); }; struct comedi_device_file_info { - comedi_device *device; - comedi_subdevice *read_subdevice; - comedi_subdevice *write_subdevice; + struct comedi_device *device; + struct comedi_subdevice *read_subdevice; + struct comedi_subdevice *write_subdevice; }; #ifdef CONFIG_COMEDI_DEBUG @@ -312,8 +301,8 @@ static const int comedi_debug; * function prototypes */ -void comedi_event(comedi_device *dev, comedi_subdevice *s); -void comedi_error(const comedi_device *dev, const char *s); +void comedi_event(struct comedi_device *dev, struct comedi_subdevice *s); +void comedi_error(const struct comedi_device *dev, const char *s); /* we can expand the number of bits used to encode devices/subdevices into the minor number soon, after more distros support > 8 bit minor numbers @@ -327,7 +316,7 @@ static const unsigned COMEDI_SUBDEVICE_MINOR_OFFSET = 1; struct comedi_device_file_info *comedi_get_device_file_info(unsigned minor); -static inline comedi_subdevice *comedi_get_read_subdevice( +static inline struct comedi_subdevice *comedi_get_read_subdevice( const struct comedi_device_file_info *info) { if (info->read_subdevice) @@ -337,7 +326,7 @@ static inline comedi_subdevice *comedi_get_read_subdevice( return info->device->read_subdev; } -static inline comedi_subdevice *comedi_get_write_subdevice( +static inline struct comedi_subdevice *comedi_get_write_subdevice( const struct comedi_device_file_info *info) { if (info->write_subdevice) @@ -347,17 +336,17 @@ static inline comedi_subdevice *comedi_get_write_subdevice( return info->device->write_subdev; } -void comedi_device_detach(comedi_device *dev); -int comedi_device_attach(comedi_device *dev, comedi_devconfig *it); -int comedi_driver_register(comedi_driver *); -int comedi_driver_unregister(comedi_driver *); +void comedi_device_detach(struct comedi_device *dev); +int comedi_device_attach(struct comedi_device *dev, struct comedi_devconfig *it); +int comedi_driver_register(struct comedi_driver *); +int comedi_driver_unregister(struct comedi_driver *); void init_polling(void); void cleanup_polling(void); -void start_polling(comedi_device *); -void stop_polling(comedi_device *); +void start_polling(struct comedi_device *); +void stop_polling(struct comedi_device *); -int comedi_buf_alloc(comedi_device *dev, comedi_subdevice *s, unsigned long +int comedi_buf_alloc(struct comedi_device *dev, struct comedi_subdevice *s, unsigned long new_size); #ifdef CONFIG_PROC_FS @@ -386,13 +375,13 @@ enum subdevice_runflags { various internal comedi functions */ -int do_rangeinfo_ioctl(comedi_device *dev, comedi_rangeinfo *arg); -int check_chanlist(comedi_subdevice *s, int n, unsigned int *chanlist); -void comedi_set_subdevice_runflags(comedi_subdevice *s, unsigned mask, +int do_rangeinfo_ioctl(struct comedi_device *dev, struct comedi_rangeinfo *arg); +int check_chanlist(struct comedi_subdevice *s, int n, unsigned int *chanlist); +void comedi_set_subdevice_runflags(struct comedi_subdevice *s, unsigned mask, unsigned bits); -unsigned comedi_get_subdevice_runflags(comedi_subdevice *s); -int insn_inval(comedi_device *dev, comedi_subdevice *s, - comedi_insn *insn, lsampl_t *data); +unsigned comedi_get_subdevice_runflags(struct comedi_subdevice *s); +int insn_inval(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); /* range stuff */ @@ -403,12 +392,12 @@ int insn_inval(comedi_device *dev, comedi_subdevice *s, #define BIP_RANGE(a) {-(a)*1e6, (a)*1e6, 0} #define UNI_RANGE(a) {0, (a)*1e6, 0} -extern const comedi_lrange range_bipolar10; -extern const comedi_lrange range_bipolar5; -extern const comedi_lrange range_bipolar2_5; -extern const comedi_lrange range_unipolar10; -extern const comedi_lrange range_unipolar5; -extern const comedi_lrange range_unknown; +extern const struct comedi_lrange range_bipolar10; +extern const struct comedi_lrange range_bipolar5; +extern const struct comedi_lrange range_bipolar2_5; +extern const struct comedi_lrange range_unipolar10; +extern const struct comedi_lrange range_unipolar5; +extern const struct comedi_lrange range_unknown; #define range_digital range_unipolar5 @@ -418,21 +407,21 @@ extern const comedi_lrange range_unknown; #define GCC_ZERO_LENGTH_ARRAY 0 #endif -struct comedi_lrange_struct { +struct comedi_lrange { int length; - comedi_krange range[GCC_ZERO_LENGTH_ARRAY]; + struct comedi_krange range[GCC_ZERO_LENGTH_ARRAY]; }; /* some silly little inline functions */ -static inline int alloc_subdevices(comedi_device *dev, +static inline int alloc_subdevices(struct comedi_device *dev, unsigned int num_subdevices) { unsigned i; dev->n_subdevices = num_subdevices; dev->subdevices = - kcalloc(num_subdevices, sizeof(comedi_subdevice), GFP_KERNEL); + kcalloc(num_subdevices, sizeof(struct comedi_subdevice), GFP_KERNEL); if (!dev->subdevices) return -ENOMEM; for (i = 0; i < num_subdevices; ++i) { @@ -444,7 +433,7 @@ static inline int alloc_subdevices(comedi_device *dev, return 0; } -static inline int alloc_private(comedi_device *dev, int size) +static inline int alloc_private(struct comedi_device *dev, int size) { dev->private = kzalloc(size, GFP_KERNEL); if (!dev->private) @@ -452,17 +441,17 @@ static inline int alloc_private(comedi_device *dev, int size) return 0; } -static inline unsigned int bytes_per_sample(const comedi_subdevice *subd) +static inline unsigned int bytes_per_sample(const struct comedi_subdevice *subd) { if (subd->subdev_flags & SDF_LSAMPL) - return sizeof(lsampl_t); + return sizeof(unsigned int); else - return sizeof(sampl_t); + return sizeof(short); } /* must be used in attach to set dev->hw_dev if you wish to dma directly into comedi's buffer */ -static inline void comedi_set_hw_dev(comedi_device *dev, struct device *hw_dev) +static inline void comedi_set_hw_dev(struct comedi_device *dev, struct device *hw_dev) { if (dev->hw_dev) put_device(dev->hw_dev); @@ -474,31 +463,31 @@ static inline void comedi_set_hw_dev(comedi_device *dev, struct device *hw_dev) } } -int comedi_buf_put(comedi_async *async, sampl_t x); -int comedi_buf_get(comedi_async *async, sampl_t *x); +int comedi_buf_put(struct comedi_async *async, short x); +int comedi_buf_get(struct comedi_async *async, short *x); -unsigned int comedi_buf_write_n_available(comedi_async *async); -unsigned int comedi_buf_write_alloc(comedi_async *async, unsigned int nbytes); -unsigned int comedi_buf_write_alloc_strict(comedi_async *async, +unsigned int comedi_buf_write_n_available(struct comedi_async *async); +unsigned int comedi_buf_write_alloc(struct comedi_async *async, unsigned int nbytes); +unsigned int comedi_buf_write_alloc_strict(struct comedi_async *async, unsigned int nbytes); -unsigned comedi_buf_write_free(comedi_async *async, unsigned int nbytes); -unsigned comedi_buf_read_alloc(comedi_async *async, unsigned nbytes); -unsigned comedi_buf_read_free(comedi_async *async, unsigned int nbytes); -unsigned int comedi_buf_read_n_available(comedi_async *async); -void comedi_buf_memcpy_to(comedi_async *async, unsigned int offset, +unsigned comedi_buf_write_free(struct comedi_async *async, unsigned int nbytes); +unsigned comedi_buf_read_alloc(struct comedi_async *async, unsigned nbytes); +unsigned comedi_buf_read_free(struct comedi_async *async, unsigned int nbytes); +unsigned int comedi_buf_read_n_available(struct comedi_async *async); +void comedi_buf_memcpy_to(struct comedi_async *async, unsigned int offset, const void *source, unsigned int num_bytes); -void comedi_buf_memcpy_from(comedi_async *async, unsigned int offset, +void comedi_buf_memcpy_from(struct comedi_async *async, unsigned int offset, void *destination, unsigned int num_bytes); -static inline unsigned comedi_buf_write_n_allocated(comedi_async *async) +static inline unsigned comedi_buf_write_n_allocated(struct comedi_async *async) { return async->buf_write_alloc_count - async->buf_write_count; } -static inline unsigned comedi_buf_read_n_allocated(comedi_async *async) +static inline unsigned comedi_buf_read_n_allocated(struct comedi_async *async) { return async->buf_read_alloc_count - async->buf_read_count; } -void comedi_reset_async_buf(comedi_async *async); +void comedi_reset_async_buf(struct comedi_async *async); static inline void *comedi_aux_data(int options[], int n) { @@ -527,10 +516,13 @@ static inline void *comedi_aux_data(int options[], int n) int comedi_alloc_board_minor(struct device *hardware_device); void comedi_free_board_minor(unsigned minor); -int comedi_alloc_subdevice_minor(comedi_device *dev, comedi_subdevice *s); -void comedi_free_subdevice_minor(comedi_subdevice *s); +int comedi_alloc_subdevice_minor(struct comedi_device *dev, struct comedi_subdevice *s); +void comedi_free_subdevice_minor(struct comedi_subdevice *s); int comedi_pci_auto_config(struct pci_dev *pcidev, const char *board_name); void comedi_pci_auto_unconfig(struct pci_dev *pcidev); +struct usb_device; /* forward declaration */ +int comedi_usb_auto_config(struct usb_device *usbdev, const char *board_name); +void comedi_usb_auto_unconfig(struct usb_device *usbdev); #include "comedi_rt.h" diff --git a/drivers/staging/comedi/comedilib.h b/drivers/staging/comedi/comedilib.h index fc5fc015726b..c2729312d57e 100644 --- a/drivers/staging/comedi/comedilib.h +++ b/drivers/staging/comedi/comedilib.h @@ -36,18 +36,16 @@ #ifndef KCOMEDILIB_DEPRECATED -typedef void comedi_t; - /* these functions may not be called at real-time priority */ -comedi_t *comedi_open(const char *path); -int comedi_close(comedi_t *dev); +void *comedi_open(const char *path); +int comedi_close(void *dev); /* these functions may be called at any priority, but may fail at real-time priority */ -int comedi_lock(comedi_t *dev, unsigned int subdev); -int comedi_unlock(comedi_t *dev, unsigned int subdev); +int comedi_lock(void *dev, unsigned int subdev); +int comedi_unlock(void *dev, unsigned int subdev); /* these functions may be called at any priority, but you must hold the lock for the subdevice */ @@ -56,68 +54,68 @@ int comedi_loglevel(int loglevel); void comedi_perror(const char *s); char *comedi_strerror(int errnum); int comedi_errno(void); -int comedi_fileno(comedi_t *dev); +int comedi_fileno(void *dev); -int comedi_cancel(comedi_t *dev, unsigned int subdev); -int comedi_register_callback(comedi_t *dev, unsigned int subdev, +int comedi_cancel(void *dev, unsigned int subdev); +int comedi_register_callback(void *dev, unsigned int subdev, unsigned int mask, int (*cb) (unsigned int, void *), void *arg); -int comedi_command(comedi_t *dev, comedi_cmd *cmd); -int comedi_command_test(comedi_t *dev, comedi_cmd *cmd); -int comedi_trigger(comedi_t *dev, unsigned int subdev, comedi_trig *it); -int __comedi_trigger(comedi_t *dev, unsigned int subdev, comedi_trig *it); -int comedi_data_write(comedi_t *dev, unsigned int subdev, unsigned int chan, - unsigned int range, unsigned int aref, lsampl_t data); -int comedi_data_read(comedi_t *dev, unsigned int subdev, unsigned int chan, - unsigned int range, unsigned int aref, lsampl_t *data); -int comedi_data_read_hint(comedi_t *dev, unsigned int subdev, +int comedi_command(void *dev, struct comedi_cmd *cmd); +int comedi_command_test(void *dev, struct comedi_cmd *cmd); +int comedi_trigger(void *dev, unsigned int subdev, struct comedi_trig *it); +int __comedi_trigger(void *dev, unsigned int subdev, struct comedi_trig *it); +int comedi_data_write(void *dev, unsigned int subdev, unsigned int chan, + unsigned int range, unsigned int aref, unsigned int data); +int comedi_data_read(void *dev, unsigned int subdev, unsigned int chan, + unsigned int range, unsigned int aref, unsigned int *data); +int comedi_data_read_hint(void *dev, unsigned int subdev, unsigned int chan, unsigned int range, unsigned int aref); -int comedi_data_read_delayed(comedi_t *dev, unsigned int subdev, +int comedi_data_read_delayed(void *dev, unsigned int subdev, unsigned int chan, unsigned int range, unsigned int aref, - lsampl_t *data, unsigned int nano_sec); -int comedi_dio_config(comedi_t *dev, unsigned int subdev, unsigned int chan, + unsigned int *data, unsigned int nano_sec); +int comedi_dio_config(void *dev, unsigned int subdev, unsigned int chan, unsigned int io); -int comedi_dio_read(comedi_t *dev, unsigned int subdev, unsigned int chan, +int comedi_dio_read(void *dev, unsigned int subdev, unsigned int chan, unsigned int *val); -int comedi_dio_write(comedi_t *dev, unsigned int subdev, unsigned int chan, +int comedi_dio_write(void *dev, unsigned int subdev, unsigned int chan, unsigned int val); -int comedi_dio_bitfield(comedi_t *dev, unsigned int subdev, unsigned int mask, +int comedi_dio_bitfield(void *dev, unsigned int subdev, unsigned int mask, unsigned int *bits); -int comedi_get_n_subdevices(comedi_t *dev); -int comedi_get_version_code(comedi_t *dev); -const char *comedi_get_driver_name(comedi_t *dev); -const char *comedi_get_board_name(comedi_t *dev); -int comedi_get_subdevice_type(comedi_t *dev, unsigned int subdevice); -int comedi_find_subdevice_by_type(comedi_t *dev, int type, unsigned int subd); -int comedi_get_n_channels(comedi_t *dev, unsigned int subdevice); -lsampl_t comedi_get_maxdata(comedi_t *dev, unsigned int subdevice, unsigned +int comedi_get_n_subdevices(void *dev); +int comedi_get_version_code(void *dev); +const char *comedi_get_driver_name(void *dev); +const char *comedi_get_board_name(void *dev); +int comedi_get_subdevice_type(void *dev, unsigned int subdevice); +int comedi_find_subdevice_by_type(void *dev, int type, unsigned int subd); +int comedi_get_n_channels(void *dev, unsigned int subdevice); +unsigned int comedi_get_maxdata(void *dev, unsigned int subdevice, unsigned int chan); -int comedi_get_n_ranges(comedi_t *dev, unsigned int subdevice, unsigned int +int comedi_get_n_ranges(void *dev, unsigned int subdevice, unsigned int chan); -int comedi_do_insn(comedi_t *dev, comedi_insn *insn); -int comedi_poll(comedi_t *dev, unsigned int subdev); +int comedi_do_insn(void *dev, struct comedi_insn *insn); +int comedi_poll(void *dev, unsigned int subdev); /* DEPRECATED functions */ -int comedi_get_rangetype(comedi_t *dev, unsigned int subdevice, +int comedi_get_rangetype(void *dev, unsigned int subdevice, unsigned int chan); /* ALPHA functions */ -unsigned int comedi_get_subdevice_flags(comedi_t *dev, unsigned int subdevice); -int comedi_get_len_chanlist(comedi_t *dev, unsigned int subdevice); -int comedi_get_krange(comedi_t *dev, unsigned int subdevice, unsigned int - chan, unsigned int range, comedi_krange *krange); -unsigned int comedi_get_buf_head_pos(comedi_t *dev, unsigned int subdevice); -int comedi_set_user_int_count(comedi_t *dev, unsigned int subdevice, +unsigned int comedi_get_subdevice_flags(void *dev, unsigned int subdevice); +int comedi_get_len_chanlist(void *dev, unsigned int subdevice); +int comedi_get_krange(void *dev, unsigned int subdevice, unsigned int + chan, unsigned int range, struct comedi_krange *krange); +unsigned int comedi_get_buf_head_pos(void *dev, unsigned int subdevice); +int comedi_set_user_int_count(void *dev, unsigned int subdevice, unsigned int buf_user_count); -int comedi_map(comedi_t *dev, unsigned int subdev, void *ptr); -int comedi_unmap(comedi_t *dev, unsigned int subdev); -int comedi_get_buffer_size(comedi_t *dev, unsigned int subdev); -int comedi_mark_buffer_read(comedi_t *dev, unsigned int subdevice, +int comedi_map(void *dev, unsigned int subdev, void *ptr); +int comedi_unmap(void *dev, unsigned int subdev); +int comedi_get_buffer_size(void *dev, unsigned int subdev); +int comedi_mark_buffer_read(void *dev, unsigned int subdevice, unsigned int num_bytes); -int comedi_mark_buffer_written(comedi_t *d, unsigned int subdevice, +int comedi_mark_buffer_written(void *d, unsigned int subdevice, unsigned int num_bytes); -int comedi_get_buffer_contents(comedi_t *dev, unsigned int subdevice); -int comedi_get_buffer_offset(comedi_t *dev, unsigned int subdevice); +int comedi_get_buffer_contents(void *dev, unsigned int subdevice); +int comedi_get_buffer_offset(void *dev, unsigned int subdevice); #else @@ -139,14 +137,14 @@ int comedi_cancel(unsigned int minor, unsigned int subdev); int comedi_register_callback(unsigned int minor, unsigned int subdev, unsigned int mask, int (*cb) (unsigned int, void *), void *arg); -int comedi_command(unsigned int minor, comedi_cmd *cmd); -int comedi_command_test(unsigned int minor, comedi_cmd *cmd); -int comedi_trigger(unsigned int minor, unsigned int subdev, comedi_trig *it); -int __comedi_trigger(unsigned int minor, unsigned int subdev, comedi_trig *it); +int comedi_command(unsigned int minor, struct comedi_cmd *cmd); +int comedi_command_test(unsigned int minor, struct comedi_cmd *cmd); +int comedi_trigger(unsigned int minor, unsigned int subdev, struct comedi_trig *it); +int __comedi_trigger(unsigned int minor, unsigned int subdev, struct comedi_trig *it); int comedi_data_write(unsigned int dev, unsigned int subdev, unsigned int chan, - unsigned int range, unsigned int aref, lsampl_t data); + unsigned int range, unsigned int aref, unsigned int data); int comedi_data_read(unsigned int dev, unsigned int subdev, unsigned int chan, - unsigned int range, unsigned int aref, lsampl_t *data); + unsigned int range, unsigned int aref, unsigned int *data); int comedi_dio_config(unsigned int dev, unsigned int subdev, unsigned int chan, unsigned int io); int comedi_dio_read(unsigned int dev, unsigned int subdev, unsigned int chan, @@ -163,11 +161,11 @@ int comedi_get_subdevice_type(unsigned int minor, unsigned int subdevice); int comedi_find_subdevice_by_type(unsigned int minor, int type, unsigned int subd); int comedi_get_n_channels(unsigned int minor, unsigned int subdevice); -lsampl_t comedi_get_maxdata(unsigned int minor, unsigned int subdevice, unsigned +unsigned int comedi_get_maxdata(unsigned int minor, unsigned int subdevice, unsigned int chan); int comedi_get_n_ranges(unsigned int minor, unsigned int subdevice, unsigned int chan); -int comedi_do_insn(unsigned int minor, comedi_insn *insn); +int comedi_do_insn(unsigned int minor, struct comedi_insn *insn); int comedi_poll(unsigned int minor, unsigned int subdev); /* DEPRECATED functions */ @@ -179,7 +177,7 @@ unsigned int comedi_get_subdevice_flags(unsigned int minor, unsigned int subdevice); int comedi_get_len_chanlist(unsigned int minor, unsigned int subdevice); int comedi_get_krange(unsigned int minor, unsigned int subdevice, unsigned int - chan, unsigned int range, comedi_krange *krange); + chan, unsigned int range, struct comedi_krange *krange); unsigned int comedi_get_buf_head_pos(unsigned int minor, unsigned int subdevice); int comedi_set_user_int_count(unsigned int minor, unsigned int subdevice, diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c index 36a93b95e3f2..6e13e450dc73 100644 --- a/drivers/staging/comedi/drivers.c +++ b/drivers/staging/comedi/drivers.c @@ -28,6 +28,7 @@ #include <linux/device.h> #include <linux/module.h> #include <linux/pci.h> +#include <linux/usb.h> #include <linux/errno.h> #include <linux/kernel.h> #include <linux/sched.h> @@ -46,26 +47,26 @@ #include <asm/io.h> #include <asm/system.h> -static int postconfig(comedi_device * dev); -static int insn_rw_emulate_bits(comedi_device * dev, comedi_subdevice * s, - comedi_insn * insn, lsampl_t * data); -static void *comedi_recognize(comedi_driver * driv, const char *name); -static void comedi_report_boards(comedi_driver * driv); -static int poll_invalid(comedi_device * dev, comedi_subdevice * s); -int comedi_buf_alloc(comedi_device * dev, comedi_subdevice * s, +static int postconfig(struct comedi_device *dev); +static int insn_rw_emulate_bits(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); +static void *comedi_recognize(struct comedi_driver * driv, const char *name); +static void comedi_report_boards(struct comedi_driver *driv); +static int poll_invalid(struct comedi_device *dev, struct comedi_subdevice *s); +int comedi_buf_alloc(struct comedi_device *dev, struct comedi_subdevice *s, unsigned long new_size); -comedi_driver *comedi_drivers; +struct comedi_driver *comedi_drivers; int comedi_modprobe(int minor) { return -EINVAL; } -static void cleanup_device(comedi_device * dev) +static void cleanup_device(struct comedi_device *dev) { int i; - comedi_subdevice *s; + struct comedi_subdevice *s; if (dev->subdevices) { for (i = 0; i < dev->n_subdevices; i++) { @@ -80,10 +81,8 @@ static void cleanup_device(comedi_device * dev) dev->subdevices = NULL; dev->n_subdevices = 0; } - if (dev->private) { - kfree(dev->private); - dev->private = NULL; - } + kfree(dev->private); + dev->private = NULL; dev->driver = 0; dev->board_name = NULL; dev->board_ptr = NULL; @@ -96,7 +95,7 @@ static void cleanup_device(comedi_device * dev) comedi_set_hw_dev(dev, NULL); } -static void __comedi_device_detach(comedi_device * dev) +static void __comedi_device_detach(struct comedi_device *dev) { dev->attached = 0; if (dev->driver) { @@ -107,16 +106,16 @@ static void __comedi_device_detach(comedi_device * dev) cleanup_device(dev); } -void comedi_device_detach(comedi_device * dev) +void comedi_device_detach(struct comedi_device *dev) { if (!dev->attached) return; __comedi_device_detach(dev); } -int comedi_device_attach(comedi_device * dev, comedi_devconfig * it) +int comedi_device_attach(struct comedi_device *dev, struct comedi_devconfig *it) { - comedi_driver *driv; + struct comedi_driver *driv; int ret; if (dev->attached) @@ -139,7 +138,7 @@ int comedi_device_attach(comedi_device * dev, comedi_devconfig * it) continue; } } - //initialize dev->driver here so comedi_error() can be called from attach + /* initialize dev->driver here so comedi_error() can be called from attach */ dev->driver = driv; ret = driv->attach(dev, it); if (ret < 0) { @@ -150,8 +149,8 @@ int comedi_device_attach(comedi_device * dev, comedi_devconfig * it) goto attached; } - // recognize has failed if we get here - // report valid board names before returning error + /* recognize has failed if we get here */ + /* report valid board names before returning error */ for (driv = comedi_drivers; driv; driv = driv->next) { if (!try_module_get(driv->module)) { printk("comedi: failed to increment module count\n"); @@ -181,7 +180,7 @@ attached: return 0; } -int comedi_driver_register(comedi_driver * driver) +int comedi_driver_register(struct comedi_driver *driver) { driver->next = comedi_drivers; comedi_drivers = driver; @@ -189,15 +188,15 @@ int comedi_driver_register(comedi_driver * driver) return 0; } -int comedi_driver_unregister(comedi_driver * driver) +int comedi_driver_unregister(struct comedi_driver *driver) { - comedi_driver *prev; + struct comedi_driver *prev; int i; /* check for devices using this driver */ for (i = 0; i < COMEDI_NUM_BOARD_MINORS; i++) { struct comedi_device_file_info *dev_file_info = comedi_get_device_file_info(i); - comedi_device *dev; + struct comedi_device *dev; if(dev_file_info == NULL) continue; dev = dev_file_info->device; @@ -225,11 +224,11 @@ int comedi_driver_unregister(comedi_driver * driver) return -EINVAL; } -static int postconfig(comedi_device * dev) +static int postconfig(struct comedi_device *dev) { int i; - comedi_subdevice *s; - comedi_async *async = NULL; + struct comedi_subdevice *s; + struct comedi_async *async = NULL; int ret; for (i = 0; i < dev->n_subdevices; i++) { @@ -246,7 +245,7 @@ static int postconfig(comedi_device * dev) SDF_CMD_WRITE)) == 0); BUG_ON(!s->do_cmdtest); - async = kzalloc(sizeof(comedi_async), GFP_KERNEL); + async = kzalloc(sizeof(struct comedi_async), GFP_KERNEL); if (async == NULL) { printk("failed to allocate async struct\n"); return -ENOMEM; @@ -298,8 +297,8 @@ static int postconfig(comedi_device * dev) return 0; } -// generic recognize function for drivers that register their supported board names -void *comedi_recognize(comedi_driver * driv, const char *name) +/* generic recognize function for drivers that register their supported board names */ +void *comedi_recognize(struct comedi_driver * driv, const char *name) { unsigned i; const char *const *name_ptr = driv->board_name; @@ -314,7 +313,7 @@ void *comedi_recognize(comedi_driver * driv, const char *name) return NULL; } -void comedi_report_boards(comedi_driver * driv) +void comedi_report_boards(struct comedi_driver *driv) { unsigned int i; const char *const *name_ptr; @@ -332,28 +331,28 @@ void comedi_report_boards(comedi_driver * driv) printk(" %s\n", driv->driver_name); } -static int poll_invalid(comedi_device * dev, comedi_subdevice * s) +static int poll_invalid(struct comedi_device *dev, struct comedi_subdevice *s) { return -EINVAL; } -int insn_inval(comedi_device * dev, comedi_subdevice * s, - comedi_insn * insn, lsampl_t * data) +int insn_inval(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) { return -EINVAL; } -static int insn_rw_emulate_bits(comedi_device * dev, comedi_subdevice * s, - comedi_insn * insn, lsampl_t * data) +static int insn_rw_emulate_bits(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) { - comedi_insn new_insn; + struct comedi_insn new_insn; int ret; static const unsigned channels_per_bitfield = 32; unsigned chan = CR_CHAN(insn->chanspec); const unsigned base_bitfield_channel = (chan < channels_per_bitfield) ? 0 : chan; - lsampl_t new_data[2]; + unsigned int new_data[2]; memset(new_data, 0, sizeof(new_data)); memset(&new_insn, 0, sizeof(new_insn)); new_insn.insn = INSN_BITS; @@ -380,7 +379,7 @@ static int insn_rw_emulate_bits(comedi_device * dev, comedi_subdevice * s, return 1; } -static inline unsigned long uvirt_to_kva(pgd_t * pgd, unsigned long adr) +static inline unsigned long uvirt_to_kva(pgd_t *pgd, unsigned long adr) { unsigned long ret = 0UL; pmd_t *pmd; @@ -413,10 +412,10 @@ static inline unsigned long kvirt_to_kva(unsigned long adr) return kva; } -int comedi_buf_alloc(comedi_device * dev, comedi_subdevice * s, +int comedi_buf_alloc(struct comedi_device *dev, struct comedi_subdevice *s, unsigned long new_size) { - comedi_async *async = s->async; + struct comedi_async *async = s->async; /* Round up new_size to multiple of PAGE_SIZE */ new_size = (new_size + PAGE_SIZE - 1) & PAGE_MASK; @@ -425,7 +424,7 @@ int comedi_buf_alloc(comedi_device * dev, comedi_subdevice * s, if (async->prealloc_buf && async->prealloc_bufsz == new_size) { return 0; } - // deallocate old buffer + /* deallocate old buffer */ if (async->prealloc_buf) { vunmap(async->prealloc_buf); async->prealloc_buf = NULL; @@ -454,7 +453,7 @@ int comedi_buf_alloc(comedi_device * dev, comedi_subdevice * s, async->buf_page_list = NULL; async->n_buf_pages = 0; } - // allocate new buffer + /* allocate new buffer */ if (new_size) { unsigned i = 0; unsigned n_pages = new_size >> PAGE_SHIFT; @@ -537,16 +536,15 @@ int comedi_buf_alloc(comedi_device * dev, comedi_subdevice * s, /* munging is applied to data by core as it passes between user * and kernel space */ -unsigned int comedi_buf_munge(comedi_async * async, unsigned int num_bytes) +unsigned int comedi_buf_munge(struct comedi_async *async, unsigned int num_bytes) { - comedi_subdevice *s = async->subdevice; + struct comedi_subdevice *s = async->subdevice; unsigned int count = 0; const unsigned num_sample_bytes = bytes_per_sample(s); if (s->munge == NULL || (async->cmd.flags & CMDF_RAWDATA)) { async->munge_count += num_bytes; - if ((int)(async->munge_count - async->buf_write_count) > 0) - BUG(); + BUG_ON((int)(async->munge_count - async->buf_write_count) > 0); return num_bytes; } /* don't munge partial samples */ @@ -567,7 +565,7 @@ unsigned int comedi_buf_munge(comedi_async * async, unsigned int num_bytes) s->munge(s->device, s, async->prealloc_buf + async->munge_ptr, block_size, async->munge_chan); - smp_wmb(); //barrier insures data is munged in buffer before munge_count is incremented + smp_wmb(); /* barrier insures data is munged in buffer before munge_count is incremented */ async->munge_chan += block_size / num_sample_bytes; async->munge_chan %= async->cmd.chanlist_len; @@ -576,12 +574,11 @@ unsigned int comedi_buf_munge(comedi_async * async, unsigned int num_bytes) async->munge_ptr %= async->prealloc_bufsz; count += block_size; } - if ((int)(async->munge_count - async->buf_write_count) > 0) - BUG(); + BUG_ON((int)(async->munge_count - async->buf_write_count) > 0); return count; } -unsigned int comedi_buf_write_n_available(comedi_async * async) +unsigned int comedi_buf_write_n_available(struct comedi_async *async) { unsigned int free_end; unsigned int nbytes; @@ -601,7 +598,7 @@ unsigned int comedi_buf_write_n_available(comedi_async * async) } /* allocates chunk for the writer from free buffer space */ -unsigned int comedi_buf_write_alloc(comedi_async * async, unsigned int nbytes) +unsigned int comedi_buf_write_alloc(struct comedi_async *async, unsigned int nbytes) { unsigned int free_end = async->buf_read_count + async->prealloc_bufsz; @@ -616,7 +613,7 @@ unsigned int comedi_buf_write_alloc(comedi_async * async, unsigned int nbytes) } /* allocates nothing unless it can completely fulfill the request */ -unsigned int comedi_buf_write_alloc_strict(comedi_async * async, +unsigned int comedi_buf_write_alloc_strict(struct comedi_async *async, unsigned int nbytes) { unsigned int free_end = async->buf_read_count + async->prealloc_bufsz; @@ -632,7 +629,7 @@ unsigned int comedi_buf_write_alloc_strict(comedi_async * async, } /* transfers a chunk from writer to filled buffer space */ -unsigned comedi_buf_write_free(comedi_async * async, unsigned int nbytes) +unsigned comedi_buf_write_free(struct comedi_async *async, unsigned int nbytes) { if ((int)(async->buf_write_count + nbytes - async->buf_write_alloc_count) > 0) { @@ -650,7 +647,7 @@ unsigned comedi_buf_write_free(comedi_async * async, unsigned int nbytes) } /* allocates a chunk for the reader from filled (and munged) buffer space */ -unsigned comedi_buf_read_alloc(comedi_async * async, unsigned nbytes) +unsigned comedi_buf_read_alloc(struct comedi_async *async, unsigned nbytes) { if ((int)(async->buf_read_alloc_count + nbytes - async->munge_count) > 0) { @@ -664,9 +661,9 @@ unsigned comedi_buf_read_alloc(comedi_async * async, unsigned nbytes) } /* transfers control of a chunk from reader to free buffer space */ -unsigned comedi_buf_read_free(comedi_async * async, unsigned int nbytes) +unsigned comedi_buf_read_free(struct comedi_async *async, unsigned int nbytes) { - // barrier insures data has been read out of buffer before read count is incremented + /* barrier insures data has been read out of buffer before read count is incremented */ smp_mb(); if ((int)(async->buf_read_count + nbytes - async->buf_read_alloc_count) > 0) { @@ -680,7 +677,7 @@ unsigned comedi_buf_read_free(comedi_async * async, unsigned int nbytes) return nbytes; } -void comedi_buf_memcpy_to(comedi_async * async, unsigned int offset, +void comedi_buf_memcpy_to(struct comedi_async *async, unsigned int offset, const void *data, unsigned int num_bytes) { unsigned int write_ptr = async->buf_write_ptr + offset; @@ -705,7 +702,7 @@ void comedi_buf_memcpy_to(comedi_async * async, unsigned int offset, } } -void comedi_buf_memcpy_from(comedi_async * async, unsigned int offset, +void comedi_buf_memcpy_from(struct comedi_async *async, unsigned int offset, void *dest, unsigned int nbytes) { void *src; @@ -731,7 +728,7 @@ void comedi_buf_memcpy_from(comedi_async * async, unsigned int offset, } } -unsigned int comedi_buf_read_n_available(comedi_async * async) +unsigned int comedi_buf_read_n_available(struct comedi_async *async) { unsigned num_bytes; @@ -746,32 +743,32 @@ unsigned int comedi_buf_read_n_available(comedi_async * async) return num_bytes; } -int comedi_buf_get(comedi_async * async, sampl_t * x) +int comedi_buf_get(struct comedi_async *async, short *x) { unsigned int n = comedi_buf_read_n_available(async); - if (n < sizeof(sampl_t)) + if (n < sizeof(short)) return 0; - comedi_buf_read_alloc(async, sizeof(sampl_t)); - *x = *(sampl_t *) (async->prealloc_buf + async->buf_read_ptr); - comedi_buf_read_free(async, sizeof(sampl_t)); + comedi_buf_read_alloc(async, sizeof(short)); + *x = *(short *) (async->prealloc_buf + async->buf_read_ptr); + comedi_buf_read_free(async, sizeof(short)); return 1; } -int comedi_buf_put(comedi_async * async, sampl_t x) +int comedi_buf_put(struct comedi_async *async, short x) { - unsigned int n = comedi_buf_write_alloc_strict(async, sizeof(sampl_t)); + unsigned int n = comedi_buf_write_alloc_strict(async, sizeof(short)); - if (n < sizeof(sampl_t)) { + if (n < sizeof(short)) { async->events |= COMEDI_CB_ERROR; return 0; } - *(sampl_t *) (async->prealloc_buf + async->buf_write_ptr) = x; - comedi_buf_write_free(async, sizeof(sampl_t)); + *(short *) (async->prealloc_buf + async->buf_write_ptr) = x; + comedi_buf_write_free(async, sizeof(short)); return 1; } -void comedi_reset_async_buf(comedi_async * async) +void comedi_reset_async_buf(struct comedi_async *async) { async->buf_write_alloc_count = 0; async->buf_write_count = 0; @@ -792,14 +789,27 @@ void comedi_reset_async_buf(comedi_async * async) int comedi_auto_config(struct device *hardware_device, const char *board_name, const int *options, unsigned num_options) { - comedi_devconfig it; + struct comedi_devconfig it; int minor; struct comedi_device_file_info *dev_file_info; int retval; + unsigned *private_data = NULL; + + if (!comedi_autoconfig) { + dev_set_drvdata(hardware_device, NULL); + return 0; + } minor = comedi_alloc_board_minor(hardware_device); if(minor < 0) return minor; - dev_set_drvdata(hardware_device, (void*)(unsigned long)minor); + + private_data = kmalloc(sizeof(unsigned), GFP_KERNEL); + if (private_data == NULL) { + retval = -ENOMEM; + goto cleanup; + } + *private_data = minor; + dev_set_drvdata(hardware_device, private_data); dev_file_info = comedi_get_device_file_info(minor); @@ -812,8 +822,11 @@ int comedi_auto_config(struct device *hardware_device, const char *board_name, c mutex_lock(&dev_file_info->device->mutex); retval = comedi_device_attach(dev_file_info->device, &it); mutex_unlock(&dev_file_info->device->mutex); + +cleanup: if(retval < 0) { + kfree(private_data); comedi_free_board_minor(minor); } return retval; @@ -821,20 +834,23 @@ int comedi_auto_config(struct device *hardware_device, const char *board_name, c void comedi_auto_unconfig(struct device *hardware_device) { - unsigned long minor = (unsigned long)dev_get_drvdata(hardware_device); + unsigned *minor = (unsigned *)dev_get_drvdata(hardware_device); + if(minor == NULL) return; - BUG_ON(minor >= COMEDI_NUM_BOARD_MINORS); + BUG_ON(*minor >= COMEDI_NUM_BOARD_MINORS); - comedi_free_board_minor(minor); + comedi_free_board_minor(*minor); + dev_set_drvdata(hardware_device, NULL); + kfree(minor); } int comedi_pci_auto_config(struct pci_dev *pcidev, const char *board_name) { int options[2]; - // pci bus + /* pci bus */ options[0] = pcidev->bus->number; - // pci slot + /* pci slot */ options[1] = PCI_SLOT(pcidev->devfn); return comedi_auto_config(&pcidev->dev, board_name, options, sizeof(options) / sizeof(options[0])); @@ -844,3 +860,16 @@ void comedi_pci_auto_unconfig(struct pci_dev *pcidev) { comedi_auto_unconfig(&pcidev->dev); } + +int comedi_usb_auto_config(struct usb_device *usbdev, + const char *board_name) +{ + BUG_ON(usbdev == NULL); + return comedi_auto_config(&usbdev->dev, board_name, NULL, 0); +} + +void comedi_usb_auto_unconfig(struct usb_device *usbdev) +{ + BUG_ON(usbdev == NULL); + comedi_auto_unconfig(&usbdev->dev); +} diff --git a/drivers/staging/comedi/drivers/8253.h b/drivers/staging/comedi/drivers/8253.h new file mode 100644 index 000000000000..08a11a5a16e6 --- /dev/null +++ b/drivers/staging/comedi/drivers/8253.h @@ -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 diff --git a/drivers/staging/comedi/drivers/8255.c b/drivers/staging/comedi/drivers/8255.c new file mode 100644 index 000000000000..0369c7c84ac5 --- /dev/null +++ b/drivers/staging/comedi/drivers/8255.c @@ -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); diff --git a/drivers/staging/comedi/drivers/8255.h b/drivers/staging/comedi/drivers/8255.h new file mode 100644 index 000000000000..979311b99275 --- /dev/null +++ b/drivers/staging/comedi/drivers/8255.h @@ -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 diff --git a/drivers/staging/comedi/drivers/Makefile b/drivers/staging/comedi/drivers/Makefile index eb7a615e0859..12d6e4312f3a 100644 --- a/drivers/staging/comedi/drivers/Makefile +++ b/drivers/staging/comedi/drivers/Makefile @@ -8,12 +8,121 @@ obj-$(CONFIG_COMEDI) += comedi_test.o obj-$(CONFIG_COMEDI) += comedi_parport.o # Comedi PCI drivers -obj-$(CONFIG_COMEDI_PCI_DRIVERS) += mite.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += 8255.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += acl7225b.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += addi_apci_035.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += addi_apci_1032.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += addi_apci_1500.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += addi_apci_1516.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += addi_apci_1564.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += addi_apci_16xx.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += addi_apci_2016.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += addi_apci_2032.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += addi_apci_2200.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += addi_apci_3001.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += addi_apci_3120.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += addi_apci_3501.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += addi_apci_3xxx.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += adl_pci6208.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += adl_pci7296.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += adl_pci7432.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += adl_pci8164.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += adl_pci9111.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += adl_pci9118.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += adq12b.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += adv_pci1710.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += adv_pci1723.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += adv_pci_dio.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += aio_aio12_8.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += aio_iiro_16.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += amplc_dio200.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += amplc_pc236.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += amplc_pc263.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += amplc_pci224.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += amplc_pci230.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += c6xdigio.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += cb_pcidas64.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += cb_pcidas.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += cb_pcidda.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += cb_pcidio.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += cb_pcimdas.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += cb_pcimdda.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += comedi_bond.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += comedi_parport.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += comedi_test.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += contec_pci_dio.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += daqboard2000.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += das08.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += das16m1.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += das16.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += das1800.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += das6402.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += das800.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += dmm32at.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += dt2801.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += dt2811.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += dt2814.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += dt2815.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += dt2817.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += dt282x.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += dt3000.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += fl512.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += gsc_hpdi.o obj-$(CONFIG_COMEDI_PCI_DRIVERS) += icp_multi.o -obj-$(CONFIG_COMEDI_PCI_DRIVERS) += me_daq.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += ii_pci20kc.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += jr3_pci.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += ke_counter.o obj-$(CONFIG_COMEDI_PCI_DRIVERS) += me4000.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += me_daq.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += mite.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += mpc624.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += multiq3.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += ni_6527.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += ni_65xx.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += ni_660x.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += ni_670x.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += ni_at_a2150.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += ni_at_ao.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += ni_atmio16d.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += ni_atmio.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += ni_labpc.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += ni_pcidio.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += ni_pcimio.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += ni_tiocmd.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += ni_tio.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += pcl711.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += pcl724.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += pcl725.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += pcl726.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += pcl730.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += pcl812.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += pcl816.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += pcl818.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += pcm3724.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += pcm3730.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += pcmad.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += pcmda12.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += pcmmio.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += pcmuio.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += poc.o obj-$(CONFIG_COMEDI_PCI_DRIVERS) += rtd520.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += rti800.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += rti802.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += s526.o obj-$(CONFIG_COMEDI_PCI_DRIVERS) += s626.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += serial2002.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += skel.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += ssv_dnp.o +obj-$(CONFIG_COMEDI_PCI_DRIVERS) += unioxx5.o + +# Comedi PCMCIA drivers +obj-$(CONFIG_COMEDI_PCMCIA_DRIVERS) += cb_das16_cs.o +obj-$(CONFIG_COMEDI_PCMCIA_DRIVERS) += das08_cs.o +obj-$(CONFIG_COMEDI_PCMCIA_DRIVERS) += ni_daq_700.o +obj-$(CONFIG_COMEDI_PCMCIA_DRIVERS) += ni_daq_dio24.o +obj-$(CONFIG_COMEDI_PCMCIA_DRIVERS) += ni_labpc_cs.o +obj-$(CONFIG_COMEDI_PCMCIA_DRIVERS) += ni_mio_cs.o +obj-$(CONFIG_COMEDI_PCMCIA_DRIVERS) += quatech_daqp_cs.o # Comedi USB drivers obj-$(CONFIG_COMEDI_USB_DRIVERS) += usbdux.o diff --git a/drivers/staging/comedi/drivers/acl7225b.c b/drivers/staging/comedi/drivers/acl7225b.c new file mode 100644 index 000000000000..b21320f0959f --- /dev/null +++ b/drivers/staging/comedi/drivers/acl7225b.c @@ -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; +} diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c new file mode 100644 index 000000000000..c96aee09e1b6 --- /dev/null +++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c @@ -0,0 +1,1047 @@ +/* + * 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. + */ +/* + | Description : APCI-1710 82X54 timer module | +*/ + +#include "APCI1710_82x54.h" + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_InitTimer | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_TimerNbr, | +| BYTE_ b_TimerMode, | +| ULONG_ ul_ReloadValue, | +| BYTE_ b_InputClockSelection, | +| BYTE_ b_InputClockLevel, | +| BYTE_ b_OutputLevel, | +| BYTE_ b_HardwareGateLevel) +INT i_InsnConfig_InitTimer(struct comedi_device *dev,struct comedi_subdevice *s, + struct comedi_insn *insn,unsigned int *data) +| ++----------------------------------------------------------------------------+ +| Task : Configure the Timer (b_TimerNbr) operating mode | +| (b_TimerMode) from selected module (b_ModulNbr). | +| You must calling this function be for you call any | +| other function witch access of the timer. | +| | +| | +| Timer mode description table | +| | +|+--------+-----------------------------+--------------+--------------------+| +||Selected+ Mode description +u_ReloadValue | Hardware gate input|| +|| mode | | description | action || +|+--------+-----------------------------+--------------+--------------------+| +|| |Mode 0 is typically used | | || +|| |for event counting. After | | || +|| |the initialisation, OUT | | || +|| |is initially low, and | | || +|| 0 |will remain low until the |Start counting| Hardware gate || +|| |counter reaches zero. | value | || +|| |OUT then goes high and | | || +|| |remains high until a new | | || +|| |count is written. See | | || +|| |"i_APCI1710_WriteTimerValue" | | || +|| |function. | | || +|+--------+-----------------------------+--------------+--------------------+| +|| |Mode 1 is similar to mode 0 | | || +|| |except for the gate input | | || +|| 1 |action. The gate input is not|Start counting| Hardware trigger || +|| |used for enabled or disabled | value | || +|| |the timer. | | || +|| |The gate input is used for | | || +|| |triggered the timer. | | || +|+--------+-----------------------------+--------------+--------------------+| +|| |This mode functions like a | | || +|| |divide-by-ul_ReloadValue | | || +|| |counter. It is typically used| | || +|| |to generate a real time clock| | || +|| |interrupt. OUT will initially| | || +|| 2 |be high after the | Division | Hardware gate || +|| |initialisation. When the | factor | || +|| |initial count has decremented| | || +|| |to 1, OUT goes low for one | | || +|| |CLK pule. OUT then goes high | | || +|| |again, the counter reloads | | || +|| |the initial count | | || +|| |(ul_ReloadValue) and the | | || +|| |process is repeated. | | || +|| |This action can generated a | | || +|| |interrupt. See function | | || +|| |"i_APCI1710_SetBoardInt- | | || +|| |RoutineX" | | || +|| |and "i_APCI1710_EnableTimer" | | || +|+--------+-----------------------------+--------------+--------------------+| +|| |Mode 3 is typically used for | | || +|| |baud rate generation. This | | || +|| |mode is similar to mode 2 | | || +|| |except for the duty cycle of | | || +|| 3 |OUT. OUT will initially be | Division | Hardware gate || +|| |high after the initialisation| factor | || +|| |When half the initial count | | || +|| |(ul_ReloadValue) has expired,| | || +|| |OUT goes low for the | | || +|| |remainder of the count. The | | || +|| |mode is periodic; the | | || +|| |sequence above is repeated | | || +|| |indefinitely. | | || +|+--------+-----------------------------+--------------+--------------------+| +|| |OUT will be initially high | | || +|| |after the initialisation. | | || +|| |When the initial count | | || +|| 4 |expires OUT will go low for |Start counting| Hardware gate || +|| |one CLK pulse and then go | value | || +|| |high again. | | || +|| |The counting sequences is | | || +|| |triggered by writing a new | | || +|| |value. See | | || +|| |"i_APCI1710_WriteTimerValue" | | || +|| |function. If a new count is | | || +|| |written during counting, | | || +|| |it will be loaded on the | | || +|| |next CLK pulse | | || +|+--------+-----------------------------+--------------+--------------------+| +|| |Mode 5 is similar to mode 4 | | || +|| |except for the gate input | | || +|| |action. The gate input is not| | || +|| 5 |used for enabled or disabled |Start counting| Hardware trigger || +|| |the timer. The gate input is | value | || +|| |used for triggered the timer.| | || +|+--------+-----------------------------+--------------+--------------------+| +| | +| | +| | +| Input clock selection table | +| | +| +--------------------------------+------------------------------------+ | +| | b_InputClockSelection | Description | | +| | parameter | | | +| +--------------------------------+------------------------------------+ | +| | APCI1710_PCI_BUS_CLOCK | For the timer input clock, the PCI | | +| | | bus clock / 4 is used. This PCI bus| | +| | | clock can be 30MHz or 33MHz. For | | +| | | Timer 0 only this selection are | | +| | | available. | | +| +--------------------------------+------------------------------------+ | +| | APCI1710_ FRONT_CONNECTOR_INPUT| Of the front connector you have the| | +| | | possibility to inject a input clock| | +| | | for Timer 1 or Timer 2. The source | | +| | | from this clock can eat the output | | +| | | clock from Timer 0 or any other | | +| | | clock source. | | +| +--------------------------------+------------------------------------+ | +| | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board | +| APCI-1710 | +| BYTE_ b_ModulNbr : Module number to | +| configure (0 to 3) | +| BYTE_ b_TimerNbr : Timer number to | +| configure (0 to 2) | +| BYTE_ b_TimerMode : Timer mode selection | +| (0 to 5) | +| 0: Interrupt on terminal| +| count | +| 1: Hardware | +| retriggerable one- | +| shot | +| 2: Rate generator | +| 3: Square wave mode | +| 4: Software triggered | +| strobe | +| 5: Hardware triggered | +| strobe | +| See timer mode | +| description table. | +| ULONG_ ul_ReloadValue : Start counting value | +| or division factor | +| See timer mode | +| description table. | +| BYTE_ b_InputClockSelection : Selection from input | +| timer clock. | +| See input clock | +| selection table. | +| BYTE_ b_InputClockLevel : Selection from input | +| clock level. | +| 0 : Low active | +| (Input inverted) | +| 1 : High active | +| BYTE_ b_OutputLevel, : Selection from output | +| clock level. | +| 0 : Low active | +| 1 : High active | +| (Output inverted) | +| BYTE_ b_HardwareGateLevel : Selection from | +| hardware gate level. | +| 0 : Low active | +| (Input inverted) | +| 1 : High active | +| If you will not used | +| the hardware gate set | +| this value to 0. +|b_ModulNbr = (BYTE) CR_AREF(insn->chanspec); + b_TimerNbr = (BYTE) CR_CHAN(insn->chanspec); + b_TimerMode = (BYTE) data[0]; + ul_ReloadValue = (ULONG) data[1]; + b_InputClockSelection =(BYTE) data[2]; + b_InputClockLevel =(BYTE) data[3]; + b_OutputLevel =(BYTE) data[4]; + b_HardwareGateLevel =(BYTE) data[5]; ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: Module selection wrong | +| -3: Timer selection wrong | +| -4: The module is not a TIMER module | +| -5: Timer mode selection is wrong | +| -6: Input timer clock selection is wrong | +| -7: Selection from input clock level is wrong | +| -8: Selection from output clock level is wrong | +| -9: Selection from hardware gate level is wrong | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_InsnConfigInitTimer(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + + INT i_ReturnValue = 0; + BYTE b_ModulNbr; + BYTE b_TimerNbr; + BYTE b_TimerMode; + ULONG ul_ReloadValue; + BYTE b_InputClockSelection; + BYTE b_InputClockLevel; + BYTE b_OutputLevel; + BYTE b_HardwareGateLevel; + + //BEGIN JK 27.10.2003 : Add the possibility to use a 40 Mhz quartz + DWORD dw_Test = 0; + //END JK 27.10.2003 : Add the possibility to use a 40 Mhz quartz + + i_ReturnValue = insn->n; + b_ModulNbr = (BYTE) CR_AREF(insn->chanspec); + b_TimerNbr = (BYTE) CR_CHAN(insn->chanspec); + b_TimerMode = (BYTE) data[0]; + ul_ReloadValue = (ULONG) data[1]; + b_InputClockSelection = (BYTE) data[2]; + b_InputClockLevel = (BYTE) data[3]; + b_OutputLevel = (BYTE) data[4]; + b_HardwareGateLevel = (BYTE) data[5]; + + /* Test the module number */ + if (b_ModulNbr < 4) { + /* Test if 82X54 timer */ + if ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF0000UL) == APCI1710_82X54_TIMER) { + /* Test the timer number */ + + if (b_TimerNbr <= 2) { + /* Test the timer mode */ + if (b_TimerMode <= 5) { + //BEGIN JK 27.10.2003 : Add the possibility to use a 40 Mhz quartz + /* Test te imput clock selection */ + /* + if (((b_TimerNbr == 0) && (b_InputClockSelection == 0)) || + ((b_TimerNbr != 0) && ((b_InputClockSelection == 0) || (b_InputClockSelection == 1)))) + */ + + if (((b_TimerNbr == 0) && + (b_InputClockSelection == APCI1710_PCI_BUS_CLOCK)) || + ((b_TimerNbr == 0) && + (b_InputClockSelection == APCI1710_10MHZ)) || + ((b_TimerNbr != 0) && + ((b_InputClockSelection == APCI1710_PCI_BUS_CLOCK) || + (b_InputClockSelection == APCI1710_FRONT_CONNECTOR_INPUT) || + (b_InputClockSelection == APCI1710_10MHZ)))) { + //BEGIN JK 27.10.2003 : Add the possibility to use a 40 Mhz quartz + if (((b_InputClockSelection == APCI1710_10MHZ) && + ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0x0000FFFFUL) >= 0x3131)) || + (b_InputClockSelection != APCI1710_10MHZ)) { + //END JK 27.10.2003 : Add the possibility to use a 40 Mhz quartz + /* Test the input clock level selection */ + + if ((b_InputClockLevel == 0) || + (b_InputClockLevel == 1)) { + /* Test the output clock level selection */ + if ((b_OutputLevel == 0) || (b_OutputLevel == 1)) { + /* Test the hardware gate level selection */ + if ((b_HardwareGateLevel == 0) || (b_HardwareGateLevel == 1)) { + //BEGIN JK 27.10.03 : Add the possibility to use a 40 Mhz quartz + /* Test if version > 1.1 and clock selection = 10MHz */ + if ((b_InputClockSelection == APCI1710_10MHZ) && ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0x0000FFFFUL) > 0x3131)) { + /* Test if 40MHz quartz on board */ + dw_Test = inl(devpriv->s_BoardInfos.ui_Address + (16 + (b_TimerNbr * 4) + (64 * b_ModulNbr))); + + dw_Test = (dw_Test >> 16) & 1; + } else { + dw_Test = 1; + } + + /* Test if detection OK */ + if (dw_Test == 1) { + //END JK 27.10.03 : Add the possibility to use a 40 Mhz quartz + /* Initialisation OK */ + devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].b_82X54Init = 1; + + /* Save the input clock selection */ + devpriv-> s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].b_InputClockSelection = b_InputClockSelection; + + /* Save the input clock level */ + devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].b_InputClockLevel = ~b_InputClockLevel & 1; + + /* Save the output level */ + devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].b_OutputLevel = ~b_OutputLevel & 1; + + /* Save the gate level */ + devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].b_HardwareGateLevel = b_HardwareGateLevel; + + /* Set the configuration word and disable the timer */ + //BEGIN JK 27.10.03 : Add the possibility to use a 40 Mhz quartz + /* + devpriv->s_ModuleInfo [b_ModulNbr]. + s_82X54ModuleInfo. + s_82X54TimerInfo [b_TimerNbr]. + dw_ConfigurationWord = (DWORD) (((b_HardwareGateLevel << 0) & 0x1) | + ((b_InputClockLevel << 1) & 0x2) | + (((~b_OutputLevel & 1) << 2) & 0x4) | + ((b_InputClockSelection << 4) & 0x10)); + */ + /* Test if 10MHz selected */ + if (b_InputClockSelection == APCI1710_10MHZ) { + b_InputClockSelection = 2; + } + + devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].dw_ConfigurationWord = (DWORD)(((b_HardwareGateLevel << 0) & 0x1) | ((b_InputClockLevel << 1) & 0x2) | (((~b_OutputLevel & 1) << 2) & 0x4) | ((b_InputClockSelection << 4) & 0x30)); + //END JK 27.10.03 : Add the possibility to use a 40 Mhz quartz + outl(devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].dw_ConfigurationWord, devpriv->s_BoardInfos.ui_Address + 32 + (b_TimerNbr * 4) + (64 * b_ModulNbr)); + + /* Initialise the 82X54 Timer */ + outl((DWORD) b_TimerMode, devpriv->s_BoardInfos.ui_Address + 16 + (b_TimerNbr * 4) + (64 * b_ModulNbr)); + + /* Write the reload value */ + outl(ul_ReloadValue, devpriv->s_BoardInfos.ui_Address + 0 + (b_TimerNbr * 4) + (64 * b_ModulNbr)); + //BEGIN JK 27.10.03 : Add the possibility to use a 40 Mhz quartz + } // if (dw_Test == 1) + else { + /* Input timer clock selection is wrong */ + i_ReturnValue = -6; + } // if (dw_Test == 1) + //END JK 27.10.03 : Add the possibility to use a 40 Mhz quartz + } // if ((b_HardwareGateLevel == 0) || (b_HardwareGateLevel == 1)) + else { + /* Selection from hardware gate level is wrong */ + DPRINTK("Selection from hardware gate level is wrong\n"); + i_ReturnValue = -9; + } // if ((b_HardwareGateLevel == 0) || (b_HardwareGateLevel == 1)) + } // if ((b_OutputLevel == 0) || (b_OutputLevel == 1)) + else { + /* Selection from output clock level is wrong */ + DPRINTK("Selection from output clock level is wrong\n"); + i_ReturnValue = -8; + } // if ((b_OutputLevel == 0) || (b_OutputLevel == 1)) + } // if ((b_InputClockLevel == 0) || (b_InputClockLevel == 1)) + else { + /* Selection from input clock level is wrong */ + DPRINTK("Selection from input clock level is wrong\n"); + i_ReturnValue = -7; + } // if ((b_InputClockLevel == 0) || (b_InputClockLevel == 1)) + } else { + /* Input timer clock selection is wrong */ + DPRINTK("Input timer clock selection is wrong\n"); + i_ReturnValue = -6; + } + } else { + /* Input timer clock selection is wrong */ + DPRINTK("Input timer clock selection is wrong\n"); + i_ReturnValue = -6; + } + } // if ((b_TimerMode >= 0) && (b_TimerMode <= 5)) + else { + /* Timer mode selection is wrong */ + DPRINTK("Timer mode selection is wrong\n"); + i_ReturnValue = -5; + } // if ((b_TimerMode >= 0) && (b_TimerMode <= 5)) + } // if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2)) + else { + /* Timer selection wrong */ + DPRINTK("Timer selection wrong\n"); + i_ReturnValue = -3; + } // if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2)) + } else { + /* The module is not a TIMER module */ + DPRINTK("The module is not a TIMER module\n"); + i_ReturnValue = -4; + } + } else { + /* Module number error */ + DPRINTK("Module number error\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_EnableTimer | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_TimerNbr, | +| BYTE_ b_InterruptEnable) +INT i_APCI1710_InsnWriteEnableDisableTimer(struct comedi_device *dev,struct comedi_subdevice *s, + struct comedi_insn *insn,unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task : Enable OR Disable the Timer (b_TimerNbr) from selected module | +| (b_ModulNbr). You must calling the | +| "i_APCI1710_InitTimer" function be for you call this | +| function. If you enable the timer interrupt, the timer | +| generate a interrupt after the timer value reach | +| the zero. See function "i_APCI1710_SetBoardIntRoutineX"| ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board | +| APCI-1710 | +| BYTE_ b_ModulNbr : Selected module number | +| (0 to 3) | +| BYTE_ b_TimerNbr : Timer number to enable | +| (0 to 2) | +| BYTE_ b_InterruptEnable : Enable or disable the | +| timer interrupt. | +| APCI1710_ENABLE : | +| Enable the timer interrupt | +| APCI1710_DISABLE : | +| Disable the timer interrupt| +i_ReturnValue=insn->n; + b_ModulNbr = (BYTE) CR_AREF(insn->chanspec); + b_TimerNbr = (BYTE) CR_CHAN(insn->chanspec); + b_ActionType = (BYTE) data[0]; // enable disable ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: Module selection wrong | +| -3: Timer selection wrong | +| -4: The module is not a TIMER module | +| -5: Timer not initialised see function | +| "i_APCI1710_InitTimer" | +| -6: Interrupt parameter is wrong | +| -7: Interrupt function not initialised. | +| See function "i_APCI1710_SetBoardIntRoutineX" | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_InsnWriteEnableDisableTimer(struct comedi_device * dev, + struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + INT i_ReturnValue = 0; + DWORD dw_DummyRead; + BYTE b_ModulNbr; + BYTE b_TimerNbr; + BYTE b_ActionType; + BYTE b_InterruptEnable; + + i_ReturnValue = insn->n; + b_ModulNbr = (BYTE) CR_AREF(insn->chanspec); + b_TimerNbr = (BYTE) CR_CHAN(insn->chanspec); + b_ActionType = (BYTE) data[0]; // enable disable + + /* Test the module number */ + if (b_ModulNbr < 4) { + /* Test if 82X54 timer */ + if ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF0000UL) == APCI1710_82X54_TIMER) { + /* Test the timer number */ + if (b_TimerNbr <= 2) { + /* Test if timer initialised */ + if (devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].b_82X54Init == 1) { + + switch (b_ActionType) { + case APCI1710_ENABLE: + b_InterruptEnable = (BYTE) data[1]; + /* Test the interrupt selection */ + if ((b_InterruptEnable == APCI1710_ENABLE) || + (b_InterruptEnable == APCI1710_DISABLE)) { + if (b_InterruptEnable == APCI1710_ENABLE) { + + dw_DummyRead = inl(devpriv->s_BoardInfos.ui_Address + 12 + (b_TimerNbr * 4) + (64 * b_ModulNbr)); + + /* Enable the interrupt */ + devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].dw_ConfigurationWord = devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].dw_ConfigurationWord | 0x8; + + outl(devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].dw_ConfigurationWord, devpriv->s_BoardInfos.ui_Address + 32 + (b_TimerNbr * 4) + (64 * b_ModulNbr)); + devpriv->tsk_Current = current; // Save the current process task structure + + } // if (b_InterruptEnable == APCI1710_ENABLE) + else { + /* Disable the interrupt */ + devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].dw_ConfigurationWord = devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].dw_ConfigurationWord & 0xF7; + + outl(devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].dw_ConfigurationWord, devpriv->s_BoardInfos.ui_Address + 32 + (b_TimerNbr * 4) + (64 * b_ModulNbr)); + + /* Save the interrupt flag */ + devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.b_InterruptMask = devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.b_InterruptMask & (0xFF - (1 << b_TimerNbr)); + } // if (b_InterruptEnable == APCI1710_ENABLE) + + /* Test if error occur */ + if (i_ReturnValue >= 0) { + /* Save the interrupt flag */ + devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.b_InterruptMask = devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.b_InterruptMask | ((1 & b_InterruptEnable) << b_TimerNbr); + + /* Enable the timer */ + outl(1, devpriv->s_BoardInfos.ui_Address + 44 + (b_TimerNbr * 4) + (64 * b_ModulNbr)); + } + } else { + /* Interrupt parameter is wrong */ + DPRINTK("\n"); + i_ReturnValue = -6; + } + break; + case APCI1710_DISABLE: + /* Test the interrupt flag */ + if (((devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.b_InterruptMask >> b_TimerNbr) & 1) == 1) { + /* Disable the interrupt */ + + devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr]. dw_ConfigurationWord = devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].dw_ConfigurationWord & 0xF7; + + outl(devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].dw_ConfigurationWord, devpriv->s_BoardInfos.ui_Address + 32 + (b_TimerNbr * 4) + (64 * b_ModulNbr)); + + /* Save the interrupt flag */ + devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.b_InterruptMask = devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.b_InterruptMask & (0xFF - (1 << b_TimerNbr)); + } + + /* Disable the timer */ + outl(0, devpriv->s_BoardInfos.ui_Address + 44 + (b_TimerNbr * 4) + (64 * b_ModulNbr)); + break; + } // Switch end + } else { + /* Timer not initialised see function */ + DPRINTK ("Timer not initialised see function\n"); + i_ReturnValue = -5; + } + } else { + /* Timer selection wrong */ + DPRINTK("Timer selection wrong\n"); + i_ReturnValue = -3; + } // if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2)) + } else { + /* The module is not a TIMER module */ + DPRINTK("The module is not a TIMER module\n"); + i_ReturnValue = -4; + } + } else { + /* Module number error */ + DPRINTK("Module number error\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_ReadAllTimerValue | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| PULONG_ pul_TimerValueArray) +INT i_APCI1710_InsnReadAllTimerValue(struct comedi_device *dev,struct comedi_subdevice *s, + struct comedi_insn *insn,unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task : Return the all timer values from selected timer | +| module (b_ModulNbr). | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board | +| APCI-1710 | +| BYTE_ b_ModulNbr : Selected module number | +| (0 to 3) | ++----------------------------------------------------------------------------+ +| Output Parameters : PULONG_ pul_TimerValueArray : Timer value array. | +| Element 0 contain the timer 0 value. | +| Element 1 contain the timer 1 value. | +| Element 2 contain the timer 2 value. | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: Module selection wrong | +| -3: The module is not a TIMER module | +| -4: Timer 0 not initialised see function | +| "i_APCI1710_InitTimer" | +| -5: Timer 1 not initialised see function | +| "i_APCI1710_InitTimer" | +| -6: Timer 2 not initialised see function | +| "i_APCI1710_InitTimer" | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_InsnReadAllTimerValue(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) +{ + INT i_ReturnValue = 0; + BYTE b_ModulNbr, b_ReadType; + PULONG pul_TimerValueArray; + + b_ModulNbr = CR_AREF(insn->chanspec); + b_ReadType = CR_CHAN(insn->chanspec); + pul_TimerValueArray = (PULONG) data; + i_ReturnValue = insn->n; + + switch (b_ReadType) { + case APCI1710_TIMER_READINTERRUPT: + + 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; + + break; + + case APCI1710_TIMER_READALLTIMER: + /* Test the module number */ + if (b_ModulNbr < 4) { + /* Test if 82X54 timer */ + if ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF0000UL) == APCI1710_82X54_TIMER) { + /* Test if timer 0 iniutialised */ + if (devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[0].b_82X54Init == 1) { + /* Test if timer 1 iniutialised */ + if (devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[1].b_82X54Init == 1) { + /* Test if timer 2 iniutialised */ + if (devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[2].b_82X54Init == 1) { + /* Latch all counter */ + outl(0x17, devpriv->s_BoardInfos.ui_Address + 12 + (64 * b_ModulNbr)); + + /* Read the timer 0 value */ + pul_TimerValueArray[0] = inl(devpriv->s_BoardInfos.ui_Address + 0 + (64 * b_ModulNbr)); + + /* Read the timer 1 value */ + pul_TimerValueArray[1] = inl(devpriv->s_BoardInfos.ui_Address + 4 + (64 * b_ModulNbr)); + + /* Read the timer 2 value */ + pul_TimerValueArray[2] = inl(devpriv->s_BoardInfos.ui_Address + 8 + (64 * b_ModulNbr)); + } else { + /* Timer 2 not initialised see function */ + DPRINTK("Timer 2 not initialised see function\n"); + i_ReturnValue = -6; + } + } else { + /* Timer 1 not initialised see function */ + DPRINTK("Timer 1 not initialised see function\n"); + i_ReturnValue = -5; + } + } else { + /* Timer 0 not initialised see function */ + DPRINTK("Timer 0 not initialised see function\n"); + i_ReturnValue = -4; + } + } else { + /* The module is not a TIMER module */ + DPRINTK("The module is not a TIMER module\n"); + i_ReturnValue = -3; + } + } else { + /* Module number error */ + DPRINTK("Module number error\n"); + i_ReturnValue = -2; + } + + } // End of Switch + return (i_ReturnValue); +} + +/* ++----------------------------------------------------------------------------+ +| Function Name :INT i_APCI1710_InsnBitsTimer(struct comedi_device *dev, +struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task : Read write functions for Timer | ++----------------------------------------------------------------------------+ +| Input Parameters : ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_InsnBitsTimer(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + BYTE b_BitsType; + INT i_ReturnValue = 0; + b_BitsType = data[0]; + + printk("\n82X54"); + + switch (b_BitsType) { + case APCI1710_TIMER_READVALUE: + i_ReturnValue = i_APCI1710_ReadTimerValue(dev, + (BYTE)CR_AREF(insn->chanspec), + (BYTE)CR_CHAN(insn->chanspec), + (PULONG) & data[0]); + break; + + case APCI1710_TIMER_GETOUTPUTLEVEL: + i_ReturnValue = i_APCI1710_GetTimerOutputLevel(dev, + (BYTE)CR_AREF(insn->chanspec), + (BYTE)CR_CHAN(insn->chanspec), + (PBYTE) &data[0]); + break; + + case APCI1710_TIMER_GETPROGRESSSTATUS: + i_ReturnValue = i_APCI1710_GetTimerProgressStatus(dev, + (BYTE)CR_AREF(insn->chanspec), + (BYTE)CR_CHAN(insn->chanspec), + (PBYTE)&data[0]); + break; + + case APCI1710_TIMER_WRITEVALUE: + i_ReturnValue = i_APCI1710_WriteTimerValue(dev, + (BYTE)CR_AREF(insn->chanspec), + (BYTE)CR_CHAN(insn->chanspec), + (ULONG)data[1]); + + break; + + default: + printk("Bits Config Parameter Wrong\n"); + i_ReturnValue = -1; + } + + if (i_ReturnValue >= 0) + i_ReturnValue = insn->n; + return (i_ReturnValue); +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_ReadTimerValue | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_TimerNbr, | +| PULONG_ pul_TimerValue) | ++----------------------------------------------------------------------------+ +| Task : Return the timer value from selected digital timer | +| (b_TimerNbr) from selected timer module (b_ModulNbr). | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board | +| APCI-1710 | +| BYTE_ b_ModulNbr : Selected module number | +| (0 to 3) | +| BYTE_ b_TimerNbr : Timer number to read | +| (0 to 2) | ++----------------------------------------------------------------------------+ +| Output Parameters : PULONG_ pul_TimerValue : Timer value | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: Module selection wrong | +| -3: Timer selection wrong | +| -4: The module is not a TIMER module | +| -5: Timer not initialised see function | +| "i_APCI1710_InitTimer" | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_ReadTimerValue(struct comedi_device * dev, + BYTE b_ModulNbr, BYTE b_TimerNbr, + PULONG pul_TimerValue) +{ + INT i_ReturnValue = 0; + + /* Test the module number */ + if (b_ModulNbr < 4) { + /* Test if 82X54 timer */ + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration[b_ModulNbr] & + 0xFFFF0000UL) == APCI1710_82X54_TIMER) { + /* Test the timer number */ + if (b_TimerNbr <= 2) { + /* Test if timer initialised */ + if (devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_82X54ModuleInfo. + s_82X54TimerInfo[b_TimerNbr]. + b_82X54Init == 1) { + /* Latch the timer value */ + outl((2 << b_TimerNbr) | 0xD0, + devpriv->s_BoardInfos. + ui_Address + 12 + + (64 * b_ModulNbr)); + + /* Read the counter value */ + *pul_TimerValue = + inl(devpriv->s_BoardInfos. + ui_Address + (b_TimerNbr * 4) + + (64 * b_ModulNbr)); + } else { + /* Timer not initialised see function */ + DPRINTK("Timer not initialised see function\n"); + i_ReturnValue = -5; + } + } else { + /* Timer selection wrong */ + DPRINTK("Timer selection wrong\n"); + i_ReturnValue = -3; + } // if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2)) + } else { + /* The module is not a TIMER module */ + DPRINTK("The module is not a TIMER module\n"); + i_ReturnValue = -4; + } + } else { + /* Module number error */ + DPRINTK("Module number error\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); +} + + /* + +----------------------------------------------------------------------------+ + | Function Name : _INT_ i_APCI1710_GetTimerOutputLevel | + | (BYTE_ b_BoardHandle, | + | BYTE_ b_ModulNbr, | + | BYTE_ b_TimerNbr, | + | PBYTE_ pb_OutputLevel) | + +----------------------------------------------------------------------------+ + | Task : Return the output signal level (pb_OutputLevel) from | + | selected digital timer (b_TimerNbr) from selected timer| + | module (b_ModulNbr). | + +----------------------------------------------------------------------------+ + | Input Parameters : BYTE_ b_BoardHandle : Handle of board | + | APCI-1710 | + | BYTE_ b_ModulNbr : Selected module number | + | (0 to 3) | + | BYTE_ b_TimerNbr : Timer number to test | + | (0 to 2) | + +----------------------------------------------------------------------------+ + | Output Parameters : PBYTE_ pb_OutputLevel : Output signal level | + | 0 : The output is low | + | 1 : The output is high | + +----------------------------------------------------------------------------+ + | Return Value : 0: No error | + | -1: The handle parameter of the board is wrong | + | -2: Module selection wrong | + | -3: Timer selection wrong | + | -4: The module is not a TIMER module | + | -5: Timer not initialised see function | + | "i_APCI1710_InitTimer" | + +----------------------------------------------------------------------------+ + */ + +INT i_APCI1710_GetTimerOutputLevel(struct comedi_device * dev, + BYTE b_ModulNbr, BYTE b_TimerNbr, + PBYTE pb_OutputLevel) +{ + INT i_ReturnValue = 0; + DWORD dw_TimerStatus; + + /* Test the module number */ + if (b_ModulNbr < 4) { + /* Test if 82X54 timer */ + if ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF0000UL) == APCI1710_82X54_TIMER) { + /* Test the timer number */ + if (b_TimerNbr <= 2) { + /* Test if timer initialised */ + if (devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].b_82X54Init == 1) { + /* Latch the timer value */ + outl((2 << b_TimerNbr) | 0xE0, devpriv->s_BoardInfos.ui_Address + 12 + (64 * b_ModulNbr)); + + /* Read the timer status */ + dw_TimerStatus = inl(devpriv->s_BoardInfos.ui_Address + 16 + (b_TimerNbr * 4) + (64 * b_ModulNbr)); + + *pb_OutputLevel = (BYTE) (((dw_TimerStatus >> 7) & 1) ^ devpriv-> s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].b_OutputLevel); + } else { + /* Timer not initialised see function */ + DPRINTK("Timer not initialised see function\n"); + i_ReturnValue = -5; + } + } else { + /* Timer selection wrong */ + DPRINTK("Timer selection wrong\n"); + i_ReturnValue = -3; + } // if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2)) + } else { + /* The module is not a TIMER module */ + DPRINTK("The module is not a TIMER module\n"); + i_ReturnValue = -4; + } + } else { + /* Module number error */ + DPRINTK("Module number error\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_GetTimerProgressStatus | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_TimerNbr, | +| PBYTE_ pb_TimerStatus) | ++----------------------------------------------------------------------------+ +| Task : Return the progress status (pb_TimerStatus) from | +| selected digital timer (b_TimerNbr) from selected timer| +| module (b_ModulNbr). | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board | +| APCI-1710 | +| BYTE_ b_ModulNbr : Selected module number | +| (0 to 3) | +| BYTE_ b_TimerNbr : Timer number to test | +| (0 to 2) | ++----------------------------------------------------------------------------+ +| Output Parameters : PBYTE_ pb_TimerStatus : Output signal level | +| 0 : Timer not in progress | +| 1 : Timer in progress | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: Module selection wrong | +| -3: Timer selection wrong | +| -4: The module is not a TIMER module | +| -5: Timer not initialised see function | +| "i_APCI1710_InitTimer" | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_GetTimerProgressStatus(struct comedi_device *dev, + BYTE b_ModulNbr, BYTE b_TimerNbr, + PBYTE pb_TimerStatus) +{ + INT i_ReturnValue = 0; + DWORD dw_TimerStatus; + + /* Test the module number */ + if (b_ModulNbr < 4) { + /* Test if 82X54 timer */ + + if ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF0000UL) == APCI1710_82X54_TIMER) { + /* Test the timer number */ + if (b_TimerNbr <= 2) { + /* Test if timer initialised */ + if (devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].b_82X54Init == 1) { + /* Latch the timer value */ + outl((2 << b_TimerNbr) | 0xE0, devpriv->s_BoardInfos.ui_Address + 12 + (64 * b_ModulNbr)); + + /* Read the timer status */ + dw_TimerStatus = inl(devpriv->s_BoardInfos.ui_Address + 16 + (b_TimerNbr * 4) + (64 * b_ModulNbr)); + + *pb_TimerStatus = (BYTE) ((dw_TimerStatus) >> 8) & 1; + printk("ProgressStatus : %d", *pb_TimerStatus); + } else { + /* Timer not initialised see function */ + i_ReturnValue = -5; + } + } else { + /* Timer selection wrong */ + i_ReturnValue = -3; + } // if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2)) + } else { + /* The module is not a TIMER module */ + + i_ReturnValue = -4; + } + } else { + /* Module number error */ + + i_ReturnValue = -2; + } + + return i_ReturnValue; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_WriteTimerValue | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_TimerNbr, | +| ULONG_ ul_WriteValue) | ++----------------------------------------------------------------------------+ +| Task : Write the value (ul_WriteValue) into the selected timer| +| (b_TimerNbr) from selected timer module (b_ModulNbr). | +| The action in depend of the time mode selection. | +| See timer mode description table. | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board | +| APCI-1710 | +| BYTE_ b_ModulNbr : Selected module number | +| (0 to 3) | +| BYTE_ b_TimerNbr : Timer number to write | +| (0 to 2) | +| ULONG_ ul_WriteValue : Value to write | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: Module selection wrong | +| -3: Timer selection wrong | +| -4: The module is not a TIMER module | +| -5: Timer not initialised see function | +| "i_APCI1710_InitTimer" | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_WriteTimerValue(struct comedi_device * dev, + BYTE b_ModulNbr, BYTE b_TimerNbr, + ULONG ul_WriteValue) +{ + INT i_ReturnValue = 0; + + /* Test the module number */ + if (b_ModulNbr < 4) { + /* Test if 82X54 timer */ + if ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF0000UL) == APCI1710_82X54_TIMER) { + /* Test the timer number */ + if (b_TimerNbr <= 2) { + /* Test if timer initialised */ + if (devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].b_82X54Init == 1) { + /* Write the value */ + outl(ul_WriteValue, devpriv->s_BoardInfos.ui_Address + (b_TimerNbr * 4) + (64 * b_ModulNbr)); + } else { + /* Timer not initialised see function */ + DPRINTK("Timer not initialised see function\n"); + i_ReturnValue = -5; + } + } else { + /* Timer selection wrong */ + DPRINTK("Timer selection wrong\n"); + i_ReturnValue = -3; + } // if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2)) + } else { + /* The module is not a TIMER module */ + DPRINTK("The module is not a TIMER module\n"); + i_ReturnValue = -4; + } + } else { + /* Module number error */ + DPRINTK("Module number error\n"); + i_ReturnValue = -2; + } + + return i_ReturnValue; +} diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.h new file mode 100644 index 000000000000..4797c0b77a43 --- /dev/null +++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.h @@ -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); diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c new file mode 100644 index 000000000000..1a54d3b2c694 --- /dev/null +++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c @@ -0,0 +1,2032 @@ +/** +@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 : CHRONO.C | Version : 2.96 | + +-------------------------------+---------------------------------------+ + | Project manager: Eric Stolz | Date : 02/12/2002 | + +-----------------------------------------------------------------------+ + | Description : APCI-1710 chronometer module | + | | + | | + +-----------------------------------------------------------------------+ + | UPDATES | + +-----------------------------------------------------------------------+ + | Date | Author | Description of updates | + +----------+-----------+------------------------------------------------+ + | 29/06/98 | S. Weber | Digital input / output implementation | + |----------|-----------|------------------------------------------------| + | 08/05/00 | Guinot C | - 0400/0228 All Function in RING 0 | + | | | available | + +-----------------------------------------------------------------------+ + | | | | + | | | | + +-----------------------------------------------------------------------+ +*/ + +/* ++----------------------------------------------------------------------------+ +| Included files | ++----------------------------------------------------------------------------+ +*/ +#include "APCI1710_Chrono.h" + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_InitChrono | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_ChronoMode, | +| BYTE_ b_PCIInputClock, | +| BYTE_ b_TimingUnit, | +| ULONG_ ul_TimingInterval, | +| PULONG_ pul_RealTimingInterval) + ++----------------------------------------------------------------------------+ +| Task : Configure the chronometer operating mode (b_ChronoMode)| +| from selected module (b_ModulNbr). | +| The ul_TimingInterval and ul_TimingUnit determine the | +| timing base for the measurement. | +| The pul_RealTimingInterval return the real timing | +| value. You must calling this function be for you call | +| any other function witch access of the chronometer. | +| | +| Witch this functionality from the APCI-1710 you have | +| the possibility to measure the timing witch two event. | +| | +| The mode 0 and 1 is appropriate for period measurement.| +| The mode 2 and 3 is appropriate for frequent | +| measurement. | +| The mode 4 to 7 is appropriate for measuring the timing| +| between two event. | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr CR_AREF(insn->chanspec) : Module number to configure | +| (0 to 3) | +| BYTE_ b_ChronoMode data[0] : Chronometer action mode | +| (0 to 7). | +| BYTE_ b_PCIInputClock data[1] : 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 | +| - APCI1710_40MHZ | +| The APCI-1710 have a | +| integrated 40Mhz | +| quartz. | +| BYTE_ b_TimingUnit data[2] : Base timing unity (0 to 4) | +| 0 : ns | +| 1 : µs | +| 2 : ms | +| 3 : s | +| 4 : mn | +| ULONG_ ul_TimingInterval : data[3] Base timing value. | ++----------------------------------------------------------------------------+ +| Output Parameters : PULONG_ pul_RealTimingInterval : Real base timing | +| value. +| data[0] ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: Module selection wrong | +| -3: The module is not a Chronometer module | +| -4: Chronometer mode selection is wrong | +| -5: The selected PCI input clock is wrong | +| -6: Timing unity selection is wrong | +| -7: Base timing selection is wrong | +| -8: You can not used the 40MHz clock selection wich | +| this board | +| -9: You can not used the 40MHz clock selection wich | +| this CHRONOS version | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_InsnConfigInitChrono(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + INT i_ReturnValue = 0; + ULONG ul_TimerValue = 0; + ULONG ul_TimingInterval = 0; + ULONG ul_RealTimingInterval = 0; + double d_RealTimingInterval = 0; + DWORD dw_ModeArray[8] = + { 0x01, 0x05, 0x00, 0x04, 0x02, 0x0E, 0x0A, 0x06 }; + BYTE b_ModulNbr, b_ChronoMode, b_PCIInputClock, b_TimingUnit; + + b_ModulNbr = CR_AREF(insn->chanspec); + b_ChronoMode = (BYTE) data[0]; + b_PCIInputClock = (BYTE) data[1]; + b_TimingUnit = (BYTE) data[2]; + ul_TimingInterval = (ULONG) data[3]; + i_ReturnValue = insn->n; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) { + /***********************/ + /* Test if chronometer */ + /***********************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration[b_ModulNbr] & + 0xFFFF0000UL) == APCI1710_CHRONOMETER) { + /*****************************/ + /* Test the chronometer mode */ + /*****************************/ + + if (b_ChronoMode <= 7) { + /**************************/ + /* Test the PCI bus clock */ + /**************************/ + + if ((b_PCIInputClock == APCI1710_30MHZ) || + (b_PCIInputClock == APCI1710_33MHZ) || + (b_PCIInputClock == APCI1710_40MHZ)) { + /*************************/ + /* Test the timing unity */ + /*************************/ + + if (b_TimingUnit <= 4) { + /**********************************/ + /* Test the base timing selection */ + /**********************************/ + + if (((b_PCIInputClock == APCI1710_30MHZ) && (b_TimingUnit == 0) && (ul_TimingInterval >= 66) && (ul_TimingInterval <= 0xFFFFFFFFUL)) || ((b_PCIInputClock == APCI1710_30MHZ) && (b_TimingUnit == 1) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 143165576UL)) || ((b_PCIInputClock == APCI1710_30MHZ) && (b_TimingUnit == 2) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 143165UL)) || ((b_PCIInputClock == APCI1710_30MHZ) && (b_TimingUnit == 3) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 143UL)) || ((b_PCIInputClock == APCI1710_30MHZ) && (b_TimingUnit == 4) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 2UL)) || ((b_PCIInputClock == APCI1710_33MHZ) && (b_TimingUnit == 0) && (ul_TimingInterval >= 60) && (ul_TimingInterval <= 0xFFFFFFFFUL)) || ((b_PCIInputClock == APCI1710_33MHZ) && (b_TimingUnit == 1) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 130150240UL)) || ((b_PCIInputClock == APCI1710_33MHZ) && (b_TimingUnit == 2) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 130150UL)) || ((b_PCIInputClock == APCI1710_33MHZ) && (b_TimingUnit == 3) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 130UL)) || ((b_PCIInputClock == APCI1710_33MHZ) && (b_TimingUnit == 4) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 2UL)) || ((b_PCIInputClock == APCI1710_40MHZ) && (b_TimingUnit == 0) && (ul_TimingInterval >= 50) && (ul_TimingInterval <= 0xFFFFFFFFUL)) || ((b_PCIInputClock == APCI1710_40MHZ) && (b_TimingUnit == 1) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 107374182UL)) || ((b_PCIInputClock == APCI1710_40MHZ) && (b_TimingUnit == 2) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 107374UL)) || ((b_PCIInputClock == APCI1710_40MHZ) && (b_TimingUnit == 3) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 107UL)) || ((b_PCIInputClock == APCI1710_40MHZ) && (b_TimingUnit == 4) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 1UL))) { + /**************************/ + /* Test the board version */ + /**************************/ + + if (((b_PCIInputClock == APCI1710_40MHZ) && (devpriv->s_BoardInfos.b_BoardVersion > 0)) || (b_PCIInputClock != APCI1710_40MHZ)) { + /************************/ + /* Test the TOR version */ + /************************/ + + if (((b_PCIInputClock == APCI1710_40MHZ) && ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF) >= 0x3131)) || (b_PCIInputClock != APCI1710_40MHZ)) { + fpu_begin + (); + + /****************************************/ + /* Calculate the timer 0 division fator */ + /****************************************/ + + switch (b_TimingUnit) { + /******/ + /* ns */ + /******/ + + case 0: + + /******************/ + /* Timer 0 factor */ + /******************/ + + ul_TimerValue + = + (ULONG) + (ul_TimingInterval + * + (0.001 * b_PCIInputClock)); + + /*******************/ + /* Round the value */ + /*******************/ + + if ((double)((double)ul_TimingInterval * (0.001 * (double)b_PCIInputClock)) >= ((double)((double)ul_TimerValue + 0.5))) { + ul_TimerValue + = + ul_TimerValue + + + 1; + } + + /*****************************/ + /* Calculate the real timing */ + /*****************************/ + + ul_RealTimingInterval + = + (ULONG) + (ul_TimerValue + / + (0.001 * (double)b_PCIInputClock)); + d_RealTimingInterval + = + (double) + ul_TimerValue + / + (0.001 + * + (double) + b_PCIInputClock); + + if ((double)((double)ul_TimerValue / (0.001 * (double)b_PCIInputClock)) >= (double)((double)ul_RealTimingInterval + 0.5)) { + ul_RealTimingInterval + = + ul_RealTimingInterval + + + 1; + } + + ul_TimingInterval + = + ul_TimingInterval + - + 1; + ul_TimerValue + = + ul_TimerValue + - + 2; + if (b_PCIInputClock != APCI1710_40MHZ) { + ul_TimerValue + = + (ULONG) + ( + (double) + (ul_TimerValue) + * + 0.99392); + } + + break; + + /******/ + /* æs */ + /******/ + + case 1: + + /******************/ + /* Timer 0 factor */ + /******************/ + + ul_TimerValue + = + (ULONG) + (ul_TimingInterval + * + (1.0 * b_PCIInputClock)); + + /*******************/ + /* Round the value */ + /*******************/ + + if ((double)((double)ul_TimingInterval * (1.0 * (double)b_PCIInputClock)) >= ((double)((double)ul_TimerValue + 0.5))) { + ul_TimerValue + = + ul_TimerValue + + + 1; + } + + /*****************************/ + /* Calculate the real timing */ + /*****************************/ + + ul_RealTimingInterval + = + (ULONG) + (ul_TimerValue + / + (1.0 * (double)b_PCIInputClock)); + d_RealTimingInterval + = + (double) + ul_TimerValue + / + ( + (double) + 1.0 + * + (double) + b_PCIInputClock); + + if ((double)((double)ul_TimerValue / (1.0 * (double)b_PCIInputClock)) >= (double)((double)ul_RealTimingInterval + 0.5)) { + ul_RealTimingInterval + = + ul_RealTimingInterval + + + 1; + } + + ul_TimingInterval + = + ul_TimingInterval + - + 1; + ul_TimerValue + = + ul_TimerValue + - + 2; + if (b_PCIInputClock != APCI1710_40MHZ) { + ul_TimerValue + = + (ULONG) + ( + (double) + (ul_TimerValue) + * + 0.99392); + } + + break; + + /******/ + /* ms */ + /******/ + + case 2: + + /******************/ + /* Timer 0 factor */ + /******************/ + + ul_TimerValue + = + ul_TimingInterval + * + (1000 + * + b_PCIInputClock); + + /*******************/ + /* Round the value */ + /*******************/ + + if ((double)((double)ul_TimingInterval * (1000.0 * (double)b_PCIInputClock)) >= ((double)((double)ul_TimerValue + 0.5))) { + ul_TimerValue + = + ul_TimerValue + + + 1; + } + + /*****************************/ + /* Calculate the real timing */ + /*****************************/ + + ul_RealTimingInterval + = + (ULONG) + (ul_TimerValue + / + (1000.0 * (double)b_PCIInputClock)); + d_RealTimingInterval + = + (double) + ul_TimerValue + / + (1000.0 + * + (double) + b_PCIInputClock); + + if ((double)((double)ul_TimerValue / (1000.0 * (double)b_PCIInputClock)) >= (double)((double)ul_RealTimingInterval + 0.5)) { + ul_RealTimingInterval + = + ul_RealTimingInterval + + + 1; + } + + ul_TimingInterval + = + ul_TimingInterval + - + 1; + ul_TimerValue + = + ul_TimerValue + - + 2; + if (b_PCIInputClock != APCI1710_40MHZ) { + ul_TimerValue + = + (ULONG) + ( + (double) + (ul_TimerValue) + * + 0.99392); + } + + break; + + /*****/ + /* s */ + /*****/ + + case 3: + + /******************/ + /* Timer 0 factor */ + /******************/ + + ul_TimerValue + = + (ULONG) + (ul_TimingInterval + * + (1000000.0 + * + b_PCIInputClock)); + + /*******************/ + /* Round the value */ + /*******************/ + + if ((double)((double)ul_TimingInterval * (1000000.0 * (double)b_PCIInputClock)) >= ((double)((double)ul_TimerValue + 0.5))) { + ul_TimerValue + = + ul_TimerValue + + + 1; + } + + /*****************************/ + /* Calculate the real timing */ + /*****************************/ + + ul_RealTimingInterval + = + (ULONG) + (ul_TimerValue + / + (1000000.0 + * + (double) + b_PCIInputClock)); + d_RealTimingInterval + = + (double) + ul_TimerValue + / + (1000000.0 + * + (double) + b_PCIInputClock); + + if ((double)((double)ul_TimerValue / (1000000.0 * (double)b_PCIInputClock)) >= (double)((double)ul_RealTimingInterval + 0.5)) { + ul_RealTimingInterval + = + ul_RealTimingInterval + + + 1; + } + + ul_TimingInterval + = + ul_TimingInterval + - + 1; + ul_TimerValue + = + ul_TimerValue + - + 2; + if (b_PCIInputClock != APCI1710_40MHZ) { + ul_TimerValue + = + (ULONG) + ( + (double) + (ul_TimerValue) + * + 0.99392); + } + + break; + + /******/ + /* mn */ + /******/ + + case 4: + + /******************/ + /* Timer 0 factor */ + /******************/ + + ul_TimerValue + = + (ULONG) + ( + (ul_TimingInterval + * + 60) + * + (1000000.0 + * + b_PCIInputClock)); + + /*******************/ + /* Round the value */ + /*******************/ + + if ((double)((double)(ul_TimingInterval * 60.0) * (1000000.0 * (double)b_PCIInputClock)) >= ((double)((double)ul_TimerValue + 0.5))) { + ul_TimerValue + = + ul_TimerValue + + + 1; + } + + /*****************************/ + /* Calculate the real timing */ + /*****************************/ + + ul_RealTimingInterval + = + (ULONG) + (ul_TimerValue + / + (1000000.0 + * + (double) + b_PCIInputClock)) + / + 60; + d_RealTimingInterval + = + ( + (double) + ul_TimerValue + / + (0.001 * (double)b_PCIInputClock)) / 60.0; + + if ((double)(((double)ul_TimerValue / (1000000.0 * (double)b_PCIInputClock)) / 60.0) >= (double)((double)ul_RealTimingInterval + 0.5)) { + ul_RealTimingInterval + = + ul_RealTimingInterval + + + 1; + } + + ul_TimingInterval + = + ul_TimingInterval + - + 1; + ul_TimerValue + = + ul_TimerValue + - + 2; + if (b_PCIInputClock != APCI1710_40MHZ) { + ul_TimerValue + = + (ULONG) + ( + (double) + (ul_TimerValue) + * + 0.99392); + } + + break; + } + + fpu_end(); + + /****************************/ + /* Save the PCI input clock */ + /****************************/ + + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_ChronoModuleInfo. + b_PCIInputClock + = + b_PCIInputClock; + + /*************************/ + /* Save the timing unity */ + /*************************/ + + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_ChronoModuleInfo. + b_TimingUnit + = + b_TimingUnit; + + /************************/ + /* Save the base timing */ + /************************/ + + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_ChronoModuleInfo. + d_TimingInterval + = + d_RealTimingInterval; + + /****************************/ + /* Set the chronometer mode */ + /****************************/ + + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_ChronoModuleInfo. + dw_ConfigReg + = + dw_ModeArray + [b_ChronoMode]; + + /***********************/ + /* Test if 40 MHz used */ + /***********************/ + + if (b_PCIInputClock == APCI1710_40MHZ) { + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_ChronoModuleInfo. + dw_ConfigReg + = + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_ChronoModuleInfo. + dw_ConfigReg + | + 0x80; + } + + outl(devpriv->s_ModuleInfo[b_ModulNbr].s_ChronoModuleInfo.dw_ConfigReg, devpriv->s_BoardInfos.ui_Address + 16 + (64 * b_ModulNbr)); + + /***********************/ + /* Write timer 0 value */ + /***********************/ + + outl(ul_TimerValue, devpriv->s_BoardInfos.ui_Address + (64 * b_ModulNbr)); + + /*********************/ + /* Chronometer init. */ + /*********************/ + + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_ChronoModuleInfo. + b_ChronoInit + = + 1; + } else { + /***********************************************/ + /* TOR version error for 40MHz clock selection */ + /***********************************************/ + + DPRINTK("TOR version error for 40MHz clock selection\n"); + i_ReturnValue + = + -9; + } + } else { + /**************************************************************/ + /* You can not used the 40MHz clock selection wich this board */ + /**************************************************************/ + + DPRINTK("You can not used the 40MHz clock selection wich this board\n"); + i_ReturnValue = + -8; + } + } else { + /**********************************/ + /* Base timing selection is wrong */ + /**********************************/ + + DPRINTK("Base timing selection is wrong\n"); + i_ReturnValue = -7; + } + } // if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4)) + else { + /***********************************/ + /* Timing unity selection is wrong */ + /***********************************/ + + DPRINTK("Timing unity selection is wrong\n"); + i_ReturnValue = -6; + } // if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4)) + } // if ((b_PCIInputClock == APCI1710_30MHZ) || (b_PCIInputClock == APCI1710_33MHZ)) + else { + /*****************************************/ + /* The selected PCI input clock is wrong */ + /*****************************************/ + + DPRINTK("The selected PCI input clock is wrong\n"); + i_ReturnValue = -5; + } // if ((b_PCIInputClock == APCI1710_30MHZ) || (b_PCIInputClock == APCI1710_33MHZ)) + } // if (b_ChronoMode >= 0 && b_ChronoMode <= 7) + else { + /***************************************/ + /* Chronometer mode selection is wrong */ + /***************************************/ + + DPRINTK("Chronometer mode selection is wrong\n"); + i_ReturnValue = -4; + } // if (b_ChronoMode >= 0 && b_ChronoMode <= 7) + } else { + /******************************************/ + /* The module is not a Chronometer module */ + /******************************************/ + + DPRINTK("The module is not a Chronometer module\n"); + i_ReturnValue = -3; + } + } else { + /***********************/ + /* Module number error */ + /***********************/ + + DPRINTK("Module number error\n"); + i_ReturnValue = -2; + } + data[0] = ul_RealTimingInterval; + return (i_ReturnValue); +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_EnableChrono | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_CycleMode, | +| BYTE_ b_InterruptEnable) +INT i_APCI1710_InsnWriteEnableDisableChrono(struct comedi_device *dev, +struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task : Enable the chronometer from selected module | +| (b_ModulNbr). You must calling the | +| "i_APCI1710_InitChrono" function be for you call this | +| function. | +| If you enable the chronometer interrupt, the | +| chronometer generate a interrupt after the stop signal.| +| See function "i_APCI1710_SetBoardIntRoutineX" and the | +| Interrupt mask description chapter from this manual. | +| The b_CycleMode parameter determine if you will | +| measured a single or more cycle. + +| Disable the chronometer from selected module | +| (b_ModulNbr). If you disable the chronometer after a | +| start signal occur and you restart the chronometer | +| witch the " i_APCI1710_EnableChrono" function, if no | +| stop signal occur this start signal is ignored. ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr CR_AREF(chanspec) : Selected module number (0 to 3) | + data[0] ENABle/Disable chrono +| BYTE_ b_CycleMode : Selected the chronometer | +| data[1] acquisition mode | +| BYTE_ b_InterruptEnable : Enable or disable the | +| data[2] chronometer interrupt. | +| APCI1710_ENABLE: | +| Enable the chronometer | +| interrupt | +| APCI1710_DISABLE: | +| Disable the chronometer | +| interrupt | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: Module selection wrong | +| -3: The module is not a Chronometer module | +| -4: Chronometer not initialised see function | +| "i_APCI1710_InitChrono" | +| -5: Chronometer acquisition mode cycle is wrong | +| -6: Interrupt parameter is wrong | +| -7: Interrupt function not initialised. | +| See function "i_APCI1710_SetBoardIntRoutineX" + -8: data[0] wrong input | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_InsnWriteEnableDisableChrono(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) +{ + INT i_ReturnValue = 0; + BYTE b_ModulNbr, b_CycleMode, b_InterruptEnable, b_Action; + b_ModulNbr = CR_AREF(insn->chanspec); + b_Action = (BYTE) data[0]; + b_CycleMode = (BYTE) data[1]; + b_InterruptEnable = (BYTE) data[2]; + i_ReturnValue = insn->n; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) { + /***********************/ + /* Test if chronometer */ + /***********************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration[b_ModulNbr] & + 0xFFFF0000UL) == APCI1710_CHRONOMETER) { + /***********************************/ + /* Test if chronometer initialised */ + /***********************************/ + + if (devpriv->s_ModuleInfo[b_ModulNbr]. + s_ChronoModuleInfo.b_ChronoInit == 1) { + + switch (b_Action) { + + case APCI1710_ENABLE: + + /*********************************/ + /* Test the cycle mode parameter */ + /*********************************/ + + if ((b_CycleMode == APCI1710_SINGLE) + || (b_CycleMode == + APCI1710_CONTINUOUS)) { + /***************************/ + /* Test the interrupt flag */ + /***************************/ + + if ((b_InterruptEnable == + APCI1710_ENABLE) + || (b_InterruptEnable == + APCI1710_DISABLE)) + { + + /***************************/ + /* Save the interrupt flag */ + /***************************/ + + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_ChronoModuleInfo. + b_InterruptMask + = + b_InterruptEnable; + + /***********************/ + /* Save the cycle mode */ + /***********************/ + + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_ChronoModuleInfo. + b_CycleMode = + b_CycleMode; + + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_ChronoModuleInfo. + dw_ConfigReg = + (devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_ChronoModuleInfo. + dw_ConfigReg & + 0x8F) | ((1 & + b_InterruptEnable) + << 5) | ((1 & + b_CycleMode) + << 6) | 0x10; + + /*****************************/ + /* Test if interrupt enabled */ + /*****************************/ + + if (b_InterruptEnable == + APCI1710_ENABLE) + { + /****************************/ + /* Clear the interrupt flag */ + /****************************/ + + outl(devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_ChronoModuleInfo. + dw_ConfigReg, + devpriv-> + s_BoardInfos. + ui_Address + + 32 + + (64 * b_ModulNbr)); + devpriv->tsk_Current = current; // Save the current process task structure + } + + /***********************************/ + /* Enable or disable the interrupt */ + /* Enable the chronometer */ + /***********************************/ + + outl(devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_ChronoModuleInfo. + dw_ConfigReg, + devpriv-> + s_BoardInfos. + ui_Address + + 16 + + (64 * b_ModulNbr)); + + /*************************/ + /* Clear status register */ + /*************************/ + + outl(0, devpriv-> + s_BoardInfos. + ui_Address + + 36 + + (64 * b_ModulNbr)); + + } // if ((b_InterruptEnable == APCI1710_ENABLE) || (b_InterruptEnable == APCI1710_DISABLE)) + else { + /********************************/ + /* Interrupt parameter is wrong */ + /********************************/ + + DPRINTK("Interrupt parameter is wrong\n"); + i_ReturnValue = -6; + } // if ((b_InterruptEnable == APCI1710_ENABLE) || (b_InterruptEnable == APCI1710_DISABLE)) + } // if ((b_CycleMode == APCI1710_SINGLE) || (b_CycleMode == APCI1710_CONTINUOUS)) + else { + /***********************************************/ + /* Chronometer acquisition mode cycle is wrong */ + /***********************************************/ + + DPRINTK("Chronometer acquisition mode cycle is wrong\n"); + i_ReturnValue = -5; + } // if ((b_CycleMode == APCI1710_SINGLE) || (b_CycleMode == APCI1710_CONTINUOUS)) + break; + + case APCI1710_DISABLE: + + devpriv->s_ModuleInfo[b_ModulNbr]. + s_ChronoModuleInfo. + b_InterruptMask = 0; + + devpriv->s_ModuleInfo[b_ModulNbr]. + s_ChronoModuleInfo. + dw_ConfigReg = + devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_ChronoModuleInfo. + dw_ConfigReg & 0x2F; + + /***************************/ + /* Disable the interrupt */ + /* Disable the chronometer */ + /***************************/ + + outl(devpriv->s_ModuleInfo[b_ModulNbr]. + s_ChronoModuleInfo.dw_ConfigReg, + devpriv->s_BoardInfos. + ui_Address + 16 + + (64 * b_ModulNbr)); + + /***************************/ + /* Test if continuous mode */ + /***************************/ + + if (devpriv->s_ModuleInfo[b_ModulNbr]. + s_ChronoModuleInfo. + b_CycleMode == + APCI1710_CONTINUOUS) { + /*************************/ + /* Clear status register */ + /*************************/ + + outl(0, devpriv->s_BoardInfos. + ui_Address + 36 + + (64 * b_ModulNbr)); + } + break; + + default: + DPRINTK("Inputs wrong! Enable or Disable chrono\n"); + i_ReturnValue = -8; + } // switch ENABLE/DISABLE + } else { + /*******************************/ + /* Chronometer not initialised */ + /*******************************/ + + DPRINTK("Chronometer not initialised\n"); + i_ReturnValue = -4; + } + } else { + /******************************************/ + /* The module is not a Chronometer module */ + /******************************************/ + + DPRINTK("The module is not a Chronometer 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_InsnReadChrono(struct comedi_device *dev,struct comedi_subdevice *s, +struct comedi_insn *insn,unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task : Read functions for Timer | ++----------------------------------------------------------------------------+ +| Input Parameters : ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_InsnReadChrono(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + BYTE b_ReadType; + INT i_ReturnValue = insn->n; + + b_ReadType = CR_CHAN(insn->chanspec); + + switch (b_ReadType) { + case APCI1710_CHRONO_PROGRESS_STATUS: + i_ReturnValue = i_APCI1710_GetChronoProgressStatus(dev, + (BYTE) CR_AREF(insn->chanspec), (PBYTE) & data[0]); + break; + + case APCI1710_CHRONO_READVALUE: + i_ReturnValue = i_APCI1710_ReadChronoValue(dev, + (BYTE) CR_AREF(insn->chanspec), + (UINT) insn->unused[0], + (PBYTE) & data[0], (PULONG) & data[1]); + break; + + case APCI1710_CHRONO_CONVERTVALUE: + i_ReturnValue = i_APCI1710_ConvertChronoValue(dev, + (BYTE) CR_AREF(insn->chanspec), + (ULONG) insn->unused[0], + (PULONG) & data[0], + (PBYTE) & data[1], + (PBYTE) & data[2], + (PUINT) & data[3], + (PUINT) & data[4], (PUINT) & data[5]); + break; + + case APCI1710_CHRONO_READINTERRUPT: + printk("In Chrono Read Interrupt\n"); + + 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; + break; + + default: + printk("ReadType Parameter wrong\n"); + } + + if (i_ReturnValue >= 0) + i_ReturnValue = insn->n; + return (i_ReturnValue); + +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_GetChronoProgressStatus | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| PBYTE_ pb_ChronoStatus) | ++----------------------------------------------------------------------------+ +| Task : Return the chronometer status (pb_ChronoStatus) from | +| selected chronometer module (b_ModulNbr). | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Selected module number (0 to 3) | ++----------------------------------------------------------------------------+ +| Output Parameters : PULONG_ pb_ChronoStatus : Return the chronometer | +| status. | +| 0 : Measurement not started.| +| No start signal occur. | +| 1 : Measurement started. | +| A start signal occur. | +| 2 : Measurement stopped. | +| A stop signal occur. | +| The measurement is | +| terminate. | +| 3: A overflow occur. You | +| must change the base | +| timing witch the | +| function | +| "i_APCI1710_InitChrono" | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: Module selection wrong | +| -3: The module is not a Chronometer module | +| -4: Chronometer not initialised see function | +| "i_APCI1710_InitChrono" | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_GetChronoProgressStatus(struct comedi_device * dev, + BYTE b_ModulNbr, PBYTE pb_ChronoStatus) +{ + INT i_ReturnValue = 0; + DWORD dw_Status; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) { + /***********************/ + /* Test if chronometer */ + /***********************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration[b_ModulNbr] & + 0xFFFF0000UL) == APCI1710_CHRONOMETER) { + /***********************************/ + /* Test if chronometer initialised */ + /***********************************/ + + if (devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_ChronoModuleInfo.b_ChronoInit == 1) { + + dw_Status = inl(devpriv->s_BoardInfos. + ui_Address + 8 + (64 * b_ModulNbr)); + + /********************/ + /* Test if overflow */ + /********************/ + + if ((dw_Status & 8) == 8) { + /******************/ + /* Overflow occur */ + /******************/ + + *pb_ChronoStatus = 3; + } // if ((dw_Status & 8) == 8) + else { + /*******************************/ + /* Test if measurement stopped */ + /*******************************/ + + if ((dw_Status & 2) == 2) { + /***********************/ + /* A stop signal occur */ + /***********************/ + + *pb_ChronoStatus = 2; + } // if ((dw_Status & 2) == 2) + else { + /*******************************/ + /* Test if measurement started */ + /*******************************/ + + if ((dw_Status & 1) == 1) { + /************************/ + /* A start signal occur */ + /************************/ + + *pb_ChronoStatus = 1; + } // if ((dw_Status & 1) == 1) + else { + /***************************/ + /* Measurement not started */ + /***************************/ + + *pb_ChronoStatus = 0; + } // if ((dw_Status & 1) == 1) + } // if ((dw_Status & 2) == 2) + } // if ((dw_Status & 8) == 8) + } else { + /*******************************/ + /* Chronometer not initialised */ + /*******************************/ + DPRINTK("Chronometer not initialised\n"); + i_ReturnValue = -4; + } + } else { + /******************************************/ + /* The module is not a Chronometer module */ + /******************************************/ + DPRINTK("The module is not a Chronometer 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_ReadChronoValue | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| UINT_ ui_TimeOut, | +| PBYTE_ pb_ChronoStatus, | +| PULONG_ pul_ChronoValue) | ++----------------------------------------------------------------------------+ +| Task : Return the chronometer status (pb_ChronoStatus) and the| +| timing value (pul_ChronoValue) after a stop signal | +| occur from selected chronometer module (b_ModulNbr). | +| This function are only avaible if you have disabled | +| the interrupt functionality. See function | +| "i_APCI1710_EnableChrono" and the Interrupt mask | +| description chapter. | +| You can test the chronometer status witch the | +| "i_APCI1710_GetChronoProgressStatus" function. | +| | +| The returned value from pul_ChronoValue parameter is | +| not real measured timing. | +| You must used the "i_APCI1710_ConvertChronoValue" | +| function or make this operation for calculate the | +| timing: | +| | +| Timing = pul_ChronoValue * pul_RealTimingInterval. | +| | +| pul_RealTimingInterval is the returned parameter from | +| "i_APCI1710_InitChrono" function and the time unity is | +| the b_TimingUnit from "i_APCI1710_InitChrono" function| ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Selected module number (0 to 3) | ++----------------------------------------------------------------------------+ +| Output Parameters : PULONG_ pb_ChronoStatus : Return the chronometer | +| status. | +| 0 : Measurement not started.| +| No start signal occur. | +| 1 : Measurement started. | +| A start signal occur. | +| 2 : Measurement stopped. | +| A stop signal occur. | +| The measurement is | +| terminate. | +| 3: A overflow occur. You | +| must change the base | +| timing witch the | +| function | +| "i_APCI1710_InitChrono" | +| PULONG pul_ChronoValue : Chronometer timing value. | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: Module selection wrong | +| -3: The module is not a Chronometer module | +| -4: Chronometer not initialised see function | +| "i_APCI1710_InitChrono" | +| -5: Timeout parameter is wrong (0 to 65535) | +| -6: Interrupt routine installed. You can not read | +| directly the chronometer measured timing. | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_ReadChronoValue(struct comedi_device * dev, + BYTE b_ModulNbr, + UINT ui_TimeOut, PBYTE pb_ChronoStatus, PULONG pul_ChronoValue) +{ + INT i_ReturnValue = 0; + DWORD dw_Status; + DWORD dw_TimeOut = 0; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) { + /***********************/ + /* Test if chronometer */ + /***********************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration[b_ModulNbr] & + 0xFFFF0000UL) == APCI1710_CHRONOMETER) { + /***********************************/ + /* Test if chronometer initialised */ + /***********************************/ + + if (devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_ChronoModuleInfo.b_ChronoInit == 1) { + /*****************************/ + /* Test the timout parameter */ + /*****************************/ + + if ((ui_TimeOut >= 0) + && (ui_TimeOut <= 65535UL)) { + + for (;;) { + /*******************/ + /* Read the status */ + /*******************/ + + dw_Status = + inl(devpriv-> + s_BoardInfos. + ui_Address + 8 + + (64 * b_ModulNbr)); + + /********************/ + /* Test if overflow */ + /********************/ + + if ((dw_Status & 8) == 8) { + /******************/ + /* Overflow occur */ + /******************/ + + *pb_ChronoStatus = 3; + + /***************************/ + /* Test if continuous mode */ + /***************************/ + + if (devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_ChronoModuleInfo. + b_CycleMode == + APCI1710_CONTINUOUS) + { + /*************************/ + /* Clear status register */ + /*************************/ + + outl(0, devpriv->s_BoardInfos.ui_Address + 36 + (64 * b_ModulNbr)); + } + + break; + } // if ((dw_Status & 8) == 8) + else { + /*******************************/ + /* Test if measurement stopped */ + /*******************************/ + + if ((dw_Status & 2) == + 2) { + /***********************/ + /* A stop signal occur */ + /***********************/ + + *pb_ChronoStatus + = 2; + + /***************************/ + /* Test if continnous mode */ + /***************************/ + + if (devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_ChronoModuleInfo. + b_CycleMode + == + APCI1710_CONTINUOUS) + { + /*************************/ + /* Clear status register */ + /*************************/ + + outl(0, devpriv->s_BoardInfos.ui_Address + 36 + (64 * b_ModulNbr)); + } + break; + } // if ((dw_Status & 2) == 2) + else { + /*******************************/ + /* Test if measurement started */ + /*******************************/ + + if ((dw_Status & 1) == 1) { + /************************/ + /* A start signal occur */ + /************************/ + + *pb_ChronoStatus + = + 1; + } // if ((dw_Status & 1) == 1) + else { + /***************************/ + /* Measurement not started */ + /***************************/ + + *pb_ChronoStatus + = + 0; + } // if ((dw_Status & 1) == 1) + } // if ((dw_Status & 2) == 2) + } // if ((dw_Status & 8) == 8) + + if (dw_TimeOut == ui_TimeOut) { + /*****************/ + /* Timeout occur */ + /*****************/ + + break; + } else { + /*************************/ + /* Increment the timeout */ + /*************************/ + + dw_TimeOut = + dw_TimeOut + 1; + mdelay(1000); + + } + } // for (;;) + + /*****************************/ + /* Test if stop signal occur */ + /*****************************/ + + if (*pb_ChronoStatus == 2) { + /**********************************/ + /* Read the measured timing value */ + /**********************************/ + + *pul_ChronoValue = + inl(devpriv-> + s_BoardInfos. + ui_Address + 4 + + (64 * b_ModulNbr)); + + if (*pul_ChronoValue != 0) { + *pul_ChronoValue = + *pul_ChronoValue + - 1; + } + } else { + /*************************/ + /* Test if timeout occur */ + /*************************/ + + if ((*pb_ChronoStatus != 3) + && (dw_TimeOut == + ui_TimeOut) + && (ui_TimeOut != 0)) { + /*****************/ + /* Timeout occur */ + /*****************/ + + *pb_ChronoStatus = 4; + } + } + + } else { + /******************************/ + /* Timeout parameter is wrong */ + /******************************/ + DPRINTK("Timeout parameter is wrong\n"); + i_ReturnValue = -5; + } + } else { + /*******************************/ + /* Chronometer not initialised */ + /*******************************/ + DPRINTK("Chronometer not initialised\n"); + i_ReturnValue = -4; + } + } else { + /******************************************/ + /* The module is not a Chronometer module */ + /******************************************/ + DPRINTK("The module is not a Chronometer 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_ConvertChronoValue | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| ULONG_ ul_ChronoValue, | +| PULONG_ pul_Hour, | +| PBYTE_ pb_Minute, | +| PBYTE_ pb_Second, | +| PUINT_ pui_MilliSecond, | +| PUINT_ pui_MicroSecond, | +| PUINT_ pui_NanoSecond) | ++----------------------------------------------------------------------------+ +| Task : Convert the chronometer measured timing | +| (ul_ChronoValue) in to h, mn, s, ms, µs, ns. | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Selected module number (0 to 3)| +| ULONG_ ul_ChronoValue : Measured chronometer timing | +| value. | +| See"i_APCI1710_ReadChronoValue"| ++----------------------------------------------------------------------------+ +| Output Parameters : PULONG_ pul_Hour : Chronometer timing hour | +| PBYTE_ pb_Minute : Chronometer timing minute | +| PBYTE_ pb_Second : Chronometer timing second | +| PUINT_ pui_MilliSecond : Chronometer timing mini | +| second | +| PUINT_ pui_MicroSecond : Chronometer timing micro | +| second | +| PUINT_ pui_NanoSecond : Chronometer timing nano | +| second | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: Module selection wrong | +| -3: The module is not a Chronometer module | +| -4: Chronometer not initialised see function | +| "i_APCI1710_InitChrono" | ++----------------------------------------------------------------------------+ +*/ + +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) +{ + INT i_ReturnValue = 0; + double d_Hour; + double d_Minute; + double d_Second; + double d_MilliSecond; + double d_MicroSecond; + double d_NanoSecond; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) { + /***********************/ + /* Test if chronometer */ + /***********************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration[b_ModulNbr] & + 0xFFFF0000UL) == APCI1710_CHRONOMETER) { + /***********************************/ + /* Test if chronometer initialised */ + /***********************************/ + + if (devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_ChronoModuleInfo.b_ChronoInit == 1) { + fpu_begin(); + + d_Hour = (double)ul_ChronoValue *(double) + devpriv->s_ModuleInfo[b_ModulNbr]. + s_ChronoModuleInfo.d_TimingInterval; + + switch (devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_ChronoModuleInfo.b_TimingUnit) { + case 0: + d_Hour = d_Hour / (double)1000.0; + + case 1: + d_Hour = d_Hour / (double)1000.0; + + case 2: + d_Hour = d_Hour / (double)1000.0; + + case 3: + d_Hour = d_Hour / (double)60.0; + + case 4: + /**********************/ + /* Calculate the hour */ + /**********************/ + + d_Hour = d_Hour / (double)60.0; + *pul_Hour = (ULONG) d_Hour; + + /************************/ + /* Calculate the minute */ + /************************/ + + d_Minute = d_Hour - *pul_Hour; + d_Minute = d_Minute * 60; + *pb_Minute = (BYTE) d_Minute; + + /************************/ + /* Calculate the second */ + /************************/ + + d_Second = d_Minute - *pb_Minute; + d_Second = d_Second * 60; + *pb_Second = (BYTE) d_Second; + + /*****************************/ + /* Calculate the mini second */ + /*****************************/ + + d_MilliSecond = d_Second - *pb_Second; + d_MilliSecond = d_MilliSecond * 1000; + *pui_MilliSecond = (UINT) d_MilliSecond; + + /******************************/ + /* Calculate the micro second */ + /******************************/ + + d_MicroSecond = + d_MilliSecond - + *pui_MilliSecond; + d_MicroSecond = d_MicroSecond * 1000; + *pui_MicroSecond = (UINT) d_MicroSecond; + + /******************************/ + /* Calculate the micro second */ + /******************************/ + + d_NanoSecond = + d_MicroSecond - + *pui_MicroSecond; + d_NanoSecond = d_NanoSecond * 1000; + *pui_NanoSecond = (UINT) d_NanoSecond; + break; + } + + fpu_end(); + } else { + /*******************************/ + /* Chronometer not initialised */ + /*******************************/ + DPRINTK("Chronometer not initialised\n"); + i_ReturnValue = -4; + } + } else { + /******************************************/ + /* The module is not a Chronometer module */ + /******************************************/ + DPRINTK("The module is not a Chronometer 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_InsnBitsChronoDigitalIO(struct comedi_device *dev,struct comedi_subdevice *s, + struct comedi_insn *insn,unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task : Sets the output witch has been passed with the | +| parameter b_Channel. Setting an output means setting an| +| output high. | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Selected module number (0 to 3)| +| BYTE_ b_OutputChannel : Selection from digital output | +| CR_CHAN() channel (0 to 2) | +| 0 : Channel H | +| 1 : Channel A | +| 2 : Channel B | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: Module selection wrong | +| -3: The module is not a Chronometer module | +| -4: The selected digital output is wrong | +| -5: Chronometer not initialised see function | +| "i_APCI1710_InitChrono" | ++----------------------------------------------------------------------------+ +*/ + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_SetChronoChlOff | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_OutputChannel) | ++----------------------------------------------------------------------------+ +| Task : Resets the output witch has been passed with the | +| parameter b_Channel. Resetting an output means setting | +| an output low. | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 + data[0] : Chl ON, Chl OFF , Chl Read , Port Read + +| BYTE_ b_ModulNbr CR_AREF : Selected module number (0 to 3)| +| BYTE_ b_OutputChannel CR_CHAN : Selection from digital output | +| channel (0 to 2) | +| 0 : Channel H | +| 1 : Channel A | +| 2 : Channel B | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: Module selection wrong | +| -3: The module is not a Chronometer module | +| -4: The selected digital output is wrong | +| -5: Chronometer not initialised see function | +| "i_APCI1710_InitChrono" | ++----------------------------------------------------------------------------+ +*/ + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_ReadChronoChlValue | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_InputChannel, | +| PBYTE_ pb_ChannelStatus) | ++----------------------------------------------------------------------------+ +| Task : Return the status from selected digital input | +| (b_InputChannel) from selected chronometer | +| module (b_ModulNbr). | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Selected module number (0 to 3)| +| BYTE_ b_InputChannel : Selection from digital input | +| channel (0 to 2) | +| CR_CHAN() 0 : Channel E | +| 1 : Channel F | +| 2 : Channel G | ++----------------------------------------------------------------------------+ +| Output Parameters : PBYTE_ pb_ChannelStatus : Digital input channel status.| +| data[0] 0 : Channel is not active | +| 1 : Channel is active | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: Module selection wrong | +| -3: The module is not a Chronometer module | +| -4: The selected digital input is wrong | +| -5: Chronometer not initialised see function | +| "i_APCI1710_InitChrono" | ++----------------------------------------------------------------------------+ +*/ + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_ReadChronoPortValue | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| PBYTE_ pb_PortValue) | ++----------------------------------------------------------------------------+ +| Task : Return the status from digital inputs port from | +| selected (b_ModulNbr) chronometer module. | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Selected module number (0 to 3)| ++----------------------------------------------------------------------------+ +| Output Parameters : PBYTE_ pb_PortValue : Digital inputs port status. +| data[0] ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: Module selection wrong | +| -3: The module is not a Chronometer module | +| -4: Chronometer not initialised see function | +| "i_APCI1710_InitChrono" | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_InsnBitsChronoDigitalIO(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) +{ + INT i_ReturnValue = 0; + BYTE b_ModulNbr, b_OutputChannel, b_InputChannel, b_IOType; + DWORD dw_Status; + PBYTE pb_ChannelStatus; + PBYTE pb_PortValue; + + b_ModulNbr = CR_AREF(insn->chanspec); + i_ReturnValue = insn->n; + b_IOType = (BYTE) data[0]; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) { + /***********************/ + /* Test if chronometer */ + /***********************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration[b_ModulNbr] & + 0xFFFF0000UL) == APCI1710_CHRONOMETER) { + /***********************************/ + /* Test if chronometer initialised */ + /***********************************/ + + if (devpriv->s_ModuleInfo[b_ModulNbr]. + s_ChronoModuleInfo.b_ChronoInit == 1) { + /***********************************/ + /* Test the digital output channel */ + /***********************************/ + switch (b_IOType) { + + case APCI1710_CHRONO_SET_CHANNELOFF: + + b_OutputChannel = + (BYTE) CR_CHAN(insn->chanspec); + if (b_OutputChannel <= 2) { + + outl(0, devpriv->s_BoardInfos. + ui_Address + 20 + + (b_OutputChannel * 4) + + (64 * b_ModulNbr)); + } // if ((b_OutputChannel >= 0) && (b_OutputChannel <= 2)) + else { + /****************************************/ + /* The selected digital output is wrong */ + /****************************************/ + + DPRINTK("The selected digital output is wrong\n"); + i_ReturnValue = -4; + + } // if ((b_OutputChannel >= 0) && (b_OutputChannel <= 2)) + + break; + + case APCI1710_CHRONO_SET_CHANNELON: + + b_OutputChannel = + (BYTE) CR_CHAN(insn->chanspec); + if (b_OutputChannel <= 2) { + + outl(1, devpriv->s_BoardInfos. + ui_Address + 20 + + (b_OutputChannel * 4) + + (64 * b_ModulNbr)); + } // if ((b_OutputChannel >= 0) && (b_OutputChannel <= 2)) + else { + /****************************************/ + /* The selected digital output is wrong */ + /****************************************/ + + DPRINTK("The selected digital output is wrong\n"); + i_ReturnValue = -4; + + } // if ((b_OutputChannel >= 0) && (b_OutputChannel <= 2)) + + break; + + case APCI1710_CHRONO_READ_CHANNEL: + /**********************************/ + /* Test the digital input channel */ + /**********************************/ + pb_ChannelStatus = (PBYTE) & data[0]; + b_InputChannel = + (BYTE) CR_CHAN(insn->chanspec); + + if (b_InputChannel <= 2) { + + dw_Status = + inl(devpriv-> + s_BoardInfos. + ui_Address + 12 + + (64 * b_ModulNbr)); + + *pb_ChannelStatus = + (BYTE) (((dw_Status >> + b_InputChannel) + & 1) ^ 1); + } // if ((b_InputChannel >= 0) && (b_InputChannel <= 2)) + else { + /***************************************/ + /* The selected digital input is wrong */ + /***************************************/ + + DPRINTK("The selected digital input is wrong\n"); + i_ReturnValue = -4; + } // if ((b_InputChannel >= 0) && (b_InputChannel <= 2)) + + break; + + case APCI1710_CHRONO_READ_PORT: + + pb_PortValue = (PBYTE) & data[0]; + + dw_Status = + inl(devpriv->s_BoardInfos. + ui_Address + 12 + + (64 * b_ModulNbr)); + + *pb_PortValue = + (BYTE) ((dw_Status & 0x7) ^ 7); + break; + } + } else { + /*******************************/ + /* Chronometer not initialised */ + /*******************************/ + + DPRINTK("Chronometer not initialised\n"); + i_ReturnValue = -5; + } + } else { + /******************************************/ + /* The module is not a Chronometer module */ + /******************************************/ + + DPRINTK("The module is not a Chronometer module\n"); + i_ReturnValue = -3; + } + } else { + /***********************/ + /* Module number error */ + /***********************/ + + DPRINTK("Module number error\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); +} diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.h new file mode 100644 index 000000000000..26b50cefee5a --- /dev/null +++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.h @@ -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); diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c new file mode 100644 index 000000000000..8be27aedaaf5 --- /dev/null +++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c @@ -0,0 +1,1020 @@ +/** +@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 : DIG_IO.C | Version : 2.96 | + +-------------------------------+---------------------------------------+ + | Project manager: Eric Stolz | Date : 02/12/2002 | + +-----------------------------------------------------------------------+ + | Description : APCI-1710 digital I/O module | + | | + | | + +-----------------------------------------------------------------------+ + | UPDATES | + +-----------------------------------------------------------------------+ + | Date | Author | Description of updates | + +----------+-----------+------------------------------------------------+ + | 16/06/98 | S. Weber | Digital input / output implementation | + |----------|-----------|------------------------------------------------| + | 08/05/00 | Guinot C | - 0400/0228 All Function in RING 0 | + | | | available | + +-----------------------------------------------------------------------+ + | | | | + | | | | + +-----------------------------------------------------------------------+ +*/ + +/* ++----------------------------------------------------------------------------+ +| Included files | ++----------------------------------------------------------------------------+ +*/ +#include "APCI1710_Dig_io.h" + +/* ++----------------------------------------------------------------------------+ +| Function Name : INT i_APCI1710_InsnConfigDigitalIO(struct comedi_device *dev, | +| struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data)| ++----------------------------------------------------------------------------+ +| Task : Configure the digital I/O operating mode from selected | +| module (b_ModulNbr). You must calling this function be| +| for you call any other function witch access of digital| +| I/O. | ++----------------------------------------------------------------------------+ +| Input Parameters : | +| BYTE_ b_ModulNbr data[0]: Module number to | +| configure (0 to 3) | +| BYTE_ b_ChannelAMode data[1] : Channel A mode selection | +| 0 : Channel used for digital | +| input | +| 1 : Channel used for digital | +| output | +| BYTE_ b_ChannelBMode data[2] : Channel B mode selection | +| 0 : Channel used for digital | +| input | +| 1 : Channel used for digital | +| output | + data[0] memory on/off +Activates and deactivates the digital output memory. + After having | +| called up this function with memory on,the output you have previously| +| activated with the function are not reset ++----------------------------------------------------------------------------+ +| 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 digital I/O module | +| -4: Bi-directional channel A configuration error | +| -5: Bi-directional channel B configuration error | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_InsnConfigDigitalIO(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + BYTE b_ModulNbr, b_ChannelAMode, b_ChannelBMode; + BYTE b_MemoryOnOff, b_ConfigType; + INT i_ReturnValue = 0; + DWORD dw_WriteConfig = 0; + + b_ModulNbr = (BYTE) CR_AREF(insn->chanspec); + b_ConfigType = (BYTE) data[0]; // Memory or Init + b_ChannelAMode = (BYTE) data[1]; + b_ChannelBMode = (BYTE) data[2]; + b_MemoryOnOff = (BYTE) data[1]; // if memory operation + i_ReturnValue = insn->n; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr >= 4) { + DPRINTK("Module Number invalid\n"); + i_ReturnValue = -2; + return i_ReturnValue; + } + switch (b_ConfigType) { + case APCI1710_DIGIO_MEMORYONOFF: + + if (b_MemoryOnOff) // If Memory ON + { + /****************************/ + /* Set the output memory on */ + /****************************/ + + devpriv->s_ModuleInfo[b_ModulNbr]. + s_DigitalIOInfo.b_OutputMemoryEnabled = 1; + + /***************************/ + /* Clear the output memory */ + /***************************/ + devpriv->s_ModuleInfo[b_ModulNbr]. + s_DigitalIOInfo.dw_OutputMemory = 0; + } else // If memory off + { + /*****************************/ + /* Set the output memory off */ + /*****************************/ + + devpriv->s_ModuleInfo[b_ModulNbr]. + s_DigitalIOInfo.b_OutputMemoryEnabled = 0; + } + break; + + case APCI1710_DIGIO_INIT: + + /*******************************/ + /* Test if digital I/O counter */ + /*******************************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration[b_ModulNbr] & + 0xFFFF0000UL) == APCI1710_DIGITAL_IO) { + + /***************************************************/ + /* Test the bi-directional channel A configuration */ + /***************************************************/ + + if ((b_ChannelAMode == 0) || (b_ChannelAMode == 1)) { + /***************************************************/ + /* Test the bi-directional channel B configuration */ + /***************************************************/ + + if ((b_ChannelBMode == 0) + || (b_ChannelBMode == 1)) { + devpriv->s_ModuleInfo[b_ModulNbr]. + s_DigitalIOInfo.b_DigitalInit = + 1; + + /********************************/ + /* Save channel A configuration */ + /********************************/ + + devpriv->s_ModuleInfo[b_ModulNbr]. + s_DigitalIOInfo. + b_ChannelAMode = b_ChannelAMode; + + /********************************/ + /* Save channel B configuration */ + /********************************/ + + devpriv->s_ModuleInfo[b_ModulNbr]. + s_DigitalIOInfo. + b_ChannelBMode = b_ChannelBMode; + + /*****************************************/ + /* Set the channel A and B configuration */ + /*****************************************/ + + dw_WriteConfig = + (DWORD) (b_ChannelAMode | + (b_ChannelBMode * 2)); + + /***************************/ + /* Write the configuration */ + /***************************/ + + outl(dw_WriteConfig, + devpriv->s_BoardInfos. + ui_Address + 4 + + (64 * b_ModulNbr)); + + } else { + /************************************************/ + /* Bi-directional channel B configuration error */ + /************************************************/ + DPRINTK("Bi-directional channel B configuration error\n"); + i_ReturnValue = -5; + } + + } else { + /************************************************/ + /* Bi-directional channel A configuration error */ + /************************************************/ + DPRINTK("Bi-directional channel A configuration error\n"); + i_ReturnValue = -4; + + } + + } else { + /******************************************/ + /* The module is not a digital I/O module */ + /******************************************/ + DPRINTK("The module is not a digital I/O module\n"); + i_ReturnValue = -3; + } + } // end of Switch + printk("Return Value %d\n", i_ReturnValue); + return i_ReturnValue; +} + +/* ++----------------------------------------------------------------------------+ +| INPUT FUNCTIONS | ++----------------------------------------------------------------------------+ +*/ + +/* ++----------------------------------------------------------------------------+ + +|INT i_APCI1710_InsnReadDigitalIOChlValue(struct comedi_device *dev,comedi_subdevice +*s, struct comedi_insn *insn,unsigned int *data) + ++----------------------------------------------------------------------------+ +| Task : Read the status from selected digital I/O digital input| +| (b_InputChannel) | ++----------------------------------------------------------------------------| + + +| +| BYTE_ b_ModulNbr CR_AREF(chanspec) : Selected module number | +| (0 to 3) | +| BYTE_ b_InputChannel CR_CHAN(chanspec) : Selection from digital | +| input ( 0 to 6) | +| 0 : Channel C | +| 1 : Channel D | +| 2 : Channel E | +| 3 : Channel F | +| 4 : Channel G | +| 5 : Channel A | +| 6 : Channel B + + + | ++----------------------------------------------------------------------------+ +| Output Parameters : data[0] : Digital input channel | +| 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 digital I/O module | +| -4: The selected digital I/O digital input is wrong | +| -5: Digital I/O not initialised | +| -6: The digital channel A is used for output | +| -7: The digital channel B is used for output | ++----------------------------------------------------------------------------+ +*/ + +//_INT_ i_APCI1710_ReadDigitalIOChlValue (BYTE_ b_BoardHandle, +// BYTE_ b_ModulNbr, +// BYTE_ b_InputChannel, +// +// PBYTE_ pb_ChannelStatus) +INT i_APCI1710_InsnReadDigitalIOChlValue(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, b_InputChannel; + PBYTE pb_ChannelStatus; + b_ModulNbr = (BYTE) CR_AREF(insn->chanspec); + b_InputChannel = (BYTE) CR_CHAN(insn->chanspec); + data[0] = 0; + pb_ChannelStatus = (PBYTE) & data[0]; + i_ReturnValue = insn->n; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) { + /*******************************/ + /* Test if digital I/O counter */ + /*******************************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration[b_ModulNbr] & + 0xFFFF0000UL) == APCI1710_DIGITAL_IO) { + /******************************************/ + /* Test the digital imnput channel number */ + /******************************************/ + + if (b_InputChannel <= 6) { + /**********************************************/ + /* Test if the digital I/O module initialised */ + /**********************************************/ + + if (devpriv->s_ModuleInfo[b_ModulNbr]. + s_DigitalIOInfo.b_DigitalInit == 1) { + /**********************************/ + /* Test if channel A or channel B */ + /**********************************/ + + if (b_InputChannel > 4) { + /*********************/ + /* Test if channel A */ + /*********************/ + + if (b_InputChannel == 5) { + /***************************/ + /* Test the channel A mode */ + /***************************/ + + if (devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_DigitalIOInfo. + b_ChannelAMode + != 0) { + /********************************************/ + /* The digital channel A is used for output */ + /********************************************/ + + i_ReturnValue = + -6; + } + } // if (b_InputChannel == 5) + else { + /***************************/ + /* Test the channel B mode */ + /***************************/ + + if (devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_DigitalIOInfo. + b_ChannelBMode + != 0) { + /********************************************/ + /* The digital channel B is used for output */ + /********************************************/ + + i_ReturnValue = + -7; + } + } // if (b_InputChannel == 5) + } // if (b_InputChannel > 4) + + /***********************/ + /* Test if error occur */ + /***********************/ + + if (i_ReturnValue >= 0) { + /**************************/ + /* Read all digital input */ + /**************************/ + + //INPDW (ps_APCI1710Variable-> + // s_Board [b_BoardHandle]. + // s_BoardInfos. + // ui_Address + (64 * b_ModulNbr), + // &dw_StatusReg); + + dw_StatusReg = + inl(devpriv-> + s_BoardInfos. + ui_Address + + (64 * b_ModulNbr)); + + *pb_ChannelStatus = + (BYTE) ((dw_StatusReg ^ + 0x1C) >> + b_InputChannel) & 1; + + } // if (i_ReturnValue == 0) + } else { + /*******************************/ + /* Digital I/O not initialised */ + /*******************************/ + DPRINTK("Digital I/O not initialised\n"); + i_ReturnValue = -5; + } + } else { + /********************************/ + /* Selected digital input error */ + /********************************/ + DPRINTK("Selected digital input error\n"); + i_ReturnValue = -4; + } + } else { + /******************************************/ + /* The module is not a digital I/O module */ + /******************************************/ + DPRINTK("The module is not a digital I/O module\n"); + i_ReturnValue = -3; + } + } else { + /***********************/ + /* Module number error */ + /***********************/ + DPRINTK("Module number error\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); +} + +/* ++----------------------------------------------------------------------------+ +| OUTPUT FUNCTIONS | ++----------------------------------------------------------------------------+ +*/ + +/* ++----------------------------------------------------------------------------+ +| Function Name : INT i_APCI1710_InsnWriteDigitalIOChlOnOff(comedi_device +|*dev,struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data) + ++----------------------------------------------------------------------------+ +| Task : Sets or resets the output witch has been passed with the | +| parameter b_Channel. Setting an output means setting | +| an ouput high. | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr (aref ) : Selected module number (0 to 3)| +| BYTE_ b_OutputChannel (CR_CHAN) : Selection from digital output | +| channel (0 to 2) | +| 0 : Channel H | +| 1 : Channel A | +| 2 : Channel B | ++----------------------------------------------------------------------------+ +| 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 digital I/O module | +| -4: The selected digital output is wrong | +| -5: digital I/O not initialised see function | +| " i_APCI1710_InitDigitalIO" | +| -6: The digital channel A is used for input | +| -7: The digital channel B is used for input + -8: Digital Output Memory OFF. | +| Use previously the function | +| "i_APCI1710_SetDigitalIOMemoryOn". | ++----------------------------------------------------------------------------+ +*/ + +//_INT_ i_APCI1710_SetDigitalIOChlOn (BYTE_ b_BoardHandle, +// BYTE_ b_ModulNbr, +// BYTE_ b_OutputChannel) +INT i_APCI1710_InsnWriteDigitalIOChlOnOff(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) +{ + INT i_ReturnValue = 0; + DWORD dw_WriteValue = 0; + BYTE b_ModulNbr, b_OutputChannel; + i_ReturnValue = insn->n; + b_ModulNbr = CR_AREF(insn->chanspec); + b_OutputChannel = CR_CHAN(insn->chanspec); + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) { + /*******************************/ + /* Test if digital I/O counter */ + /*******************************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration[b_ModulNbr] & + 0xFFFF0000UL) == APCI1710_DIGITAL_IO) { + /**********************************************/ + /* Test if the digital I/O module initialised */ + /**********************************************/ + + if (devpriv->s_ModuleInfo[b_ModulNbr]. + s_DigitalIOInfo.b_DigitalInit == 1) { + /******************************************/ + /* Test the digital output channel number */ + /******************************************/ + + switch (b_OutputChannel) { + /*************/ + /* Channel H */ + /*************/ + + case 0: + break; + + /*************/ + /* Channel A */ + /*************/ + + case 1: + if (devpriv->s_ModuleInfo[b_ModulNbr]. + s_DigitalIOInfo. + b_ChannelAMode != 1) { + /*******************************************/ + /* The digital channel A is used for input */ + /*******************************************/ + + i_ReturnValue = -6; + } + break; + + /*************/ + /* Channel B */ + /*************/ + + case 2: + if (devpriv->s_ModuleInfo[b_ModulNbr]. + s_DigitalIOInfo. + b_ChannelBMode != 1) { + /*******************************************/ + /* The digital channel B is used for input */ + /*******************************************/ + + i_ReturnValue = -7; + } + break; + + default: + /****************************************/ + /* The selected digital output is wrong */ + /****************************************/ + + i_ReturnValue = -4; + break; + } + + /***********************/ + /* Test if error occur */ + /***********************/ + + if (i_ReturnValue >= 0) { + + /*********************************/ + /* Test if set channel ON */ + /*********************************/ + if (data[0]) { + /*********************************/ + /* Test if output memory enabled */ + /*********************************/ + + if (devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_DigitalIOInfo. + b_OutputMemoryEnabled == + 1) { + dw_WriteValue = + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_DigitalIOInfo. + dw_OutputMemory + | (1 << + b_OutputChannel); + + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_DigitalIOInfo. + dw_OutputMemory + = dw_WriteValue; + } else { + dw_WriteValue = + 1 << + b_OutputChannel; + } + } // set channel off + else { + if (devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_DigitalIOInfo. + b_OutputMemoryEnabled == + 1) { + dw_WriteValue = + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_DigitalIOInfo. + dw_OutputMemory + & (0xFFFFFFFFUL + - + (1 << b_OutputChannel)); + + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_DigitalIOInfo. + dw_OutputMemory + = dw_WriteValue; + } else { + /*****************************/ + /* Digital Output Memory OFF */ + /*****************************/ + // +Use previously the function "i_APCI1710_SetDigitalIOMemoryOn" + i_ReturnValue = -8; + } + + } + /*******************/ + /* Write the value */ + /*******************/ + + //OUTPDW (ps_APCI1710Variable-> + // s_Board [b_BoardHandle]. + // s_BoardInfos. + // ui_Address + (64 * b_ModulNbr), + // dw_WriteValue); + outl(dw_WriteValue, + devpriv->s_BoardInfos. + ui_Address + (64 * b_ModulNbr)); + } + } else { + /*******************************/ + /* Digital I/O not initialised */ + /*******************************/ + + i_ReturnValue = -5; + } + } else { + /******************************************/ + /* The module is not a digital I/O module */ + /******************************************/ + + i_ReturnValue = -3; + } + } else { + /***********************/ + /* Module number error */ + /***********************/ + + i_ReturnValue = -2; + } + + return (i_ReturnValue); +} + +/* ++----------------------------------------------------------------------------+ + +|INT i_APCI1710_InsnBitsDigitalIOPortOnOff(struct comedi_device *dev,comedi_subdevice + *s, struct comedi_insn *insn,unsigned int *data) ++----------------------------------------------------------------------------+ +| Task : write: + Sets or resets one or several outputs from port. | +| Setting an output means setting an output high. | +| If you have switched OFF the digital output memory | +| (OFF), all the other output are set to "0". + +| read: + Read the status from digital input port | +| from selected digital I/O module (b_ModulNbr) ++----------------------------------------------------------------------------+ +| Input Parameters : + BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr CR_AREF(aref) : Selected module number (0 to 3)| +| BYTE_ b_PortValue CR_CHAN(chanspec) : Output Value ( 0 To 7 ) +| data[0] read or write port + data[1] if write then indicate ON or OFF + + if read : data[1] will return port status. ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : + + INPUT : + + 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: The module parameter is wrong | +| -3: The module is not a digital I/O module | +| -4: Digital I/O not initialised + + OUTPUT: 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: The module parameter is wrong | +| -3: The module is not a digital I/O module | +| -4: Output value wrong | +| -5: digital I/O not initialised see function | +| " i_APCI1710_InitDigitalIO" | +| -6: The digital channel A is used for input | +| -7: The digital channel B is used for input + -8: Digital Output Memory OFF. | +| Use previously the function | +| "i_APCI1710_SetDigitalIOMemoryOn". | ++----------------------------------------------------------------------------+ +*/ + +//_INT_ i_APCI1710_SetDigitalIOPortOn (BYTE_ b_BoardHandle, +// BYTE_ b_ModulNbr, +// BYTE_ b_PortValue) +INT i_APCI1710_InsnBitsDigitalIOPortOnOff(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) +{ + INT i_ReturnValue = 0; + DWORD dw_WriteValue = 0; + DWORD dw_StatusReg; + BYTE b_ModulNbr, b_PortValue; + BYTE b_PortOperation, b_PortOnOFF; + + PBYTE pb_PortValue; + + b_ModulNbr = (BYTE) CR_AREF(insn->chanspec); + b_PortOperation = (BYTE) data[0]; // Input or output + b_PortOnOFF = (BYTE) data[1]; // if output then On or Off + b_PortValue = (BYTE) data[2]; // if out put then Value + i_ReturnValue = insn->n; + pb_PortValue = (PBYTE) & data[0]; +// if input then read value + + switch (b_PortOperation) { + case APCI1710_INPUT: + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) { + /*******************************/ + /* Test if digital I/O counter */ + /*******************************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration[b_ModulNbr] & + 0xFFFF0000UL) == APCI1710_DIGITAL_IO) { + /**********************************************/ + /* Test if the digital I/O module initialised */ + /**********************************************/ + + if (devpriv->s_ModuleInfo[b_ModulNbr]. + s_DigitalIOInfo.b_DigitalInit == 1) { + /**************************/ + /* Read all digital input */ + /**************************/ + + //INPDW (ps_APCI1710Variable-> + // s_Board [b_BoardHandle]. + // s_BoardInfos. + // ui_Address + (64 * b_ModulNbr), + // &dw_StatusReg); + + dw_StatusReg = + inl(devpriv->s_BoardInfos. + ui_Address + (64 * b_ModulNbr)); + *pb_PortValue = + (BYTE) (dw_StatusReg ^ 0x1C); + + } else { + /*******************************/ + /* Digital I/O not initialised */ + /*******************************/ + + i_ReturnValue = -4; + } + } else { + /******************************************/ + /* The module is not a digital I/O module */ + /******************************************/ + + i_ReturnValue = -3; + } + } else { + /***********************/ + /* Module number error */ + /***********************/ + + i_ReturnValue = -2; + } + + break; + + case APCI1710_OUTPUT: + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) { + /*******************************/ + /* Test if digital I/O counter */ + /*******************************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration[b_ModulNbr] & + 0xFFFF0000UL) == APCI1710_DIGITAL_IO) { + /**********************************************/ + /* Test if the digital I/O module initialised */ + /**********************************************/ + + if (devpriv->s_ModuleInfo[b_ModulNbr]. + s_DigitalIOInfo.b_DigitalInit == 1) { + /***********************/ + /* Test the port value */ + /***********************/ + + if (b_PortValue <= 7) { + /***********************************/ + /* Test the digital output channel */ + /***********************************/ + + /**************************/ + /* Test if channel A used */ + /**************************/ + + if ((b_PortValue & 2) == 2) { + if (devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_DigitalIOInfo. + b_ChannelAMode + != 1) { + /*******************************************/ + /* The digital channel A is used for input */ + /*******************************************/ + + i_ReturnValue = + -6; + } + } // if ((b_PortValue & 2) == 2) + + /**************************/ + /* Test if channel B used */ + /**************************/ + + if ((b_PortValue & 4) == 4) { + if (devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_DigitalIOInfo. + b_ChannelBMode + != 1) { + /*******************************************/ + /* The digital channel B is used for input */ + /*******************************************/ + + i_ReturnValue = + -7; + } + } // if ((b_PortValue & 4) == 4) + + /***********************/ + /* Test if error occur */ + /***********************/ + + if (i_ReturnValue >= 0) { + + //if(data[1]) + //{ + switch (b_PortOnOFF) { + /*********************************/ + /* Test if set Port ON */ + /*********************************/ + + case APCI1710_ON: + + /*********************************/ + /* Test if output memory enabled */ + /*********************************/ + + if (devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_DigitalIOInfo. + b_OutputMemoryEnabled + == 1) { + dw_WriteValue + = + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_DigitalIOInfo. + dw_OutputMemory + | + b_PortValue; + + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_DigitalIOInfo. + dw_OutputMemory + = + dw_WriteValue; + } else { + dw_WriteValue + = + b_PortValue; + } + break; + + // If Set PORT OFF + case APCI1710_OFF: + + /*********************************/ + /* Test if output memory enabled */ + /*********************************/ + + if (devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_DigitalIOInfo. + b_OutputMemoryEnabled + == 1) { + dw_WriteValue + = + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_DigitalIOInfo. + dw_OutputMemory + & + (0xFFFFFFFFUL + - + b_PortValue); + + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_DigitalIOInfo. + dw_OutputMemory + = + dw_WriteValue; + } else { + /*****************************/ + /* Digital Output Memory OFF */ + /*****************************/ + + i_ReturnValue + = + -8; + } + } // switch + + /*******************/ + /* Write the value */ + /*******************/ + + // OUTPDW (ps_APCI1710Variable-> + // s_Board [b_BoardHandle]. + // s_BoardInfos. + // ui_Address + (64 * b_ModulNbr), + // dw_WriteValue); + outl(dw_WriteValue, + devpriv-> + s_BoardInfos. + ui_Address + + (64 * b_ModulNbr)); + } + } else { + /**********************/ + /* Output value wrong */ + /**********************/ + + i_ReturnValue = -4; + } + } else { + /*******************************/ + /* Digital I/O not initialised */ + /*******************************/ + + i_ReturnValue = -5; + } + } else { + /******************************************/ + /* The module is not a digital I/O module */ + /******************************************/ + + i_ReturnValue = -3; + } + } else { + /***********************/ + /* Module number error */ + /***********************/ + + i_ReturnValue = -2; + } + break; + + default: + i_ReturnValue = -9; + DPRINTK("NO INPUT/OUTPUT specified\n"); + } //switch INPUT / OUTPUT + return (i_ReturnValue); +} diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.h new file mode 100644 index 000000000000..5ef157a55ca1 --- /dev/null +++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.h @@ -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); diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c new file mode 100644 index 000000000000..1062f2fdec30 --- /dev/null +++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c @@ -0,0 +1,5363 @@ +/** +@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 : INC_CPT.C | Version : 2.96 | + +-------------------------------+---------------------------------------+ + | Project manager: Eric Stolz | Date : 02/12/2002 | + +-----------------------------------------------------------------------+ + | Description : APCI-1710 incremental counter module | + | | + | | + +-----------------------------------------------------------------------+ + | UPDATES | + +-----------------------------------------------------------------------+ + | Date | Author | Description of updates | + +----------+-----------+------------------------------------------------+ + | | | | + |----------|-----------|------------------------------------------------| + | 08/05/00 | Guinot C | - 0400/0228 All Function in RING 0 | + | | | available | + +-----------------------------------------------------------------------+ + | 29/06/01 | Guinot C. | - 1100/0231 -> 0701/0232 | + | | | See i_APCI1710_DisableFrequencyMeasurement | + +-----------------------------------------------------------------------+ +*/ + +/* ++----------------------------------------------------------------------------+ +| Included files | ++----------------------------------------------------------------------------+ +*/ + +#include "APCI1710_INCCPT.h" + +/* ++----------------------------------------------------------------------------+ +| INT i_APCI1710_InsnConfigINCCPT(struct comedi_device *dev,struct comedi_subdevice *s, +struct comedi_insn *insn,unsigned int *data) + ++----------------------------------------------------------------------------+ +| Task : Configuration function for INC_CPT | ++----------------------------------------------------------------------------+ +| Input Parameters : | ++----------------------------------------------------------------------------+ +| Output Parameters : *data ++----------------------------------------------------------------------------+ +| Return Value : | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_InsnConfigINCCPT(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + UINT ui_ConfigType; + INT i_ReturnValue = 0; + ui_ConfigType = CR_CHAN(insn->chanspec); + + printk("\nINC_CPT"); + + devpriv->tsk_Current = current; // Save the current process task structure + switch (ui_ConfigType) { + case APCI1710_INCCPT_INITCOUNTER: + i_ReturnValue = i_APCI1710_InitCounter(dev, + CR_AREF(insn->chanspec), + (BYTE) data[0], + (BYTE) data[1], + (BYTE) data[2], (BYTE) data[3], (BYTE) data[4]); + break; + + case APCI1710_INCCPT_COUNTERAUTOTEST: + i_ReturnValue = i_APCI1710_CounterAutoTest(dev, + (PBYTE) & data[0]); + break; + + case APCI1710_INCCPT_INITINDEX: + i_ReturnValue = i_APCI1710_InitIndex(dev, + CR_AREF(insn->chanspec), + (BYTE) data[0], + (BYTE) data[1], (BYTE) data[2], (BYTE) data[3]); + break; + + case APCI1710_INCCPT_INITREFERENCE: + i_ReturnValue = i_APCI1710_InitReference(dev, + CR_AREF(insn->chanspec), (BYTE) data[0]); + break; + + case APCI1710_INCCPT_INITEXTERNALSTROBE: + i_ReturnValue = i_APCI1710_InitExternalStrobe(dev, + CR_AREF(insn->chanspec), + (BYTE) data[0], (BYTE) data[1]); + break; + + case APCI1710_INCCPT_INITCOMPARELOGIC: + i_ReturnValue = i_APCI1710_InitCompareLogic(dev, + CR_AREF(insn->chanspec), (UINT) data[0]); + break; + + case APCI1710_INCCPT_INITFREQUENCYMEASUREMENT: + i_ReturnValue = i_APCI1710_InitFrequencyMeasurement(dev, + CR_AREF(insn->chanspec), + (BYTE) data[0], + (BYTE) data[1], (ULONG) data[2], (PULONG) & data[0]); + break; + + default: + printk("Insn Config : Config Parameter Wrong\n"); + + } + + if (i_ReturnValue >= 0) + i_ReturnValue = insn->n; + return (i_ReturnValue); +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_InitCounter | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_CounterRange, | +| BYTE_ b_FirstCounterModus, | +| BYTE_ b_FirstCounterOption, | +| BYTE_ b_SecondCounterModus, | +| BYTE_ b_SecondCounterOption) | ++----------------------------------------------------------------------------+ +| Task : Configure the counter operating mode from selected | +| module (b_ModulNbr). You must calling this function be | +| for you call any other function witch access of | +| counters. | +| | +| Counter range | +| ------------- | +| +------------------------------------+-----------------------------------+ | +| | Parameter Passed value | Description | | +| |------------------------------------+-----------------------------------| | +| |b_ModulNbr APCI1710_16BIT_COUNTER | The module is configured for | | +| | | two 16-bit counter. | | +| | | - b_FirstCounterModus and | | +| | | b_FirstCounterOption | | +| | | configure the first 16 bit | | +| | | counter. | | +| | | - b_SecondCounterModus and | | +| | | b_SecondCounterOption | | +| | | configure the second 16 bit | | +| | | counter. | | +| |------------------------------------+-----------------------------------| | +| |b_ModulNbr APCI1710_32BIT_COUNTER | The module is configured for one | | +| | | 32-bit counter. | | +| | | - b_FirstCounterModus and | | +| | | b_FirstCounterOption | | +| | | configure the 32 bit counter. | | +| | | - b_SecondCounterModus and | | +| | | b_SecondCounterOption | | +| | | are not used and have no | | +| | | importance. | | +| +------------------------------------+-----------------------------------+ | +| | +| Counter operating mode | +| ---------------------- | +| | +| +--------------------+-------------------------+-------------------------+ | +| | Parameter | Passed value | Description | | +| |--------------------+-------------------------+-------------------------| | +| |b_FirstCounterModus | APCI1710_QUADRUPLE_MODE | In the quadruple mode, | | +| | or | | the edge analysis | | +| |b_SecondCounterModus| | circuit generates a | | +| | | | counting pulse from | | +| | | | each edge of 2 signals | | +| | | | which are phase shifted | | +| | | | in relation to each | | +| | | | other. | | +| |--------------------+-------------------------+-------------------------| | +| |b_FirstCounterModus | APCI1710_DOUBLE_MODE | Functions in the same | | +| | or | | way as the quadruple | | +| |b_SecondCounterModus| | mode, except that only | | +| | | | two of the four edges | | +| | | | are analysed per | | +| | | | period | | +| |--------------------+-------------------------+-------------------------| | +| |b_FirstCounterModus | APCI1710_SIMPLE_MODE | Functions in the same | | +| | or | | way as the quadruple | | +| |b_SecondCounterModus| | mode, except that only | | +| | | | one of the four edges | | +| | | | is analysed per | | +| | | | period. | | +| |--------------------+-------------------------+-------------------------| | +| |b_FirstCounterModus | APCI1710_DIRECT_MODE | In the direct mode the | | +| | or | | both edge analysis | | +| |b_SecondCounterModus| | circuits are inactive. | | +| | | | The inputs A, B in the | | +| | | | 32-bit mode or A, B and | | +| | | | C, D in the 16-bit mode | | +| | | | represent, each, one | | +| | | | clock pulse gate circuit| | +| | | | There by frequency and | | +| | | | pulse duration | | +| | | | measurements can be | | +| | | | performed. | | +| +--------------------+-------------------------+-------------------------+ | +| | +| | +| IMPORTANT! | +| If you have configured the module for two 16-bit counter, a mixed | +| mode with a counter in quadruple/double/single mode | +| and the other counter in direct mode is not possible! | +| | +| | +| Counter operating option for quadruple/double/simple mode | +| --------------------------------------------------------- | +| | +| +----------------------+-------------------------+------------------------+| +| | Parameter | Passed value | Description || +| |----------------------+-------------------------+------------------------|| +| |b_FirstCounterOption | APCI1710_HYSTERESIS_ON | In both edge analysis || +| | or | | circuits is available || +| |b_SecondCounterOption | | one hysteresis circuit.|| +| | | | It suppresses each || +| | | | time the first counting|| +| | | | pulse after a change || +| | | | of rotation. || +| |----------------------+-------------------------+------------------------|| +| |b_FirstCounterOption | APCI1710_HYSTERESIS_OFF | The first counting || +| | or | | pulse is not suppress || +| |b_SecondCounterOption | | after a change of || +| | | | rotation. || +| +----------------------+-------------------------+------------------------+| +| | +| | +| IMPORTANT! | +| This option are only avaible if you have selected the direct mode. | +| | +| | +| Counter operating option for direct mode | +| ---------------------------------------- | +| | +| +----------------------+--------------------+----------------------------+ | +| | Parameter | Passed value | Description | | +| |----------------------+--------------------+----------------------------| | +| |b_FirstCounterOption | APCI1710_INCREMENT | The counter increment for | | +| | or | | each counting pulse | | +| |b_SecondCounterOption | | | | +| |----------------------+--------------------+----------------------------| | +| |b_FirstCounterOption | APCI1710_DECREMENT | The counter decrement for | | +| | or | | each counting pulse | | +| |b_SecondCounterOption | | | | +| +----------------------+--------------------+----------------------------+ | +| | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710| +| BYTE_ b_ModulNbr : Module number to | +| configure (0 to 3) | +| BYTE_ b_CounterRange : Selection form counter | +| range. | +| BYTE_ b_FirstCounterModus : First counter operating | +| mode. | +| BYTE_ b_FirstCounterOption : First counter option. | +| BYTE_ b_SecondCounterModus : Second counter operating | +| mode. | +| BYTE_ b_SecondCounterOption : Second counter option. | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: The module is not a counter module | +| -3: The selected counter range is wrong. | +| -4: The selected first counter operating mode is wrong. | +| -5: The selected first counter operating option is wrong| +| -6: The selected second counter operating mode is wrong.| +| -7: The selected second counter operating option is | +| wrong. | ++----------------------------------------------------------------------------+ +*/ + +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_ReturnValue = 0; + + /*******************************/ + /* Test if incremental counter */ + /*******************************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF0000UL) == + APCI1710_INCREMENTAL_COUNTER) { + /**************************/ + /* Test the counter range */ + /**************************/ + + if (b_CounterRange == APCI1710_16BIT_COUNTER + || b_CounterRange == APCI1710_32BIT_COUNTER) { + /********************************/ + /* Test the first counter modus */ + /********************************/ + + if (b_FirstCounterModus == APCI1710_QUADRUPLE_MODE || + b_FirstCounterModus == APCI1710_DOUBLE_MODE || + b_FirstCounterModus == APCI1710_SIMPLE_MODE || + b_FirstCounterModus == APCI1710_DIRECT_MODE) { + /*********************************/ + /* Test the first counter option */ + /*********************************/ + + if ((b_FirstCounterModus == APCI1710_DIRECT_MODE + && (b_FirstCounterOption == + APCI1710_INCREMENT + || b_FirstCounterOption + == APCI1710_DECREMENT)) + || (b_FirstCounterModus != + APCI1710_DIRECT_MODE + && (b_FirstCounterOption == + APCI1710_HYSTERESIS_ON + || b_FirstCounterOption + == + APCI1710_HYSTERESIS_OFF))) + { + /**************************/ + /* Test if 16-bit counter */ + /**************************/ + + if (b_CounterRange == + APCI1710_16BIT_COUNTER) { + /*********************************/ + /* Test the second counter modus */ + /*********************************/ + + if ((b_FirstCounterModus != + APCI1710_DIRECT_MODE + && + (b_SecondCounterModus + == + APCI1710_QUADRUPLE_MODE + || + b_SecondCounterModus + == + APCI1710_DOUBLE_MODE + || + b_SecondCounterModus + == + APCI1710_SIMPLE_MODE)) + || (b_FirstCounterModus + == + APCI1710_DIRECT_MODE + && + b_SecondCounterModus + == + APCI1710_DIRECT_MODE)) + { + /**********************************/ + /* Test the second counter option */ + /**********************************/ + + if ((b_SecondCounterModus == APCI1710_DIRECT_MODE && (b_SecondCounterOption == APCI1710_INCREMENT || b_SecondCounterOption == APCI1710_DECREMENT)) || (b_SecondCounterModus != APCI1710_DIRECT_MODE && (b_SecondCounterOption == APCI1710_HYSTERESIS_ON || b_SecondCounterOption == APCI1710_HYSTERESIS_OFF))) { + i_ReturnValue = + 0; + } else { + /*********************************************************/ + /* The selected second counter operating option is wrong */ + /*********************************************************/ + + DPRINTK("The selected second counter operating option is wrong\n"); + i_ReturnValue = + -7; + } + } else { + /*******************************************************/ + /* The selected second counter operating mode is wrong */ + /*******************************************************/ + + DPRINTK("The selected second counter operating mode is wrong\n"); + i_ReturnValue = -6; + } + } + } else { + /********************************************************/ + /* The selected first counter operating option is wrong */ + /********************************************************/ + + DPRINTK("The selected first counter operating option is wrong\n"); + i_ReturnValue = -5; + } + } else { + /******************************************************/ + /* The selected first counter operating mode is wrong */ + /******************************************************/ + DPRINTK("The selected first counter operating mode is wrong\n"); + i_ReturnValue = -4; + } + } else { + /***************************************/ + /* The selected counter range is wrong */ + /***************************************/ + + DPRINTK("The selected counter range is wrong\n"); + i_ReturnValue = -3; + } + + /*************************/ + /* Test if a error occur */ + /*************************/ + + if (i_ReturnValue == 0) { + /**************************/ + /* Test if 16-Bit counter */ + /**************************/ + + if (b_CounterRange == APCI1710_32BIT_COUNTER) { + devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister1 = b_CounterRange | + b_FirstCounterModus | + b_FirstCounterOption; + } else { + devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister1 = b_CounterRange | + (b_FirstCounterModus & 0x5) | + (b_FirstCounterOption & 0x20) | |